将 angularjs 指令转换为 angular 10
Convert angularjs directive to angular 10
我想在我的 angular 项目中使用此代码:
'use strict';
/**
* Floating text animation (random)
*/
angular.module('g1b.text-animation', []).
directive('textAnimation', ['$document', '$interval', '$timeout', function ($document, $interval, $timeout) {
return {
restrict: 'A',
compile: function () {
return {
pre: function () {},
post: function (scope, element) {
var chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
$interval(function () {
for ( var i = 0; i < Math.floor(Math.random() * 5); i++ ) {
var character = chars[Math.floor(Math.random() * chars.length)];
var duration = Math.floor(Math.random() * 15);
var offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
var size = 12 + (15 - duration);
var span = angular.element('<span class="animated-text" style="right:'+offset+'vw; font-size: '+size+'px; animation-duration:'+duration+'s">'+character+'</span>');
element.append(span);
$timeout(function (span) {
span.remove();
}, duration * 1000, false, span);
}
}, 250);
}
};
}
};
}]);
它还有一个 CSS 文件。
这段代码基本上是一个文字动画。
我的问题是我不知道从哪里开始。
这就是我想要实现的目标:
https://rawgit.com/g1eb/angular-text-animation/master/
这是它的 npm:
https://github.com/g1eb/angular-text-animation
更新:
我已经自己尝试过了,这就是我所拥有的:
@ViewChildren('styleDiv', {read: ElementRef}) children: QueryList<ElementRef>;
constructor(private renderer: Renderer2, private host: ElementRef) {
}
ngOnInit(): void {
}
ngAfterViewInit(): void {
this.animateBackground();
}
private animateBackground(): void {
const renderer = this.renderer;
const children = this.children;
const host = this.host;
const chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
setInterval(() => {
for (let i = 0; i < Math.floor(Math.random() * 5); i++) {
const character = chars[Math.floor(Math.random() * chars.length)];
const duration = Math.floor(Math.random() * 15);
const offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
const size = 12 + (15 - duration);
const span = '<span class="animated-text" style="right:' + offset + 'vw; font-size: ' +
+size + 'px; animation-duration:' + duration + 's">' + character + '</span>';
this.children.first.nativeElement.insertAdjacentHTML('beforeend', span);
setTimeout(() => {
// renderer.removeChild(children.first.nativeElement.parentNode, children.first.nativeElement);
}, duration * 1000, false, host, children, renderer);
}
}, 250, host, children, renderer);
}
它可以工作,但我在设置超时函数中确实有问题。
我可以将跨度添加到 dom,但无法将其删除。
在与编写此指令的人交谈后,我们决定我将为 angular 2+ 编写一个新指令,他应该会在接下来的几天内批准拉取请求。
新代码应该很快就会在他的存储库中可用:
https://github.com/g1eb/angular-text-animation
但现在,这是新指令:
import {AfterViewInit, Directive, ElementRef, Input, Renderer2} from '@angular/core';
@Directive({
selector: '[sbzTextAnimation]'
})
export class NgxSbzTextAnimationDirective implements AfterViewInit {
@Input() maxFontSize = 20;
@Input() colorSchemeArray: string[];
@Input() position: 'left' | 'right' = 'right';
constructor(private elementRef: ElementRef, private renderer: Renderer2) {
}
ngAfterViewInit(): void {
this.init();
this.animateBackground();
}
private init(): void {
this.colorSchemeArray = this.colorSchemeArray
? this.colorSchemeArray
: [
'#63b598', '#ce7d78', '#ea9e70', '#a48a9e', '#c6e1e8', '#648177', '#0d5ac1',
'#f205e6', '#1c0365', '#14a9ad', '#4ca2f9', '#a4e43f', '#d298e2', '#6119d0',
'#d2737d', '#c0a43c', '#f2510e', '#651be6', '#79806e', '#61da5e', '#cd2f00',
'#9348af', '#01ac53', '#c5a4fb', '#996635', '#b11573', '#4bb473', '#75d89e',
'#2f3f94', '#2f7b99', '#da967d', '#34891f', '#b0d87b', '#ca4751', '#7e50a8',
];
}
private animateBackground(): void {
// need to access them in the setTimeout function
const renderer = this.renderer;
const elementRef = this.elementRef;
const chars = [...Array(26)].map((e, i) => (i + 10).toString(36));
setInterval(() => {
for (let i = 0; i < Math.floor(Math.random() * 5); i++) {
const duration = Math.floor(Math.random() * 15);
const offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
const size = 12 + (this.maxFontSize - duration);
const color = this.colorSchemeArray[Math.floor(Math.random() * this.colorSchemeArray.length)];
const span = renderer.createElement('span');
span.innerText = chars[Math.floor(Math.random() * chars.length)];
renderer.addClass(span, 'animated-text');
renderer.setStyle(span, 'color', color);
renderer.setStyle(span, this.position, `${offset}vw`);
renderer.setStyle(span, 'font-size', `${size}px`);
renderer.setStyle(span, 'animation-duration', `${duration}s`);
renderer.setStyle(span, 'color', color);
renderer.appendChild(elementRef.nativeElement, span);
setTimeout(() => {
renderer.removeChild(elementRef.nativeElement, elementRef.nativeElement.firstChild);
}, duration * 1000, false, elementRef, renderer);
}
}, 250);
}
}
我也做了一些修改:
- 文字现在是彩虹色。
- 添加了最大字体大小的输入以自定义用例:[maxFontSize]="30"
- 添加了彩虹色输入。如果用户只想要一种颜色,他可以传递一种
颜色或不同的方案是这样的:
[colorSchemeArray]="['#000"]
- 为背景中浮动文本的位置添加了输入。
这是指令的 CSS(应该在使用指令的组件的 CSS 文件中):
/**
* Floating text animation styles
*/
.animated-text {
cursor: default;
color: #68C2A3;
font-family: 'VT323', monospace, sans-serif;
text-shadow: 0 0 1px #ffffff;
font-size: 24px;
position: fixed;
top: -50px;
user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
animation-name: float-animation;
animation-timing-function: ease-out;
}
@keyframes float-animation {
0% {
top: 100vh;
opacity: 0;
}
25% {
opacity: 1;
}
50% {
opacity: 1;
}
75% {
opacity: 0;
}
100% {
top: -25px;
opacity: 0;
}
}
这是一个完整的工作演示:
https://stackblitz.com/edit/floating-text-animation?file=src/app/app.component.html
更新:
这是 npm 上最终指令的 link:
https://www.npmjs.com/package/ngx-sbz-text-animation
您也可以将 rxjs 与调度程序一起使用,它可以稍微平滑动画。
interval(250)
.pipe(
// tap(_ => console.log("started..")),
mergeMap(_ =>
from([...Array(Math.floor(Math.random() * 5))]).pipe(
observeOn(asyncScheduler)
)
),
map(_ => this.getMap()),
tap(({ span }) =>
this.elementRef.nativeElement.insertAdjacentHTML("beforeend", span)
),
mergeMap(({ duration }) =>
of(null).pipe(
delay(duration * 1000),
tap(_ =>
renderer.removeChild(
this.elementRef.nativeElement,
this.elementRef.nativeElement.firstChild
)
)
)
),
takeUntil(this._destroy$)
)
.subscribe();
添加了一个方法:
getMap(): { span: string; duration: number } {
const character = this.chars[Math.floor(Math.random() * this.chars.length)];
const duration = Math.floor(Math.random() * 15);
const offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
const size = 12 + (this.maxFontSize - duration);
const color = this.colorSchemeArray[
Math.floor(Math.random() * this.colorSchemeArray.length)
];
return {
duration,
span: `<span class="animated-text" style="color: ${color};${
this.position
}: ${offset}vw; font-size: ${size}px; animation-duration:${
duration}s">${character}</span>`
};
}
创建一个主题 _destory$ 和 OnDestroy 方法:在 takeUntil 中用于垃圾收集
我使用的调度程序是 asyncScheduler
或 animationFrameScheduler
。 animationFrameScheduler
更好,但删除需要调整
我想在我的 angular 项目中使用此代码:
'use strict';
/**
* Floating text animation (random)
*/
angular.module('g1b.text-animation', []).
directive('textAnimation', ['$document', '$interval', '$timeout', function ($document, $interval, $timeout) {
return {
restrict: 'A',
compile: function () {
return {
pre: function () {},
post: function (scope, element) {
var chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
$interval(function () {
for ( var i = 0; i < Math.floor(Math.random() * 5); i++ ) {
var character = chars[Math.floor(Math.random() * chars.length)];
var duration = Math.floor(Math.random() * 15);
var offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
var size = 12 + (15 - duration);
var span = angular.element('<span class="animated-text" style="right:'+offset+'vw; font-size: '+size+'px; animation-duration:'+duration+'s">'+character+'</span>');
element.append(span);
$timeout(function (span) {
span.remove();
}, duration * 1000, false, span);
}
}, 250);
}
};
}
};
}]);
它还有一个 CSS 文件。 这段代码基本上是一个文字动画。 我的问题是我不知道从哪里开始。
这就是我想要实现的目标: https://rawgit.com/g1eb/angular-text-animation/master/
这是它的 npm: https://github.com/g1eb/angular-text-animation
更新:
我已经自己尝试过了,这就是我所拥有的:
@ViewChildren('styleDiv', {read: ElementRef}) children: QueryList<ElementRef>;
constructor(private renderer: Renderer2, private host: ElementRef) {
}
ngOnInit(): void {
}
ngAfterViewInit(): void {
this.animateBackground();
}
private animateBackground(): void {
const renderer = this.renderer;
const children = this.children;
const host = this.host;
const chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
setInterval(() => {
for (let i = 0; i < Math.floor(Math.random() * 5); i++) {
const character = chars[Math.floor(Math.random() * chars.length)];
const duration = Math.floor(Math.random() * 15);
const offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
const size = 12 + (15 - duration);
const span = '<span class="animated-text" style="right:' + offset + 'vw; font-size: ' +
+size + 'px; animation-duration:' + duration + 's">' + character + '</span>';
this.children.first.nativeElement.insertAdjacentHTML('beforeend', span);
setTimeout(() => {
// renderer.removeChild(children.first.nativeElement.parentNode, children.first.nativeElement);
}, duration * 1000, false, host, children, renderer);
}
}, 250, host, children, renderer);
}
它可以工作,但我在设置超时函数中确实有问题。 我可以将跨度添加到 dom,但无法将其删除。
在与编写此指令的人交谈后,我们决定我将为 angular 2+ 编写一个新指令,他应该会在接下来的几天内批准拉取请求。 新代码应该很快就会在他的存储库中可用: https://github.com/g1eb/angular-text-animation
但现在,这是新指令:
import {AfterViewInit, Directive, ElementRef, Input, Renderer2} from '@angular/core';
@Directive({
selector: '[sbzTextAnimation]'
})
export class NgxSbzTextAnimationDirective implements AfterViewInit {
@Input() maxFontSize = 20;
@Input() colorSchemeArray: string[];
@Input() position: 'left' | 'right' = 'right';
constructor(private elementRef: ElementRef, private renderer: Renderer2) {
}
ngAfterViewInit(): void {
this.init();
this.animateBackground();
}
private init(): void {
this.colorSchemeArray = this.colorSchemeArray
? this.colorSchemeArray
: [
'#63b598', '#ce7d78', '#ea9e70', '#a48a9e', '#c6e1e8', '#648177', '#0d5ac1',
'#f205e6', '#1c0365', '#14a9ad', '#4ca2f9', '#a4e43f', '#d298e2', '#6119d0',
'#d2737d', '#c0a43c', '#f2510e', '#651be6', '#79806e', '#61da5e', '#cd2f00',
'#9348af', '#01ac53', '#c5a4fb', '#996635', '#b11573', '#4bb473', '#75d89e',
'#2f3f94', '#2f7b99', '#da967d', '#34891f', '#b0d87b', '#ca4751', '#7e50a8',
];
}
private animateBackground(): void {
// need to access them in the setTimeout function
const renderer = this.renderer;
const elementRef = this.elementRef;
const chars = [...Array(26)].map((e, i) => (i + 10).toString(36));
setInterval(() => {
for (let i = 0; i < Math.floor(Math.random() * 5); i++) {
const duration = Math.floor(Math.random() * 15);
const offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
const size = 12 + (this.maxFontSize - duration);
const color = this.colorSchemeArray[Math.floor(Math.random() * this.colorSchemeArray.length)];
const span = renderer.createElement('span');
span.innerText = chars[Math.floor(Math.random() * chars.length)];
renderer.addClass(span, 'animated-text');
renderer.setStyle(span, 'color', color);
renderer.setStyle(span, this.position, `${offset}vw`);
renderer.setStyle(span, 'font-size', `${size}px`);
renderer.setStyle(span, 'animation-duration', `${duration}s`);
renderer.setStyle(span, 'color', color);
renderer.appendChild(elementRef.nativeElement, span);
setTimeout(() => {
renderer.removeChild(elementRef.nativeElement, elementRef.nativeElement.firstChild);
}, duration * 1000, false, elementRef, renderer);
}
}, 250);
}
}
我也做了一些修改:
- 文字现在是彩虹色。
- 添加了最大字体大小的输入以自定义用例:[maxFontSize]="30"
- 添加了彩虹色输入。如果用户只想要一种颜色,他可以传递一种 颜色或不同的方案是这样的: [colorSchemeArray]="['#000"]
- 为背景中浮动文本的位置添加了输入。
这是指令的 CSS(应该在使用指令的组件的 CSS 文件中):
/**
* Floating text animation styles
*/
.animated-text {
cursor: default;
color: #68C2A3;
font-family: 'VT323', monospace, sans-serif;
text-shadow: 0 0 1px #ffffff;
font-size: 24px;
position: fixed;
top: -50px;
user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
animation-name: float-animation;
animation-timing-function: ease-out;
}
@keyframes float-animation {
0% {
top: 100vh;
opacity: 0;
}
25% {
opacity: 1;
}
50% {
opacity: 1;
}
75% {
opacity: 0;
}
100% {
top: -25px;
opacity: 0;
}
}
这是一个完整的工作演示: https://stackblitz.com/edit/floating-text-animation?file=src/app/app.component.html
更新: 这是 npm 上最终指令的 link: https://www.npmjs.com/package/ngx-sbz-text-animation
您也可以将 rxjs 与调度程序一起使用,它可以稍微平滑动画。
interval(250)
.pipe(
// tap(_ => console.log("started..")),
mergeMap(_ =>
from([...Array(Math.floor(Math.random() * 5))]).pipe(
observeOn(asyncScheduler)
)
),
map(_ => this.getMap()),
tap(({ span }) =>
this.elementRef.nativeElement.insertAdjacentHTML("beforeend", span)
),
mergeMap(({ duration }) =>
of(null).pipe(
delay(duration * 1000),
tap(_ =>
renderer.removeChild(
this.elementRef.nativeElement,
this.elementRef.nativeElement.firstChild
)
)
)
),
takeUntil(this._destroy$)
)
.subscribe();
添加了一个方法:
getMap(): { span: string; duration: number } {
const character = this.chars[Math.floor(Math.random() * this.chars.length)];
const duration = Math.floor(Math.random() * 15);
const offset = Math.floor(Math.random() * (45 - duration * 3)) + 3;
const size = 12 + (this.maxFontSize - duration);
const color = this.colorSchemeArray[
Math.floor(Math.random() * this.colorSchemeArray.length)
];
return {
duration,
span: `<span class="animated-text" style="color: ${color};${
this.position
}: ${offset}vw; font-size: ${size}px; animation-duration:${
duration}s">${character}</span>`
};
}
创建一个主题 _destory$ 和 OnDestroy 方法:在 takeUntil 中用于垃圾收集
我使用的调度程序是 asyncScheduler
或 animationFrameScheduler
。 animationFrameScheduler
更好,但删除需要调整