ng-cw-v12
Version:
Angular UI component library
179 lines (174 loc) • 8.8 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, Directive, Input, Output, NgModule } from '@angular/core';
class BorderBeamDirective {
constructor(el, renderer) {
this.el = el;
this.renderer = renderer;
this.ncSize = 50; // 光条大小 单位px
this.ncDuration = 6000; // 动画时长,ms
this.ncStopTime = 0; // 停止动画时间,ms,0表示不停止
this.ncColorFrom = '#ffaa40'; // 渐变起始颜色
this.ncColorTo = '#9c40ff'; // 渐变结束颜色
this._reverse = false; // 是否反向动画
this.ncInitialOffset = 0; // 初始偏移位置 (0-100) 单位%
this.ncBorderWidth = 1; // 边框宽度 单位px
this.ncEnabled = true; // 是否启用动画
this.ncEnabledChange = new EventEmitter(); // 双向绑定输出事件
this.isInitialized = false;
// 为每个实例生成唯一的动画名称
this.animationName = `ncBorderBeam_${Math.random().toString(36).substring(2, 11)}`;
}
set ncReverse(val) {
this._reverse = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncReverse() {
return this._reverse;
}
ngOnInit() {
this.createBorderBeamContainer();
this.isInitialized = true;
if (this.ncEnabled) {
this.startAnimation();
}
}
ngOnChanges(changes) {
if (this.isInitialized && changes['ncEnabled']) {
if (this.ncEnabled) {
this.startAnimation();
}
else {
this.stopAnimation();
}
}
}
ngOnDestroy() {
if (this.stopTimer) {
clearTimeout(this.stopTimer);
}
}
createBorderBeamContainer() {
// 创建边框容器
this.borderContainer = this.renderer.createElement('div');
this.renderer.addClass(this.borderContainer, 'border-beam-container');
// 设置边框容器样式
this.renderer.setStyle(this.borderContainer, 'position', 'absolute');
this.renderer.setStyle(this.borderContainer, 'inset', '0');
this.renderer.setStyle(this.borderContainer, 'borderRadius', 'inherit');
this.renderer.setStyle(this.borderContainer, 'pointerEvents', 'none');
this.renderer.setStyle(this.borderContainer, 'border', `${this.ncBorderWidth}px solid transparent`);
this.renderer.setStyle(this.borderContainer, 'maskClip', 'padding-box, border-box');
this.renderer.setStyle(this.borderContainer, 'maskComposite', 'intersect');
this.renderer.setStyle(this.borderContainer, 'maskImage', 'linear-gradient(transparent, transparent), linear-gradient(#000, #000)');
// 创建光条元素
this.beamElement = this.renderer.createElement('div');
this.renderer.addClass(this.beamElement, 'border-beam');
// 设置光条样式
this.renderer.setStyle(this.beamElement, 'position', 'absolute');
this.renderer.setStyle(this.beamElement, 'width', `${this.ncSize}px`);
this.renderer.setStyle(this.beamElement, 'aspectRatio', '1');
this.renderer.setStyle(this.beamElement, 'background', `linear-gradient(to left, ${this.ncColorFrom}, ${this.ncColorTo}, transparent)`);
this.renderer.setStyle(this.beamElement, 'offsetPath', `rect(0 auto auto 0 round ${this.ncSize}px)`);
// 初始状态下隐藏光条
this.renderer.setStyle(this.beamElement, 'opacity', '0');
const elementPosition = this.el.nativeElement.style.position;
if (!elementPosition || elementPosition === 'static') {
this.renderer.setStyle(this.el.nativeElement, 'position', 'relative');
}
// 添加关键帧动画样式
this.styleElement = this.renderer.createElement('style');
const startOffset = this.ncReverse ? `${100 - this.ncInitialOffset}%` : `${this.ncInitialOffset}%`;
const endOffset = this.ncReverse ? `${-this.ncInitialOffset}%` : `${100 + this.ncInitialOffset}%`;
const keyframes = `
${this.animationName} {
0% {
offset-distance: ${startOffset};
}
100% {
offset-distance: ${endOffset};
}
}
`;
this.renderer.appendChild(this.styleElement, this.renderer.createText(keyframes));
this.renderer.appendChild(this.el.nativeElement, this.styleElement);
// 将光条添加到边框容器中
this.renderer.appendChild(this.borderContainer, this.beamElement);
// 将边框容器添加到宿主元素中
this.renderer.appendChild(this.el.nativeElement, this.borderContainer);
}
startAnimation() {
if (!this.beamElement)
return;
// 显示光条元素
this.renderer.setStyle(this.beamElement, 'opacity', '1');
this.renderer.setStyle(this.beamElement, 'animation', `${this.animationName} ${this.ncDuration}ms linear infinite`);
// 如果设置了停止时间,则在指定时间后标记需要停止
if (this.ncStopTime > 0) {
this.stopTimer = setTimeout(() => {
this.stopAnimation();
// 当因为 ncStopTime 停止动画时,更新 ncEnabled 值并发出事件
this.ncEnabled = false;
this.ncEnabledChange.emit(false);
}, this.ncStopTime);
}
}
stopAnimation() {
if (!this.beamElement)
return;
if (this.stopTimer) {
clearTimeout(this.stopTimer);
this.stopTimer = null;
}
this.renderer.setStyle(this.beamElement, 'animation', 'none');
this.renderer.setStyle(this.beamElement, 'opacity', '0');
}
}
BorderBeamDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: BorderBeamDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
BorderBeamDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.1.5", type: BorderBeamDirective, selector: "[ncBorderBeam]", inputs: { ncSize: "ncSize", ncDuration: "ncDuration", ncStopTime: "ncStopTime", ncColorFrom: "ncColorFrom", ncColorTo: "ncColorTo", ncReverse: "ncReverse", ncInitialOffset: "ncInitialOffset", ncBorderWidth: "ncBorderWidth", ncEnabled: "ncEnabled" }, outputs: { ncEnabledChange: "ncEnabledChange" }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: BorderBeamDirective, decorators: [{
type: Directive,
args: [{
selector: '[ncBorderBeam]'
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { ncSize: [{
type: Input
}], ncDuration: [{
type: Input
}], ncStopTime: [{
type: Input
}], ncColorFrom: [{
type: Input
}], ncColorTo: [{
type: Input
}], ncReverse: [{
type: Input
}], ncInitialOffset: [{
type: Input
}], ncBorderWidth: [{
type: Input
}], ncEnabled: [{
type: Input
}], ncEnabledChange: [{
type: Output
}] } });
class NcBorderBeamModule {
}
NcBorderBeamModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcBorderBeamModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NcBorderBeamModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcBorderBeamModule, declarations: [BorderBeamDirective], exports: [BorderBeamDirective] });
NcBorderBeamModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcBorderBeamModule, imports: [[]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcBorderBeamModule, decorators: [{
type: NgModule,
args: [{
declarations: [
BorderBeamDirective
],
imports: [],
exports: [
BorderBeamDirective
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { BorderBeamDirective, NcBorderBeamModule };
//# sourceMappingURL=ng-cw-v12-border-beam.js.map