UNPKG

ng-cw-v12

Version:

Angular UI component library

183 lines (178 loc) 9.6 kB
import * as i0 from '@angular/core'; import { Component, Input, ViewChild, NgModule } from '@angular/core'; class AuroraTextComponent { constructor() { /** 展示的文本内容 */ this._text = ''; /** 颜色 */ this.ncColors = ["#FF0080", "#7928CA", "#0070F3", "#38bdf8", "#a855f7", "#2dd4bf"]; /** 速度 */ this.ncSpeed = 1; this.dimensions = { width: 0, height: 0 }; this.isReady = false; this.textStyle = {}; this.maskId = `aurora-mask-${Math.random().toString(36).substring(2, 11)}`; } set ncText(value) { this._text = value; setTimeout(() => { this.start(); }); } get ncText() { return this._text; } ngOnInit() { } ngOnDestroy() { this.clear(); } start() { this.clear(); this.computeTextStyles(); this.updateDimensions(); this.startAnimation(); } clear() { if (this.animationFrameId) { cancelAnimationFrame(this.animationFrameId); } } computeTextStyles() { var _a; if ((_a = this.textContentRef) === null || _a === void 0 ? void 0 : _a.nativeElement) { const computedStyle = getComputedStyle(this.textContentRef.nativeElement); this.textStyle = this.extractTextStyles(computedStyle); } } updateDimensions() { var _a; if ((_a = this.svgTextRef) === null || _a === void 0 ? void 0 : _a.nativeElement) { try { const bbox = this.svgTextRef.nativeElement.getBBox(); this.dimensions = { width: Math.max(1, bbox.width), height: Math.max(1, bbox.height) }; this.isReady = true; } catch (e) { console.error('获取 SVG 元素尺寸时出错:', e); } } } startAnimation() { var _a; const canvas = (_a = this.canvasRef) === null || _a === void 0 ? void 0 : _a.nativeElement; if (!canvas) return; const ctx = canvas.getContext('2d'); if (!ctx) return; let time = 0; const baseSpeed = 0.008; const animate = () => { if (!ctx || !canvas) return; if (canvas.width !== this.dimensions.width || canvas.height !== this.dimensions.height) { canvas.width = this.dimensions.width; canvas.height = this.dimensions.height; } ctx.clearRect(0, 0, canvas.width, canvas.height); time += baseSpeed * this.ncSpeed; this.ncColors.forEach((color, i) => { const x = canvas.width * (0.5 + Math.cos(time * 0.8 + i * 1.3) * 0.4 + Math.sin(time * 0.5 + i * 0.7) * 0.2); const y = canvas.height * (0.5 + Math.sin(time * 0.7 + i * 1.5) * 0.4 + Math.cos(time * 0.6 + i * 0.8) * 0.2); const gradient = ctx.createRadialGradient(x, y, 0, x, y, canvas.width * 0.4); gradient.addColorStop(0, `${color}99`); gradient.addColorStop(0.5, `${color}33`); gradient.addColorStop(1, "#00000000"); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); }); this.animationFrameId = requestAnimationFrame(animate); }; animate(); } getStyleString() { let styleStr = ''; for (const [key, value] of Object.entries(this.textStyle)) { if (value) { // 将驼峰命名转换为连字符命名 const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase(); styleStr += `${cssKey}:${value};`; } } return styleStr; } // 提取文本相关样式的辅助方法 extractTextStyles(computedStyle) { return { fontSize: computedStyle.fontSize, fontFamily: computedStyle.fontFamily, fontWeight: computedStyle.fontWeight, fontStyle: computedStyle.fontStyle, letterSpacing: computedStyle.letterSpacing, lineHeight: computedStyle.lineHeight, textTransform: computedStyle.textTransform, fontVariant: computedStyle.fontVariant, fontStretch: computedStyle.fontStretch, fontFeatureSettings: computedStyle.fontFeatureSettings, textDecoration: computedStyle.textDecoration, textShadow: computedStyle.textShadow, }; } } AuroraTextComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: AuroraTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); AuroraTextComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: AuroraTextComponent, selector: "nc-aurora-text", inputs: { ncText: "ncText", ncColors: "ncColors", ncSpeed: "ncSpeed" }, viewQueries: [{ propertyName: "textContentRef", first: true, predicate: ["textContent"], descendants: true }, { propertyName: "svgTextRef", first: true, predicate: ["svgText"], descendants: true }, { propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true }], ngImport: i0, template: "<span class=\"aurora-text relative inline-block align-middle\" [style.width]=\"dimensions.width ? dimensions.width + 'px' : 'auto'\"\r\n [style.height]=\"dimensions.height ? dimensions.height + 'px' : 'auto'\">\r\n\r\n <!-- \u9690\u85CF\u7684\u6587\u672C\u7528\u4E8ESEO -->\r\n <span class=\"sr-only\">\r\n {{ncText}}\r\n </span>\r\n\r\n <!-- \u89C6\u89C9\u5360\u4F4D\u7B26 -->\r\n <span #textContent style=\"opacity: 0;display: inline-block; white-space: nowrap;\"\r\n [style.position]=\"isReady ? 'absolute' : 'relative'\" aria-hidden=\"true\">\r\n {{ncText}}\r\n </span>\r\n\r\n <div class=\"absolute inset-0\" [style.opacity]=\"isReady ? 1 : 0\" style=\"transition: opacity 0.2s ease-in;\"\r\n aria-hidden=\"true\">\r\n\r\n <svg [attr.width]=\"dimensions.width\" [attr.height]=\"dimensions.height\" class=\"absolute inset-0\">\r\n <defs>\r\n <clipPath [attr.id]=\"maskId\">\r\n <text #svgText x=\"50%\" y=\"50%\" dominant-baseline=\"middle\" text-anchor=\"middle\"\r\n [attr.style]=\"getStyleString()\">{{ncText}}</text>\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n\r\n <canvas #canvas [style.clip-path]=\"'url(#' + maskId + ')'\" [style.-webkit-clip-path]=\"'url(#' + maskId + ')'\"\r\n class=\"h-full w-full\">\r\n </canvas>\r\n </div>\r\n</span>", styles: [":host{display:inline-block}.relative{position:relative}.absolute{position:absolute}.inset-0{top:0;right:0;bottom:0;left:0}.inline-block{display:inline-block}.align-middle{vertical-align:middle}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.h-full{height:100%}.w-full{width:100%}\n"] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: AuroraTextComponent, decorators: [{ type: Component, args: [{ selector: 'nc-aurora-text', templateUrl: './aurora-text.component.html', styleUrls: ['./aurora-text.component.less'] }] }], ctorParameters: function () { return []; }, propDecorators: { ncText: [{ type: Input }], ncColors: [{ type: Input }], ncSpeed: [{ type: Input }], textContentRef: [{ type: ViewChild, args: ['textContent'] }], svgTextRef: [{ type: ViewChild, args: ['svgText'] }], canvasRef: [{ type: ViewChild, args: ['canvas'] }] } }); class NcAuroraTextModule { } NcAuroraTextModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcAuroraTextModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); NcAuroraTextModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcAuroraTextModule, declarations: [AuroraTextComponent], exports: [AuroraTextComponent] }); NcAuroraTextModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcAuroraTextModule, imports: [[]] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcAuroraTextModule, decorators: [{ type: NgModule, args: [{ declarations: [ AuroraTextComponent ], imports: [], exports: [ AuroraTextComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { AuroraTextComponent, NcAuroraTextModule }; //# sourceMappingURL=ng-cw-v12-aurora-text.js.map