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检测最新更新的组件属性。
请求更新
我尝试使用 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检测最新更新的组件属性。
请求更新