ng-cw-v12
Version:
Angular UI Component Library
471 lines (438 loc) • 19.5 kB
JavaScript
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 = `
precision highp float;
attribute vec3 position;
attribute vec2 uv;
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 vec2 uFocal;
uniform vec2 uRotation;
uniform float uStarSpeed;
uniform float uDensity;
uniform float uHueShift;
uniform float uSpeed;
uniform vec2 uMouse;
uniform float uGlowIntensity;
uniform float uSaturation;
uniform bool uMouseRepulsion;
uniform float uTwinkleIntensity;
uniform float uRotationSpeed;
uniform float uRepulsionStrength;
uniform float uMouseActiveFactor;
uniform float uAutoCenterRepulsion;
varying vec2 vUv;
#define NUM_LAYER 4.0
#define STAR_COLOR_CUTOFF 0.2
#define MAT45 mat2(0.7071, -0.7071, 0.7071, 0.7071)
#define PERIOD 3.0
float Hash21(vec2 p) {
p = fract(p * vec2(123.34, 456.21));
p += dot(p, p + 45.32);
return fract(p.x * p.y);
}
float tri(float x) {
return abs(fract(x) * 2.0 - 1.0);
}
float tris(float x) {
float t = fract(x);
return 1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0));
}
float trisn(float x) {
float t = fract(x);
return 2.0 * (1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0))) - 1.0;
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
float Star(vec2 uv, float flare) {
float d = length(uv);
float m = (0.05 * uGlowIntensity) / d;
float rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));
m += rays * flare * uGlowIntensity;
uv *= MAT45;
rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));
m += rays * 0.3 * flare * uGlowIntensity;
m *= smoothstep(1.0, 0.2, d);
return m;
}
vec3 StarLayer(vec2 uv) {
vec3 col = vec3(0.0);
vec2 gv = fract(uv) - 0.5;
vec2 id = floor(uv);
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
vec2 offset = vec2(float(x), float(y));
vec2 si = id + vec2(float(x), float(y));
float seed = Hash21(si);
float size = fract(seed * 345.32);
float glossLocal = tri(uStarSpeed / (PERIOD * seed + 1.0));
float flareSize = smoothstep(0.9, 1.0, size) * glossLocal;
float red = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 1.0)) + STAR_COLOR_CUTOFF;
float blu = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 3.0)) + STAR_COLOR_CUTOFF;
float grn = min(red, blu) * seed;
vec3 base = vec3(red, grn, blu);
float hue = atan(base.g - base.r, base.b - base.r) / (2.0 * 3.14159) + 0.5;
hue = fract(hue + uHueShift / 360.0);
float sat = length(base - vec3(dot(base, vec3(0.299, 0.587, 0.114)))) * uSaturation;
float val = max(max(base.r, base.g), base.b);
base = hsv2rgb(vec3(hue, sat, val));
vec2 pad = vec2(tris(seed * 34.0 + uTime * uSpeed / 10.0), tris(seed * 38.0 + uTime * uSpeed / 30.0)) - 0.5;
float star = Star(gv - offset - pad, flareSize);
vec3 color = base;
float twinkle = trisn(uTime * uSpeed + seed * 6.2831) * 0.5 + 1.0;
twinkle = mix(1.0, twinkle, uTwinkleIntensity);
star *= twinkle;
col += star * size * color;
}
}
return col;
}
void main() {
vec2 focalPx = uFocal * uResolution.xy;
vec2 uv = (vUv * uResolution.xy - focalPx) / uResolution.y;
vec2 mouseNorm = uMouse - vec2(0.5);
if (uAutoCenterRepulsion > 0.0) {
vec2 centerUV = vec2(0.0, 0.0);
float centerDist = length(uv - centerUV);
vec2 repulsion = normalize(uv - centerUV) * (uAutoCenterRepulsion / (centerDist + 0.1));
uv += repulsion * 0.05;
} else if (uMouseRepulsion) {
vec2 mousePosUV = (uMouse * uResolution.xy - focalPx) / uResolution.y;
float mouseDist = length(uv - mousePosUV);
vec2 repulsion = normalize(uv - mousePosUV) * (uRepulsionStrength / (mouseDist + 0.1));
uv += repulsion * 0.05 * uMouseActiveFactor;
} else {
vec2 mouseOffset = mouseNorm * 0.1 * uMouseActiveFactor;
uv += mouseOffset;
}
float autoRotAngle = uTime * uRotationSpeed;
mat2 autoRot = mat2(cos(autoRotAngle), -sin(autoRotAngle), sin(autoRotAngle), cos(autoRotAngle));
uv = autoRot * uv;
uv = mat2(uRotation.x, -uRotation.y, uRotation.y, uRotation.x) * uv;
vec3 col = vec3(0.0);
for (float i = 0.0; i < 1.0; i += 1.0 / NUM_LAYER) {
float depth = fract(i + uStarSpeed * uSpeed);
float scale = mix(20.0 * uDensity, 0.5 * uDensity, depth);
float fade = depth * smoothstep(1.0, 0.9, depth);
col += StarLayer(uv * scale + i * 453.32) * fade;
}
float alpha = length(col);
alpha = smoothstep(0.0, 0.3, alpha);
alpha = min(alpha, 1.0);
gl_FragColor = vec4(col, alpha);
}
`;
class GalaxyBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 将星系效应的焦点设置为 [x, y] 坐标(0-1) */
this.ncFocal = [0.5, 0.5];
/** 控制星系的旋转矩阵,其旋转值为[x, y] */
this.ncRotation = [1.0, 0.0];
/** 控制星星的移动速度和动画效果(0.1-2) */
this.ncStarSpeed = 0.5;
/** 控制星星的密度(0.1-3) */
this.ncDensity = 1;
/** 将所有星星的色调按指定的角度(0-360度)进行调整(在ncSaturation不为0时生效)*/
this.ncHueShift = 140;
/** 为真时,停止所有基于时间的动画 */
this._disableAnimation = false;
/** 所有动画的全局速度倍率(0.1-3) */
this.ncSpeed = 1.0;
/** 是否启用鼠标交互 */
this._mouseInteraction = true;
/** 控制星光效果的强度(0-1) */
this.ncGlowIntensity = 0.3;
/** 控制星星的颜色饱和度(0-1,0:灰度 1:全彩) */
this.ncSaturation = 0.0;
/** 是否启用鼠标排斥效果 */
this._mouseRepulsion = true;
/** 鼠标排斥力度(0-10) */
this.ncRepulsionStrength = 2;
/** 控制星星闪烁的程度(0-1,0:不闪烁 1:最大闪烁) */
this.ncTwinkleIntensity = 0.3;
/** 星系自动旋转的速度(0-0.5) */
this.ncRotationSpeed = 0.1;
/** 自动向中心排斥的强度(0-20,如果大于0则不使用鼠标位置) */
this.ncAutoCenterRepulsion = 0;
this.animationId = null;
this.targetMousePos = { x: 0.5, y: 0.5 };
this.smoothMousePos = { x: 0.5, y: 0.5 };
this.targetMouseActive = 0.0;
this.smoothMouseActive = 0.0;
this.animate = (t) => {
this.animationId = requestAnimationFrame(this.animate);
if (!this.ncDisableAnimation) {
this.uniforms.uTime.value = t * 0.001;
this.uniforms.uStarSpeed.value = (t * 0.001 * this.ncStarSpeed) / 10.0;
}
const lerpFactor = 0.05;
this.smoothMousePos.x += (this.targetMousePos.x - this.smoothMousePos.x) * lerpFactor;
this.smoothMousePos.y += (this.targetMousePos.y - this.smoothMousePos.y) * lerpFactor;
this.smoothMouseActive += (this.targetMouseActive - this.smoothMouseActive) * lerpFactor;
this.uniforms.uMouse.value[0] = this.smoothMousePos.x;
this.uniforms.uMouse.value[1] = this.smoothMousePos.y;
this.uniforms.uMouseActiveFactor.value = this.smoothMouseActive;
this.renderer.render(this.scene, this.camera);
};
this.handleMouseLeave = () => {
this.targetMouseActive = 0.0;
};
}
set ncDisableAnimation(val) {
this._disableAnimation = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncDisableAnimation() {
return this._disableAnimation;
}
set ncMouseInteraction(val) {
this._mouseInteraction = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncMouseInteraction() {
return this._mouseInteraction;
}
set ncMouseRepulsion(val) {
this._mouseRepulsion = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncMouseRepulsion() {
return this._mouseRepulsion;
}
ngOnInit() { }
ngAfterViewInit() {
this.initWebGL();
}
ngOnDestroy() {
this.cleanup();
}
ngOnChanges(changes) {
if (!this.uniforms)
return;
this.updateUniforms();
}
initWebGL() {
const container = this.containerRef.nativeElement;
this.renderer = new THREE.WebGLRenderer({
alpha: true,
premultipliedAlpha: false,
antialias: false
});
this.renderer.setClearColor(0x000000, 0);
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
container.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
this.uniforms = {
uTime: { value: 0 },
uResolution: { value: new THREE.Vector3() },
uFocal: { value: new THREE.Vector2() },
uRotation: { value: new THREE.Vector2() },
uStarSpeed: { value: this.ncStarSpeed },
uDensity: { value: this.ncDensity },
uHueShift: { value: this.ncHueShift },
uSpeed: { value: this.ncSpeed },
uMouse: { value: [this.smoothMousePos.x, this.smoothMousePos.y] },
uGlowIntensity: { value: this.ncGlowIntensity },
uSaturation: { value: this.ncSaturation },
uMouseRepulsion: { value: this.ncMouseRepulsion },
uTwinkleIntensity: { value: this.ncTwinkleIntensity },
uRotationSpeed: { value: this.ncRotationSpeed },
uRepulsionStrength: { value: this.ncRepulsionStrength },
uMouseActiveFactor: { value: 0.0 },
uAutoCenterRepulsion: { value: this.ncAutoCenterRepulsion }
};
this.updateUniforms();
const geometry = new THREE.PlaneGeometry(2, 2);
this.material = new THREE.RawShaderMaterial({
vertexShader,
fragmentShader,
uniforms: this.uniforms,
transparent: true,
blending: THREE.NormalBlending
});
const mesh = new THREE.Mesh(geometry, this.material);
this.scene.add(mesh);
this.resizeObserver = new ResizeObserver(() => this.resize());
this.resizeObserver.observe(container);
this.resize();
this.ngZone.runOutsideAngular(() => {
this.animate(0);
});
}
updateUniforms() {
if (!this.uniforms || !this.renderer)
return;
this.renderer.setClearColor(0x000000, 0);
this.material && (this.material.transparent = true);
this.uniforms.uFocal.value.set(this.ncFocal[0], this.ncFocal[1]);
this.uniforms.uRotation.value.set(this.ncRotation[0], this.ncRotation[1]);
this.uniforms.uStarSpeed.value = this.ncStarSpeed;
this.uniforms.uDensity.value = this.ncDensity;
this.uniforms.uHueShift.value = this.ncHueShift;
this.uniforms.uSpeed.value = this.ncSpeed;
this.uniforms.uGlowIntensity.value = this.ncGlowIntensity;
this.uniforms.uSaturation.value = this.ncSaturation;
this.uniforms.uMouseRepulsion.value = this.ncMouseRepulsion;
this.uniforms.uTwinkleIntensity.value = this.ncTwinkleIntensity;
this.uniforms.uRotationSpeed.value = this.ncRotationSpeed;
this.uniforms.uRepulsionStrength.value = this.ncRepulsionStrength;
this.uniforms.uAutoCenterRepulsion.value = this.ncAutoCenterRepulsion;
}
resize() {
if (!this.containerRef || !this.renderer)
return;
const container = this.containerRef.nativeElement;
const width = container.offsetWidth;
const height = container.offsetHeight;
this.renderer.setSize(width, height);
if (this.uniforms) {
this.uniforms.uResolution.value.set(width, height, width / height);
}
}
onMouseMove(e) {
if (!this.ncMouseInteraction)
return;
this.updateMousePos(e.clientX, e.clientY);
}
onMouseLeave() {
this.handleMouseLeave();
}
onTouchMove(e) {
if (!this.ncMouseInteraction || e.touches.length === 0)
return;
this.updateMousePos(e.touches[0].clientX, e.touches[0].clientY);
}
onTouchEnd() {
this.handleMouseLeave();
}
updateMousePos(clientX, clientY) {
if (!this.containerRef)
return;
const rect = this.containerRef.nativeElement.getBoundingClientRect();
const x = (clientX - rect.left) / rect.width;
const y = 1.0 - (clientY - rect.top) / rect.height;
this.targetMousePos = { x, y };
this.targetMouseActive = 1.0;
}
cleanup() {
var _a;
if (this.animationId !== null) {
cancelAnimationFrame(this.animationId);
this.animationId = null;
}
if (this.resizeObserver) {
this.resizeObserver.disconnect();
}
const container = (_a = this.containerRef) === null || _a === void 0 ? void 0 : _a.nativeElement;
if (container) {
if (this.renderer && container.contains(this.renderer.domElement)) {
container.removeChild(this.renderer.domElement);
}
}
if (this.renderer) {
this.renderer.dispose();
}
if (this.material) {
this.material.dispose();
}
if (this.scene) {
this.scene.clear();
}
}
}
GalaxyBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: GalaxyBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
GalaxyBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: GalaxyBackgroundComponent, selector: "nc-galaxy-background", inputs: { ncFocal: "ncFocal", ncRotation: "ncRotation", ncStarSpeed: "ncStarSpeed", ncDensity: "ncDensity", ncHueShift: "ncHueShift", ncDisableAnimation: "ncDisableAnimation", ncSpeed: "ncSpeed", ncMouseInteraction: "ncMouseInteraction", ncGlowIntensity: "ncGlowIntensity", ncSaturation: "ncSaturation", ncMouseRepulsion: "ncMouseRepulsion", ncRepulsionStrength: "ncRepulsionStrength", ncTwinkleIntensity: "ncTwinkleIntensity", ncRotationSpeed: "ncRotationSpeed", ncAutoCenterRepulsion: "ncAutoCenterRepulsion" }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseleave": "onMouseLeave()", "touchstart": "onTouchMove($event)", "touchmove": "onTouchMove($event)", "touchend": "onTouchEnd()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-galaxy-canvas-container\"></div>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-galaxy-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.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: GalaxyBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-galaxy-background',
templateUrl: './galaxy-background.component.html',
styleUrls: ['./galaxy-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncFocal: [{
type: Input
}], ncRotation: [{
type: Input
}], ncStarSpeed: [{
type: Input
}], ncDensity: [{
type: Input
}], ncHueShift: [{
type: Input
}], ncDisableAnimation: [{
type: Input
}], ncSpeed: [{
type: Input
}], ncMouseInteraction: [{
type: Input
}], ncGlowIntensity: [{
type: Input
}], ncSaturation: [{
type: Input
}], ncMouseRepulsion: [{
type: Input
}], ncRepulsionStrength: [{
type: Input
}], ncTwinkleIntensity: [{
type: Input
}], ncRotationSpeed: [{
type: Input
}], ncAutoCenterRepulsion: [{
type: Input
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], onMouseLeave: [{
type: HostListener,
args: ['mouseleave']
}], onTouchMove: [{
type: HostListener,
args: ['touchstart', ['$event']]
}, {
type: HostListener,
args: ['touchmove', ['$event']]
}], onTouchEnd: [{
type: HostListener,
args: ['touchend']
}] } });
class NcGalaxyBackgroundModule {
}
NcGalaxyBackgroundModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcGalaxyBackgroundModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NcGalaxyBackgroundModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcGalaxyBackgroundModule, declarations: [GalaxyBackgroundComponent], imports: [CommonModule], exports: [GalaxyBackgroundComponent] });
NcGalaxyBackgroundModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcGalaxyBackgroundModule, imports: [[
CommonModule
]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcGalaxyBackgroundModule, decorators: [{
type: NgModule,
args: [{
declarations: [
GalaxyBackgroundComponent
],
imports: [
CommonModule
],
exports: [
GalaxyBackgroundComponent
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { GalaxyBackgroundComponent, NcGalaxyBackgroundModule };
//# sourceMappingURL=ng-cw-v12-galaxy-background.js.map