UNPKG

ng-cw-v12

Version:

Angular UI Component Library

407 lines (381 loc) 17.4 kB
import * as i0 from '@angular/core'; import { Component, ViewChild, Input, HostListener, NgModule } from '@angular/core'; import * as THREE from 'three'; import { CommonModule } from '@angular/common'; const vertexShader = ` varying vec2 vUv; void main() { vUv = uv; gl_Position = vec4(position, 1.0); } `; const fragmentShader = ` precision highp float; uniform float uTime; uniform vec3 uResolution; uniform float uSpeed; uniform float uScale; uniform float uBrightness; uniform vec3 uColor1; uniform vec3 uColor2; uniform float uNoiseFreq; uniform float uNoiseAmp; uniform float uBandHeight; uniform float uBandSpread; uniform float uOctaveDecay; uniform float uLayerOffset; uniform float uColorSpeed; uniform vec2 uMouse; uniform float uMouseInfluence; uniform bool uEnableMouse; #define TAU 6.28318 vec3 gradientHash(vec3 p) { p = vec3( dot(p, vec3(127.1, 311.7, 234.6)), dot(p, vec3(269.5, 183.3, 198.3)), dot(p, vec3(169.5, 283.3, 156.9)) ); vec3 h = fract(sin(p) * 43758.5453123); float phi = acos(2.0 * h.x - 1.0); float theta = TAU * h.y; return vec3(cos(theta) * sin(phi), sin(theta) * cos(phi), cos(phi)); } float quinticSmooth(float t) { float t2 = t * t; float t3 = t * t2; return 6.0 * t3 * t2 - 15.0 * t2 * t2 + 10.0 * t3; } vec3 cosineGradient(float t, vec3 a, vec3 b, vec3 c, vec3 d) { return a + b * cos(TAU * (c * t + d)); } float perlin3D(float amplitude, float frequency, float px, float py, float pz) { float x = px * frequency; float y = py * frequency; float fx = floor(x); float fy = floor(y); float fz = floor(pz); float cx = ceil(x); float cy = ceil(y); float cz = ceil(pz); vec3 g000 = gradientHash(vec3(fx, fy, fz)); vec3 g100 = gradientHash(vec3(cx, fy, fz)); vec3 g010 = gradientHash(vec3(fx, cy, fz)); vec3 g110 = gradientHash(vec3(cx, cy, fz)); vec3 g001 = gradientHash(vec3(fx, fy, cz)); vec3 g101 = gradientHash(vec3(cx, fy, cz)); vec3 g011 = gradientHash(vec3(fx, cy, cz)); vec3 g111 = gradientHash(vec3(cx, cy, cz)); float d000 = dot(g000, vec3(x - fx, y - fy, pz - fz)); float d100 = dot(g100, vec3(x - cx, y - fy, pz - fz)); float d010 = dot(g010, vec3(x - fx, y - cy, pz - fz)); float d110 = dot(g110, vec3(x - cx, y - cy, pz - fz)); float d001 = dot(g001, vec3(x - fx, y - fy, pz - cz)); float d101 = dot(g101, vec3(x - cx, y - fy, pz - cz)); float d011 = dot(g011, vec3(x - fx, y - cy, pz - cz)); float d111 = dot(g111, vec3(x - cx, y - cy, pz - cz)); float sx = quinticSmooth(x - fx); float sy = quinticSmooth(y - fy); float sz = quinticSmooth(pz - fz); float lx00 = mix(d000, d100, sx); float lx10 = mix(d010, d110, sx); float lx01 = mix(d001, d101, sx); float lx11 = mix(d011, d111, sx); float ly0 = mix(lx00, lx10, sy); float ly1 = mix(lx01, lx11, sy); return amplitude * mix(ly0, ly1, sz); } float auroraGlow(float t, vec2 shift) { vec2 uv = gl_FragCoord.xy / uResolution.y; uv += shift; float noiseVal = 0.0; float freq = uNoiseFreq; float amp = uNoiseAmp; vec2 samplePos = uv * uScale; for (float i = 0.0; i < 3.0; i += 1.0) { noiseVal += perlin3D(amp, freq, samplePos.x, samplePos.y, t); amp *= uOctaveDecay; freq *= 2.0; } float yBand = uv.y * 10.0 - uBandHeight * 10.0; return 0.3 * max(exp(uBandSpread * (1.0 - 1.1 * abs(noiseVal + yBand))), 0.0); } void main() { vec2 uv = gl_FragCoord.xy / uResolution.xy; float t = uSpeed * 0.4 * uTime; vec2 shift = vec2(0.0); if (uEnableMouse) { shift = (uMouse - 0.5) * uMouseInfluence; } vec3 col = vec3(0.0); col += 0.99 * auroraGlow(t, shift) * cosineGradient(uv.x + uTime * uSpeed * 0.2 * uColorSpeed, vec3(0.5), vec3(0.5), vec3(1.0), vec3(0.3, 0.20, 0.20)) * uColor1; col += 0.99 * auroraGlow(t + uLayerOffset, shift) * cosineGradient(uv.x + uTime * uSpeed * 0.1 * uColorSpeed, vec3(0.5), vec3(0.5), vec3(2.0, 1.0, 0.0), vec3(0.5, 0.20, 0.25)) * uColor2; col *= uBrightness; float alpha = clamp(length(col), 0.0, 1.0); gl_FragColor = vec4(col, alpha); } `; class SoftAuroraBackgroundComponent { constructor(ngZone) { this.ngZone = ngZone; /** 播放速度(0.1-5) */ this.ncSpeed = 0.6; /** 缩放比例(0.1-3) */ this.ncScale = 1.5; /** 亮度(0.1-3) */ this.ncBrightness = 1.0; /** 光晕颜色1 */ this.ncColor1 = '#f7f7f7'; /** 光晕颜色2 */ this.ncColor2 = '#e100ff'; /** 噪声频率(0.5-10) */ this.ncNoiseFrequency = 2.5; /** 噪声幅度(0.5-10) */ this.ncNoiseAmplitude = 1.0; /** 色带高度位置(0-1) */ this.ncBandHeight = 0.5; /** 色带扩展程度(0.1-3) */ this.ncBandSpread = 1.0; /** 噪声每层的衰减量(0.01-0.5) */ this.ncOctaveDecay = 0.1; /** 两层极光之间的时间差(0-1) */ this.ncLayerOffset = 0; /** 颜色渐变速度(0.1-5) */ this.ncColorSpeed = 1.0; /** 鼠标事件的影响力(0.1-1) */ this.ncMouseInfluence = 0.25; /** 是否启用鼠标交互 */ this._enableMouseInteraction = true; this.animationFrameId = null; this.targetMouse = [0.5, 0.5]; this.currentMouse = [0.5, 0.5]; this.timeOffset = 0; this.lastTime = 0; this.animate = () => { this.animationFrameId = requestAnimationFrame(this.animate); const currentTime = performance.now(); this.timeOffset += (currentTime - this.lastTime); this.lastTime = currentTime; if (this.material) { this.material.uniforms['uTime'].value = this.timeOffset * 0.001; if (this.ncEnableMouseInteraction) { this.currentMouse[0] += 0.05 * (this.targetMouse[0] - this.currentMouse[0]); this.currentMouse[1] += 0.05 * (this.targetMouse[1] - this.currentMouse[1]); this.material.uniforms['uMouse'].value.set(this.currentMouse[0], this.currentMouse[1]); } else { this.material.uniforms['uMouse'].value.set(0.5, 0.5); } this.renderer.render(this.scene, this.camera); } }; } set ncEnableMouseInteraction(val) { this._enableMouseInteraction = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncEnableMouseInteraction() { return this._enableMouseInteraction; } ngOnInit() { } ngAfterViewInit() { this.ngZone.runOutsideAngular(() => { this.initThreeJS(); }); } ngOnDestroy() { this.cleanup(); } ngOnChanges(changes) { if (!this.material) return; if (changes['ncSpeed']) this.material.uniforms['uSpeed'].value = this.ncSpeed; if (changes['ncScale']) this.material.uniforms['uScale'].value = this.ncScale; if (changes['ncBrightness']) this.material.uniforms['uBrightness'].value = this.ncBrightness; if (changes['ncColor1']) this.material.uniforms['uColor1'].value.set(this.ncColor1); if (changes['ncColor2']) this.material.uniforms['uColor2'].value.set(this.ncColor2); if (changes['ncNoiseFrequency']) this.material.uniforms['uNoiseFreq'].value = this.ncNoiseFrequency; if (changes['ncNoiseAmplitude']) this.material.uniforms['uNoiseAmp'].value = this.ncNoiseAmplitude; if (changes['ncBandHeight']) this.material.uniforms['uBandHeight'].value = this.ncBandHeight; if (changes['ncBandSpread']) this.material.uniforms['uBandSpread'].value = this.ncBandSpread; if (changes['ncOctaveDecay']) this.material.uniforms['uOctaveDecay'].value = this.ncOctaveDecay; if (changes['ncLayerOffset']) this.material.uniforms['uLayerOffset'].value = this.ncLayerOffset; if (changes['ncColorSpeed']) this.material.uniforms['uColorSpeed'].value = this.ncColorSpeed; if (changes['ncMouseInfluence']) this.material.uniforms['uMouseInfluence'].value = this.ncMouseInfluence; if (changes['ncEnableMouseInteraction']) this.material.uniforms['uEnableMouse'].value = this.ncEnableMouseInteraction; } onMouseMove(e) { if (!this.ncEnableMouseInteraction || !this.renderer) return; const canvas = this.renderer.domElement; const rect = canvas.getBoundingClientRect(); if (rect.width === 0 || rect.height === 0) return; this.targetMouse = [ (e.clientX - rect.left) / rect.width, 1.0 - (e.clientY - rect.top) / rect.height ]; } onMouseLeave() { if (!this.ncEnableMouseInteraction) return; this.targetMouse = [0.5, 0.5]; } initThreeJS() { const container = this.containerRef.nativeElement; this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: false, premultipliedAlpha: false }); this.renderer.setClearColor(0x000000, 0); // transparent background this.scene = new THREE.Scene(); this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); this.material = new THREE.ShaderMaterial({ vertexShader, fragmentShader, transparent: true, uniforms: { uTime: { value: 0 }, uResolution: { value: new THREE.Vector3() }, uSpeed: { value: this.ncSpeed }, uScale: { value: this.ncScale }, uBrightness: { value: this.ncBrightness }, uColor1: { value: new THREE.Color(this.ncColor1) }, uColor2: { value: new THREE.Color(this.ncColor2) }, uNoiseFreq: { value: this.ncNoiseFrequency }, uNoiseAmp: { value: this.ncNoiseAmplitude }, uBandHeight: { value: this.ncBandHeight }, uBandSpread: { value: this.ncBandSpread }, uOctaveDecay: { value: this.ncOctaveDecay }, uLayerOffset: { value: this.ncLayerOffset }, uColorSpeed: { value: this.ncColorSpeed }, uMouse: { value: new THREE.Vector2(0.5, 0.5) }, uMouseInfluence: { value: this.ncMouseInfluence }, uEnableMouse: { value: this.ncEnableMouseInteraction } } }); const geometry = new THREE.PlaneGeometry(2, 2); this.mesh = new THREE.Mesh(geometry, this.material); this.scene.add(this.mesh); container.appendChild(this.renderer.domElement); this.resizeObserver = new ResizeObserver(() => this.resize()); this.resizeObserver.observe(container); this.resize(); this.lastTime = performance.now(); this.animate(); } resize() { if (!this.containerRef || !this.renderer) return; const container = this.containerRef.nativeElement; const width = container.offsetWidth; const height = container.offsetHeight; if (width === 0 || height === 0) return; this.renderer.setSize(width, height); if (this.material) { this.material.uniforms['uResolution'].value.set(width, height, width / height); } } cleanup() { if (this.animationFrameId !== null) { cancelAnimationFrame(this.animationFrameId); this.animationFrameId = null; } if (this.resizeObserver) { this.resizeObserver.disconnect(); } if (this.renderer && this.containerRef) { const container = this.containerRef.nativeElement; if (container.contains(this.renderer.domElement)) { container.removeChild(this.renderer.domElement); } this.renderer.dispose(); this.renderer.forceContextLoss(); } if (this.mesh) { if (this.mesh.geometry) this.mesh.geometry.dispose(); if (this.material) this.material.dispose(); } } } SoftAuroraBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: SoftAuroraBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); SoftAuroraBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: SoftAuroraBackgroundComponent, selector: "nc-soft-aurora-background", inputs: { ncSpeed: "ncSpeed", ncScale: "ncScale", ncBrightness: "ncBrightness", ncColor1: "ncColor1", ncColor2: "ncColor2", ncNoiseFrequency: "ncNoiseFrequency", ncNoiseAmplitude: "ncNoiseAmplitude", ncBandHeight: "ncBandHeight", ncBandSpread: "ncBandSpread", ncOctaveDecay: "ncOctaveDecay", ncLayerOffset: "ncLayerOffset", ncColorSpeed: "ncColorSpeed", ncMouseInfluence: "ncMouseInfluence", ncEnableMouseInteraction: "ncEnableMouseInteraction" }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseleave": "onMouseLeave()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-soft-aurora-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-soft-aurora-canvas-container{position:absolute;inset:0;z-index:0;width:100%;height:100%;background-color:#000}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: SoftAuroraBackgroundComponent, decorators: [{ type: Component, args: [{ selector: 'nc-soft-aurora-background', templateUrl: './soft-aurora-background.component.html', styleUrls: ['./soft-aurora-background.component.less'] }] }], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{ type: ViewChild, args: ['container', { static: true }] }], ncSpeed: [{ type: Input }], ncScale: [{ type: Input }], ncBrightness: [{ type: Input }], ncColor1: [{ type: Input }], ncColor2: [{ type: Input }], ncNoiseFrequency: [{ type: Input }], ncNoiseAmplitude: [{ type: Input }], ncBandHeight: [{ type: Input }], ncBandSpread: [{ type: Input }], ncOctaveDecay: [{ type: Input }], ncLayerOffset: [{ type: Input }], ncColorSpeed: [{ type: Input }], ncMouseInfluence: [{ type: Input }], ncEnableMouseInteraction: [{ type: Input }], onMouseMove: [{ type: HostListener, args: ['mousemove', ['$event']] }], onMouseLeave: [{ type: HostListener, args: ['mouseleave'] }] } }); class NcSoftAuroraBackgroundModule { } NcSoftAuroraBackgroundModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcSoftAuroraBackgroundModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); NcSoftAuroraBackgroundModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcSoftAuroraBackgroundModule, declarations: [SoftAuroraBackgroundComponent], imports: [CommonModule], exports: [SoftAuroraBackgroundComponent] }); NcSoftAuroraBackgroundModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcSoftAuroraBackgroundModule, imports: [[ CommonModule ]] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcSoftAuroraBackgroundModule, decorators: [{ type: NgModule, args: [{ declarations: [ SoftAuroraBackgroundComponent ], imports: [ CommonModule ], exports: [ SoftAuroraBackgroundComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { NcSoftAuroraBackgroundModule, SoftAuroraBackgroundComponent }; //# sourceMappingURL=ng-cw-v12-soft-aurora-background.js.map