ng-cw-v12
Version:
Angular UI Component Library
359 lines (350 loc) • 21.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('three'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define('ng-cw-v12/ripple-grid-background', ['exports', '@angular/core', 'three', '@angular/common'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global["ng-cw-v12"] = global["ng-cw-v12"] || {}, global["ng-cw-v12"]["ripple-grid-background"] = {}), global.ng.core, global.THREE, global.ng.common));
})(this, (function (exports, i0, THREE, common) { 'use strict';
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var i0__namespace = /*#__PURE__*/_interopNamespace(i0);
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
var vert = "\n attribute vec3 position;\n varying vec2 vUv;\n void main() {\n vUv = position.xy * 0.5 + 0.5;\n gl_Position = vec4(position, 1.0);\n }\n";
var frag = "\n precision highp float;\n uniform float iTime;\n uniform vec2 iResolution;\n uniform bool enableRainbow;\n uniform vec3 gridColor;\n uniform float rippleIntensity;\n uniform float gridSize;\n uniform float gridThickness;\n uniform float fadeDistance;\n uniform float vignetteStrength;\n uniform float glowIntensity;\n uniform float opacity;\n uniform float gridRotation;\n uniform bool mouseInteraction;\n uniform vec2 mousePosition;\n uniform float mouseInfluence;\n uniform float mouseInteractionRadius;\n varying vec2 vUv;\n\n float pi = 3.141592;\n\n mat2 rotate(float angle) {\n float s = sin(angle);\n float c = cos(angle);\n return mat2(c, -s, s, c);\n }\n\n void main() {\n vec2 uv = vUv * 2.0 - 1.0;\n uv.x *= iResolution.x / iResolution.y;\n\n if (gridRotation != 0.0) {\n uv = rotate(gridRotation * pi / 180.0) * uv;\n }\n\n float dist = length(uv);\n float func = sin(pi * (iTime - dist));\n vec2 rippleUv = uv + uv * func * rippleIntensity;\n\n if (mouseInteraction && mouseInfluence > 0.0) {\n vec2 mouseUv = (mousePosition * 2.0 - 1.0);\n mouseUv.x *= iResolution.x / iResolution.y;\n float mouseDist = length(uv - mouseUv);\n \n float influence = mouseInfluence * exp(-mouseDist * mouseDist / (mouseInteractionRadius * mouseInteractionRadius));\n \n float mouseWave = sin(pi * (iTime * 2.0 - mouseDist * 3.0)) * influence;\n rippleUv += normalize(uv - mouseUv) * mouseWave * rippleIntensity * 0.3;\n }\n\n vec2 a = sin(gridSize * 0.5 * pi * rippleUv - pi / 2.0);\n vec2 b = abs(a);\n\n float aaWidth = 0.5;\n vec2 smoothB = vec2(\n smoothstep(0.0, aaWidth, b.x),\n smoothstep(0.0, aaWidth, b.y)\n );\n\n vec3 color = vec3(0.0);\n color += exp(-gridThickness * smoothB.x * (0.8 + 0.5 * sin(pi * iTime)));\n color += exp(-gridThickness * smoothB.y);\n color += 0.5 * exp(-(gridThickness / 4.0) * sin(smoothB.x));\n color += 0.5 * exp(-(gridThickness / 3.0) * smoothB.y);\n\n if (glowIntensity > 0.0) {\n color += glowIntensity * exp(-gridThickness * 0.5 * smoothB.x);\n color += glowIntensity * exp(-gridThickness * 0.5 * smoothB.y);\n }\n\n float ddd = exp(-2.0 * clamp(pow(dist, fadeDistance), 0.0, 1.0));\n \n vec2 vignetteCoords = vUv - 0.5;\n float vignetteDistance = length(vignetteCoords);\n float vignette = 1.0 - pow(vignetteDistance * 2.0, vignetteStrength);\n vignette = clamp(vignette, 0.0, 1.0);\n \n vec3 t;\n if (enableRainbow) {\n t = vec3(\n uv.x * 0.5 + 0.5 * sin(iTime),\n uv.y * 0.5 + 0.5 * cos(iTime),\n pow(cos(iTime), 4.0)\n ) + 0.5;\n } else {\n t = gridColor;\n }\n\n float finalFade = ddd * vignette;\n float alpha = length(color) * finalFade * opacity;\n gl_FragColor = vec4(color * t * finalFade * opacity, alpha);\n }\n";
var RippleGridBackgroundComponent = /** @class */ (function () {
function RippleGridBackgroundComponent(ngZone) {
this.ngZone = ngZone;
/** 彩虹模式关闭时网格的颜色 */
this.ncGridColor = '#5227ff';
/** 控制中心波纹效应的强度(0-0.3)*/
this.ncRippleIntensity = 0.05;
/** 控制网格图案的密度/大小(5-30)*/
this.ncGridSize = 10.0;
/** 控制网格线的粗细(5-50)*/
this.ncGridThickness = 15.0;
/** 控制淡入淡出效果从中心向外延伸的距离(0.5-3)*/
this.ncFadeDistance = 1.5;
/** 控制暗角(边缘变暗)效果的强度(0.5-5)*/
this.ncVignetteStrength = 2.0;
/** 为网格线添加发光效果(0-1)*/
this.ncGlowIntensity = 0.1;
/** 整体效果的不透明度(0-1)*/
this.ncOpacity = 1.0;
/** 将整个网格图案旋转一定角度(0-360)*/
this.ncGridRotation = 0;
/** 启用鼠标/触摸交互以产生涟漪效 */
this._mouseInteraction = true;
/** 控制鼠标交互效果的半径(0.2-2)*/
this.ncMouseInteractionRadius = 1;
/** 为网格启用彩虹色循环动画 */
this._enableRainbow = false;
this.rafId = null;
this.resizeRafId = null;
this.isVisible = true;
this.isDestroyed = false;
this.clock = new THREE__namespace.Clock();
this.mousePosition = new THREE__namespace.Vector2(0.5, 0.5);
this.targetMouse = new THREE__namespace.Vector2(0.5, 0.5);
this.targetInfluence = 0;
}
Object.defineProperty(RippleGridBackgroundComponent.prototype, "ncMouseInteraction", {
get: function () {
return this._mouseInteraction;
},
set: function (val) {
this._mouseInteraction = val !== null && val !== undefined && val !== false && val !== 'false';
},
enumerable: false,
configurable: true
});
Object.defineProperty(RippleGridBackgroundComponent.prototype, "ncEnableRainbow", {
get: function () {
return this._enableRainbow;
},
set: function (val) {
this._enableRainbow = val !== null && val !== undefined && val !== false && val !== 'false';
},
enumerable: false,
configurable: true
});
RippleGridBackgroundComponent.prototype.ngOnInit = function () { };
RippleGridBackgroundComponent.prototype.ngAfterViewInit = function () {
var _this = this;
this.initWebGL();
this.setupResizeObserver();
this.setupIntersectionObserver();
this.ngZone.runOutsideAngular(function () {
_this.startAnimation();
});
};
RippleGridBackgroundComponent.prototype.ngOnDestroy = function () {
this.isDestroyed = true;
this.cleanup();
};
RippleGridBackgroundComponent.prototype.ngOnChanges = function (changes) {
if (!this.material)
return;
this.updateUniforms();
};
RippleGridBackgroundComponent.prototype.hexToRgb = function (hex) {
var cleanHex = hex;
if (cleanHex.startsWith('#')) {
cleanHex = cleanHex.slice(1);
}
var result = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(cleanHex);
return result
? new THREE__namespace.Vector3(parseInt(result[1], 16) / 255, parseInt(result[2], 16) / 255, parseInt(result[3], 16) / 255)
: new THREE__namespace.Vector3(1, 1, 1);
};
RippleGridBackgroundComponent.prototype.updateUniforms = function () {
if (!this.material)
return;
var u = this.material.uniforms;
u.enableRainbow.value = this.ncEnableRainbow;
u.gridColor.value.copy(this.hexToRgb(this.ncGridColor));
u.rippleIntensity.value = this.ncRippleIntensity;
u.gridSize.value = this.ncGridSize;
u.gridThickness.value = this.ncGridThickness;
u.fadeDistance.value = this.ncFadeDistance;
u.vignetteStrength.value = this.ncVignetteStrength;
u.glowIntensity.value = this.ncGlowIntensity;
u.opacity.value = this.ncOpacity;
u.gridRotation.value = this.ncGridRotation;
u.mouseInteraction.value = this.ncMouseInteraction;
u.mouseInteractionRadius.value = this.ncMouseInteractionRadius;
};
RippleGridBackgroundComponent.prototype.initWebGL = function () {
var el = this.containerRef.nativeElement;
this.renderer = new THREE__namespace.WebGLRenderer({
alpha: true,
antialias: true,
powerPreference: 'high-performance'
});
var dpr = Math.min(window.devicePixelRatio, 2);
this.renderer.setPixelRatio(dpr);
this.renderer.setSize(el.offsetWidth, el.offsetHeight);
el.appendChild(this.renderer.domElement);
this.scene = new THREE__namespace.Scene();
// The camera doesn't matter much as we use RawShaderMaterial that sets gl_Position directly
this.camera = new THREE__namespace.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
this.camera.position.z = 1;
var geometry = new THREE__namespace.PlaneGeometry(2, 2);
this.material = new THREE__namespace.RawShaderMaterial({
vertexShader: vert,
fragmentShader: frag,
uniforms: {
iTime: { value: 0 },
iResolution: { value: new THREE__namespace.Vector2(el.offsetWidth, el.offsetHeight) },
enableRainbow: { value: this.ncEnableRainbow },
gridColor: { value: this.hexToRgb(this.ncGridColor) },
rippleIntensity: { value: this.ncRippleIntensity },
gridSize: { value: this.ncGridSize },
gridThickness: { value: this.ncGridThickness },
fadeDistance: { value: this.ncFadeDistance },
vignetteStrength: { value: this.ncVignetteStrength },
glowIntensity: { value: this.ncGlowIntensity },
opacity: { value: this.ncOpacity },
gridRotation: { value: this.ncGridRotation },
mouseInteraction: { value: this.ncMouseInteraction },
mousePosition: { value: new THREE__namespace.Vector2(0.5, 0.5) },
mouseInfluence: { value: 0 },
mouseInteractionRadius: { value: this.ncMouseInteractionRadius }
},
blending: THREE__namespace.NormalBlending,
transparent: true,
depthTest: false,
depthWrite: false
});
this.mesh = new THREE__namespace.Mesh(geometry, this.material);
this.scene.add(this.mesh);
this.clock.start();
};
RippleGridBackgroundComponent.prototype.onMouseMove = function (e) {
if (!this.ncMouseInteraction || !this.containerRef)
return;
var rect = this.containerRef.nativeElement.getBoundingClientRect();
var x = (e.clientX - rect.left) / rect.width;
var y = 1.0 - (e.clientY - rect.top) / rect.height; // Flip Y coordinate
this.targetMouse.set(x, y);
};
RippleGridBackgroundComponent.prototype.onMouseEnter = function () {
if (!this.ncMouseInteraction)
return;
this.targetInfluence = 1.0;
};
RippleGridBackgroundComponent.prototype.onMouseLeave = function () {
if (!this.ncMouseInteraction)
return;
this.targetInfluence = 0.0;
};
RippleGridBackgroundComponent.prototype.setupResizeObserver = function () {
var _this = this;
var el = this.containerRef.nativeElement;
this.resizeObserver = new ResizeObserver(function () {
if (_this.resizeRafId !== null)
cancelAnimationFrame(_this.resizeRafId);
_this.ngZone.runOutsideAngular(function () {
_this.resizeRafId = requestAnimationFrame(function () {
if (!_this.renderer || !el)
return;
var w = el.offsetWidth || 1;
var h = el.offsetHeight || 1;
_this.renderer.setSize(w, h);
if (_this.material) {
_this.material.uniforms.iResolution.value.set(w, h);
}
_this.resizeRafId = null;
});
});
});
this.resizeObserver.observe(el);
};
RippleGridBackgroundComponent.prototype.setupIntersectionObserver = function () {
var _this = this;
var el = this.containerRef.nativeElement;
this.intersectionObserver = new IntersectionObserver(function (entries) {
_this.isVisible = entries[0].isIntersecting;
if (_this.isVisible) {
if (_this.rafId === null) {
_this.ngZone.runOutsideAngular(function () {
_this.startAnimation();
});
}
}
}, { threshold: [0, 0.01, 0.1] });
this.intersectionObserver.observe(el);
};
RippleGridBackgroundComponent.prototype.startAnimation = function () {
var _this = this;
if (this.isDestroyed)
return;
var render = function () {
if (!_this.isVisible) {
_this.rafId = null;
return;
}
_this.rafId = requestAnimationFrame(render);
var t = _this.clock.getElapsedTime();
if (_this.material) {
_this.material.uniforms.iTime.value = t;
// Mouse smoothing
var lerpFactor = 0.1;
_this.mousePosition.x += (_this.targetMouse.x - _this.mousePosition.x) * lerpFactor;
_this.mousePosition.y += (_this.targetMouse.y - _this.mousePosition.y) * lerpFactor;
var currentInfluence = _this.material.uniforms.mouseInfluence.value;
_this.material.uniforms.mouseInfluence.value += (_this.targetInfluence - currentInfluence) * 0.05;
_this.material.uniforms.mousePosition.value.copy(_this.mousePosition);
}
_this.renderer.render(_this.scene, _this.camera);
};
render();
};
RippleGridBackgroundComponent.prototype.cleanup = function () {
var _a, _b, _c;
if (this.rafId !== null)
cancelAnimationFrame(this.rafId);
if (this.resizeRafId !== null)
cancelAnimationFrame(this.resizeRafId);
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
(_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
if (this.renderer) {
var el = (_c = this.containerRef) === null || _c === void 0 ? void 0 : _c.nativeElement;
if (el && this.renderer.domElement.parentNode === el) {
el.removeChild(this.renderer.domElement);
}
this.renderer.dispose();
}
};
return RippleGridBackgroundComponent;
}());
RippleGridBackgroundComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: RippleGridBackgroundComponent, deps: [{ token: i0__namespace.NgZone }], target: i0__namespace.ɵɵFactoryTarget.Component });
RippleGridBackgroundComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: RippleGridBackgroundComponent, selector: "nc-ripple-grid-background", inputs: { ncGridColor: "ncGridColor", ncRippleIntensity: "ncRippleIntensity", ncGridSize: "ncGridSize", ncGridThickness: "ncGridThickness", ncFadeDistance: "ncFadeDistance", ncVignetteStrength: "ncVignetteStrength", ncGlowIntensity: "ncGlowIntensity", ncOpacity: "ncOpacity", ncGridRotation: "ncGridRotation", ncMouseInteraction: "ncMouseInteraction", ncMouseInteractionRadius: "ncMouseInteractionRadius", ncEnableRainbow: "ncEnableRainbow" }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0__namespace, template: "<div #container class=\"nc-ripple-grid-canvas-container\"></div>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-ripple-grid-canvas-container{position:absolute;inset:0;z-index:0;background-color:#000}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] });
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: RippleGridBackgroundComponent, decorators: [{
type: i0.Component,
args: [{
selector: 'nc-ripple-grid-background',
templateUrl: './ripple-grid-background.component.html',
styleUrls: ['./ripple-grid-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0__namespace.NgZone }]; }, propDecorators: { containerRef: [{
type: i0.ViewChild,
args: ['container', { static: true }]
}], ncGridColor: [{
type: i0.Input
}], ncRippleIntensity: [{
type: i0.Input
}], ncGridSize: [{
type: i0.Input
}], ncGridThickness: [{
type: i0.Input
}], ncFadeDistance: [{
type: i0.Input
}], ncVignetteStrength: [{
type: i0.Input
}], ncGlowIntensity: [{
type: i0.Input
}], ncOpacity: [{
type: i0.Input
}], ncGridRotation: [{
type: i0.Input
}], ncMouseInteraction: [{
type: i0.Input
}], ncMouseInteractionRadius: [{
type: i0.Input
}], ncEnableRainbow: [{
type: i0.Input
}], onMouseMove: [{
type: i0.HostListener,
args: ['mousemove', ['$event']]
}], onMouseEnter: [{
type: i0.HostListener,
args: ['mouseenter']
}], onMouseLeave: [{
type: i0.HostListener,
args: ['mouseleave']
}] } });
var NcRippleGridBackgroundModule = /** @class */ (function () {
function NcRippleGridBackgroundModule() {
}
return NcRippleGridBackgroundModule;
}());
NcRippleGridBackgroundModule.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcRippleGridBackgroundModule, deps: [], target: i0__namespace.ɵɵFactoryTarget.NgModule });
NcRippleGridBackgroundModule.ɵmod = i0__namespace.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcRippleGridBackgroundModule, declarations: [RippleGridBackgroundComponent], imports: [common.CommonModule], exports: [RippleGridBackgroundComponent] });
NcRippleGridBackgroundModule.ɵinj = i0__namespace.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcRippleGridBackgroundModule, imports: [[
common.CommonModule
]] });
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcRippleGridBackgroundModule, decorators: [{
type: i0.NgModule,
args: [{
declarations: [
RippleGridBackgroundComponent
],
imports: [
common.CommonModule
],
exports: [
RippleGridBackgroundComponent
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
exports.NcRippleGridBackgroundModule = NcRippleGridBackgroundModule;
exports.RippleGridBackgroundComponent = RippleGridBackgroundComponent;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=ng-cw-v12-ripple-grid-background.umd.js.map