UNPKG

ng-cw-v12

Version:

Angular UI Component Library

359 lines (350 loc) 21.7 kB
(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