将 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);
  }
}

我也做了一些修改:

  1. 文字现在是彩虹色。
  2. 添加了最大字体大小的输入以自定义用例:[maxFontSize]="30"
  3. 添加了彩虹色输入。如果用户只想要一种颜色,他可以传递一种 颜色或不同的方案是这样的: [colorSchemeArray]="['#000"]
  4. 为背景中浮动文本的位置添加了输入。

这是指令的 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 中用于垃圾收集 我使用的调度程序是 asyncScheduleranimationFrameScheduleranimationFrameScheduler 更好,但删除需要调整