Angular TimelineLite 时间功能不适用于 OnInit

Angular TimelineLite time function doesn't work with OnInit

我尝试使用 TimelineLite 实现进度条和计时器:

HTML:

<div id="progress"></div>
{{timeline.time()}}

CSS:

#progress {
  width: 100%;
  height: 30px;
  background-color: red;
}

这是我想要的:
当页面加载时,进度条开始从 100% 到 0% 宽度(持续 10 秒)进行动画处理。另外,我想显示 time 函数的结果。
这是我所做的:

public timeline = new TimelineLite();

ngOnInit() {
  this.start();
}

start() {
  const progress = document.getElementById('progress');
  this.timeline.fromTo(progress, 10, {width: '100%'}, {width: 0, ease: Linear.easeNone});
}

所以当页面加载时,进度条工作但计时器不工作。我不知道为什么。如果我尝试在 ngOnInit 处设置 3 秒的超时,它会起作用:

ngOnInit() {
  setTimeout(() => this.start(), 3000);
}

此外,如果我创建一个按钮,然后在单击时调用 start 函数,它会起作用:

<button (click)="start()">Start</button>

所以问题是,如果我尝试从 ngOnInit.

调用 fromTo 函数,计时器将不起作用

这显然是angular调用生命周期方法的时间线案例。问题很可能出在 onInit 中,您没有立即获得 DOM 元素 progress。你已经让它工作应用 settimeout 另一种方法是保持 setinterval 直到你找到 progress.
貌似最好的办法是在ngAfterViewInit()中写this.start()而不是ngOnInit()

可能是因为超时在模板初始化后开始,然后代码在 OnInit 之外运行。不过我不确定。

您可能想在这里使用 zone.run()。

这里有一个 link,它可能对您有所帮助:https://medium.com/@MertzAlertz/what-the-hell-is-zone-js-and-why-is-it-in-my-angular-2-6ff28bcf943e

您好,您应该使用 @ViewChild 来定位您的元素,并在您想要操作时使用 AfterViewInit lifeCycleHook |访问您的 DOMElement(当前组件或子组件)。

export class AppComponent implements AfterViewInit {

  @ViewChild('progress') progressElement: ElementRef;

  constructor(private changeRef: ChangeDetectorRef) { } 

  public timeline = new TimelineLite();
  ngAfterViewInit() {
    this.start();
  }

  start() {
    this.timeline.eventCallback('onUpdate', () => {
      this.time = this.timeline.time();
      this.changeRef.detectChanges();
    }, [] );

    // Here i use the ViewChild Binding instead of pure javascript fetching.
    this.timeline.fromTo(this.progressElement.nativeElement, 10, {width: '100%'}, {width: 0, ease: Linear.easeNone});
  }
}

为了方便您的测试,我做了 Github Pull request。任何阅读过您的原始问题的人都可以轻松看出其中的区别。


更新 1:在您看来,您调用了一个函数,该函数 return 来自 TimelineLite 的当前计时器。因为只是函数调用,所以不会在每次内部 TimelineLite 更新时一次又一次地调用它。

要做到这一点,您必须使用 TimelineLite event binding

现在,默认情况下,每次通过以下代码更新属性时,您的视图都不会 "updated":

this.timeline.eventCallback('onUpdate', () => {
  // angular is not inform by default than something happen here.
 }, [] );

就是为什么,你应该使用ChangeDetectorRef来强制angular检测最新更新的组件属性。

请求更新