Функция времени Angular TimelineLite не работает с OnInit - PullRequest
2 голосов
/ 08 апреля 2019

Я пытаюсь реализовать индикатор выполнения и таймер, используя TimelineLite:

HTML:

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

CSS:

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

enter image description here

Вот что я хочу:
Когда страница загружается, индикатор выполнения начинает анимацию от 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});
}

Поэтому, когда страница загружается, индикатор выполнения работает, а таймер - нет. Я не знаю почему. Если я попытаюсь установить тайм-аут на 3 секунды на ngOnInit, это сработает:

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

Также, если я создаю кнопку, которая при нажатии вызывает функцию start, она работает:

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

Так что проблема в том, что таймер не работает, если я пытаюсь вызвать функцию fromTo из ngOnInit.

Ответы [ 3 ]

1 голос
/ 17 апреля 2019

Привет, вы должны использовать @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 .Любой, кто прочитал ваш оригинальный вопрос, может легко увидеть разницу.


Обновление 1: по вашему мнению, вы вызываете функцию, которая возвращает текущий таймер из TimelineLite.Поскольку это просто вызов функции, он не будет вызываться снова и снова при каждом внутреннем обновлении TimelineLite.

Для этого необходимо использовать привязку события TimelineLite .

Теперь по умолчанию ваш вид не будет «обновляться» каждый раз, когда вы обновляете свой атрибут из следующего кода:

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

, поэтому вы должны использовать ChangeDetectorRef, чтобы принудить угол кобнаружение самого нового обновленного атрибута компонента.

запрос на обновление обновлен

0 голосов
/ 10 апреля 2019

Вероятно, это происходит потому, что после инициализации шаблона начинается тайм-аут, а затем выполняется код вне OnInit. Я не уверен, хотя.

Вы можете использовать zone.run () здесь.

Вот ссылка, которая может оказаться полезной для вас: https://medium.com/@MertzAlertz/what-the-hell-is-zone-js-and-why-is-it-in-my-angular-2-6ff28bcf943e

0 голосов
/ 08 апреля 2019

Это, очевидно, случай временной шкалы вызова методов жизненного цикла angular. Весьма вероятно, что проблема в onInit, где вы не сразу получаете элемент DOM progress. Вы заставили его работать, применяя settimeout, иначе вы должны оставить setinterval, пока не найдете progress.
Казалось бы, лучший способ - написать this.start() в ngAfterViewInit() вместо ngOnInit()

...