ng-cw-v12
Version:
Angular UI component library
183 lines (178 loc) • 9.6 kB
JavaScript
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