Javascript Angular2物理动画
我希望执行一些物理动画,并在一组DOM元素上执行动画。不是帆布非常重要:不是画布。 我已经让它工作了,但是性能比我预期的要慢,即使考虑到DOM操作是多么昂贵。如果一次页面上有多个组件,即使您将间隔调整为不太频繁,它也几乎无法使用 我想知道是否有一个更简单或更有效的方法,同时保持在一定的角度内。也许可以完全跳过分区的角度渲染?在不使用角度绑定的情况下使用香草,这是一种更有效的方式,所以我想知道我是否只是做了错误的角度部分,或者我是否应该打破这些部分的角度。我以为区域应该比全球操纵表现更好 在屏幕上晃动某些东西的示例代码(真实动画更复杂,但遵循此确切技术): 如果最好在Angular的控制之外进行此操作,是否有任何标准?我可以用一个组件绘制DOM元素,然后分派一个窗口事件来启动非角度代码Javascript Angular2物理动画,javascript,angularjs,angular,animation,Javascript,Angularjs,Angular,Animation,我希望执行一些物理动画,并在一组DOM元素上执行动画。不是帆布非常重要:不是画布。 我已经让它工作了,但是性能比我预期的要慢,即使考虑到DOM操作是多么昂贵。如果一次页面上有多个组件,即使您将间隔调整为不太频繁,它也几乎无法使用 我想知道是否有一个更简单或更有效的方法,同时保持在一定的角度内。也许可以完全跳过分区的角度渲染?在不使用角度绑定的情况下使用香草,这是一种更有效的方式,所以我想知道我是否只是做了错误的角度部分,或者我是否应该打破这些部分的角度。我以为区域应该比全球操纵表现更好 在屏幕上
同样值得注意的是:我不能从点A开始,然后立即跳到点B,以便让CSS变换绘制动画。动画的可预测性不足以过渡/轻松。除非有一个非常聪明的解决方案,否则我看不出它是如何被动画化的,除了在每一个步骤中滴答作响。我通过使用一个全局滴答器解决了性能问题,而不是让每个组件负责自己的问题。ticker是一个简单的可观察对象,每个组件都订阅和取消订阅它本来可以启动和停止自己的间隔的位置
import {Injectable} from '@angular/core';
import {Observer, Observable} from 'rxjs';
@Injectable()
export class TickerService {
private _observer: Observer<number>;
private _timer:any;
public data$ = new Observable(observer => this._observer = observer).share();
constructor() {
this.data$ = new Observable(observer => {
this._observer = observer;
}).share();
}
public start():void {
if(this._timer) { // not required... just didn't want to have two going at once
this.stop();
}
this._timer = setInterval(() => {
this.tick();
}, 30);
}
public stop():void {
clearInterval(this._timer);
this._timer = 0;
}
private tick():void {
this._observer.next(new Date().getTime()); // the date part is irrelevant. i just wanted to use it to track the performance lag between each tick
}
}
从'@angular/core'导入{Injectable};
从“rxjs”导入{Observer,Observable};
@可注射()
导出类票证服务{
私人观察员:观察员;
私人定时器:任何;
公共数据$=新的可观察对象(观察者=>this.\u观察者=观察者).share();
构造函数(){
this.data$=新的可观察对象(observer=>{
这个._observer=观察者;
}).share();
}
public start():void{
如果(这个._计时器){//不是必需的……只是不想让两个同时运行
这个。停止();
}
这个。_timer=setInterval(()=>{
这个。勾选();
}, 30);
}
公共停止():无效{
clearInterval(此计时器);
这个。_定时器=0;
}
private tick():void{
this._observer.next(new Date().getTime());//日期部分无关紧要。我只想用它来跟踪每个刻度之间的性能延迟
}
}
项目可以对其作出如下反应:
@Component({
selector: 'thingy,[thingy]',
template: `<div #container [ngStyle]="getStyle()"><ng-content></ng-content></div>`
})
export class Thingy implements OnInit, OnDestroy {
private _x:number = 0;
private _y:number = 0;
private _subscription:Subscription;
private _style:CSSStyleDeclaration = {
left: 0,
top: 0,
position: absolute
};
constructor(private _ticker:TickerService){}
ngOnInit() {
this._subscription = this._ticker.data$.subscribe(() => {
this._x++;
this._y = Math.sin(this._x);
this._style.left = this._x + "px";
this._style.top = this._y + "px";
});
this._ticker.start(); // even though every instance will call this, there's a guard in the TickerService to only allow one ticker to run
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
getStyle():CSSStyleDeclaration {
return this._style;
}
}
@组件({
选择器:“thingy,[thingy]”,
模板:``
})
导出类Thingy实现OnInit、OnDestroy{
私有x:number=0;
私有_y:number=0;
私人认购:认购;
私有_样式:CSSStyleDeclaration={
左:0,,
排名:0,
位置:绝对位置
};
构造函数(私有_ticker:TickerService){}
恩戈尼尼特(){
此._订阅=此._ticker.data$.subscribe(()=>{
这个;
this._y=Math.sin(this._x);
this._style.left=this._x+“px”;
this._style.top=this._y+“px”;
});
this._ticker.start();//即使每个实例都会调用它,TickerService中也有一个保护,只允许一个ticker运行
}
恩贡德斯特罗(){
此._订阅。取消订阅();
}
getStyle():CSSStyleDeclaration{
返回此样式;
}
}
这一微小的变化使5件东西的性能从约5fps提高到约60fps。我相信这是因为每种东西都产生了自己的股票代码,导致它自己的(阻塞)摘要/绘画与其他东西的顺序不一致。这导致Angle单独消化每个变化,并形成一个巨大的堆栈。它不是执行5次更新的一次勾选,而是执行5次勾选,每次更新1次
现在,所有更改都在一次摘要/区域更新中进行并执行。出于好奇,您是否尝试过在Angular 2中使用内置渲染器
setElementStyle
,而不是通过ngStyle指令应用样式?我没有尝试过渲染器。我会尝试一下(可能需要几天),然后用我发现的更新。
@ViewChild("container") container:ElementRef;
this._container.nativeElement.styles.top = this._y + "px";
import {Injectable} from '@angular/core';
import {Observer, Observable} from 'rxjs';
@Injectable()
export class TickerService {
private _observer: Observer<number>;
private _timer:any;
public data$ = new Observable(observer => this._observer = observer).share();
constructor() {
this.data$ = new Observable(observer => {
this._observer = observer;
}).share();
}
public start():void {
if(this._timer) { // not required... just didn't want to have two going at once
this.stop();
}
this._timer = setInterval(() => {
this.tick();
}, 30);
}
public stop():void {
clearInterval(this._timer);
this._timer = 0;
}
private tick():void {
this._observer.next(new Date().getTime()); // the date part is irrelevant. i just wanted to use it to track the performance lag between each tick
}
}
@Component({
selector: 'thingy,[thingy]',
template: `<div #container [ngStyle]="getStyle()"><ng-content></ng-content></div>`
})
export class Thingy implements OnInit, OnDestroy {
private _x:number = 0;
private _y:number = 0;
private _subscription:Subscription;
private _style:CSSStyleDeclaration = {
left: 0,
top: 0,
position: absolute
};
constructor(private _ticker:TickerService){}
ngOnInit() {
this._subscription = this._ticker.data$.subscribe(() => {
this._x++;
this._y = Math.sin(this._x);
this._style.left = this._x + "px";
this._style.top = this._y + "px";
});
this._ticker.start(); // even though every instance will call this, there's a guard in the TickerService to only allow one ticker to run
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
getStyle():CSSStyleDeclaration {
return this._style;
}
}