Angular 6 变换动画不会改变元素的样式
Angular 6 Transform Animation doesn't change styles on Element
要点
我正在用 Angular6 创建一个图像滑块,它可以通过拖动来移动。位置通过 transform: translateX(percentage)
更改。当用户不再单击时,我正在为 x 位置设置动画。
问题
显示问题 in this video。
(1) 动画有效但未更改元素的 transform
样式。 (所以动画结束后translateX的值是错误的)
(2)动画一次后,拖动不再起作用(仅在破坏动画时,会导致奇怪的行为)
代码
Html:
<div
class="slider"
(mousedown)="onMouseDown($event)"
(touchstart)="onTouchStart($event)"
(mouseup)="onMouseUp($event)"
(touchend)="onTouchEnd($event)"
(mousemove)="onMouseMove($event)"
(touchmove)="onTouchMove($event)"
(mouseleave)="onMouseLeave($event)"
#slider
>
<div
class="vis-container"
[style.transform]="translateXValue"
[class.grabbing]="grabbing"
[class.grab]="!grabbing"
#container
>
<div
class="item"
*ngFor="let i of images; let j = index"
[style.left]="j * 100 + '%'"
>
<img
dyImagePositioning
src="{{i}}"
>
</div>
</div>
<div>{{translateXValue}}</div>
</div>
打字稿:
images: string[] = [
'https://images.unsplash.com/photo-1533147722845-4078740ae714?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c8e866ca41f36ad560c435c1bb51e0fd&auto=format&fit=crop&w=1350&q=80',
'https://images.unsplash.com/photo-1504415724575-56cef5e3da72?ixlib=rb-0.3.5&s=89c39a767a764693bcc2e2c2ecad59ce&auto=format&fit=crop&w=1350&q=80',
'https://s3.eu-central-1.amazonaws.com/drakery-4/product-files/5b5c8d96823eba53e45ba5ac/5b5c8d9a823eba53e45ba5ad-normal.webp',
];
grabbing: boolean = false;
startX: number;
startXPerc: number;
translateX: number = 0;
animationDurance: number = 300;
@ViewChild('slider') slider;
@ViewChild('container') container;
constructor(
private builder: AnimationBuilder,
) { }
ngOnInit(): void { }
start(pageX: number): void {
this.grabbing = true;
this.startX = pageX - this.slider.nativeElement.offsetLeft;
this.startXPerc = this.translateX;
}
onMouseDown(event: MouseEvent): void {
this.start(event.pageX);
}
onTouchStart(event: TouchEvent): void {
this.start(event.changedTouches[0].pageX);
}
end(): void {
this.grabbing = false;
const endX = Math.round(this.translateX / 100) * 100;
const animationFactory = this.builder.build(this.translate(
this.translateX,
endX,
));
const animationPlayer: AnimationPlayer = animationFactory.create(this.container.nativeElement);
animationPlayer.play();
// Destroying the animation makes it able
// to drag again, but results in weird behaviour
/* animationPlayer.onDone(() => {
animationPlayer.destroy();
}) */
}
onMouseUp(event: MouseEvent): void {
this.end();
}
onTouchEnd(event: TouchEvent): void {
this.end();
}
move(pageX: number): void {
if (!this.grabbing) return;
event.preventDefault();
const x = pageX - this.slider.nativeElement.offsetLeft;
const diff = this.startX - x;
const diffPerc = 100 * diff / this.slider.nativeElement.offsetWidth;
this.translateX = this.startXPerc - diffPerc;
}
onMouseMove(event: MouseEvent): void {
this.move(event.pageX);
}
onTouchMove(event: TouchEvent): void {
this.move(event.changedTouches[0].pageX);
}
onMouseLeave(event: MouseEvent): void {
if (!this.grabbing) return;
this.grabbing = false;
this.end();
}
get translateXValue(): string {
return `translateX(${this.translateX}%)`
}
private translate(startX: number, endX: number): AnimationMetadata[] {
return [
style({ transform: `translateX(${startX}%)` }),
animate(`${this.animationDurance}ms ease-out`, style({ transform: `translateX(${endX}%)` })),
];
}
在您的情况下,我会放弃 angular 动画,而只使用 css 动画。
所以在你的情况下它会是这样的:
.slider
...
transition-duration: 500ms
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1)
我遇到了和你一样的问题。仅销毁动画是不够的,因为样式 属性 被重置为动画之前的状态,因此具有不希望的行为。在 onDone
回调中,您应该在销毁动画之前,将新样式 属性 设置为元素:
// ...
animation.onDone(() => {
this.container.nativeElement.style.transform = this.translate(
this.translateX,
endX,
);
animation.destroy();
});
要点
我正在用 Angular6 创建一个图像滑块,它可以通过拖动来移动。位置通过 transform: translateX(percentage)
更改。当用户不再单击时,我正在为 x 位置设置动画。
问题
显示问题 in this video。
(1) 动画有效但未更改元素的 transform
样式。 (所以动画结束后translateX的值是错误的)
(2)动画一次后,拖动不再起作用(仅在破坏动画时,会导致奇怪的行为)
代码
Html:
<div
class="slider"
(mousedown)="onMouseDown($event)"
(touchstart)="onTouchStart($event)"
(mouseup)="onMouseUp($event)"
(touchend)="onTouchEnd($event)"
(mousemove)="onMouseMove($event)"
(touchmove)="onTouchMove($event)"
(mouseleave)="onMouseLeave($event)"
#slider
>
<div
class="vis-container"
[style.transform]="translateXValue"
[class.grabbing]="grabbing"
[class.grab]="!grabbing"
#container
>
<div
class="item"
*ngFor="let i of images; let j = index"
[style.left]="j * 100 + '%'"
>
<img
dyImagePositioning
src="{{i}}"
>
</div>
</div>
<div>{{translateXValue}}</div>
</div>
打字稿:
images: string[] = [
'https://images.unsplash.com/photo-1533147722845-4078740ae714?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c8e866ca41f36ad560c435c1bb51e0fd&auto=format&fit=crop&w=1350&q=80',
'https://images.unsplash.com/photo-1504415724575-56cef5e3da72?ixlib=rb-0.3.5&s=89c39a767a764693bcc2e2c2ecad59ce&auto=format&fit=crop&w=1350&q=80',
'https://s3.eu-central-1.amazonaws.com/drakery-4/product-files/5b5c8d96823eba53e45ba5ac/5b5c8d9a823eba53e45ba5ad-normal.webp',
];
grabbing: boolean = false;
startX: number;
startXPerc: number;
translateX: number = 0;
animationDurance: number = 300;
@ViewChild('slider') slider;
@ViewChild('container') container;
constructor(
private builder: AnimationBuilder,
) { }
ngOnInit(): void { }
start(pageX: number): void {
this.grabbing = true;
this.startX = pageX - this.slider.nativeElement.offsetLeft;
this.startXPerc = this.translateX;
}
onMouseDown(event: MouseEvent): void {
this.start(event.pageX);
}
onTouchStart(event: TouchEvent): void {
this.start(event.changedTouches[0].pageX);
}
end(): void {
this.grabbing = false;
const endX = Math.round(this.translateX / 100) * 100;
const animationFactory = this.builder.build(this.translate(
this.translateX,
endX,
));
const animationPlayer: AnimationPlayer = animationFactory.create(this.container.nativeElement);
animationPlayer.play();
// Destroying the animation makes it able
// to drag again, but results in weird behaviour
/* animationPlayer.onDone(() => {
animationPlayer.destroy();
}) */
}
onMouseUp(event: MouseEvent): void {
this.end();
}
onTouchEnd(event: TouchEvent): void {
this.end();
}
move(pageX: number): void {
if (!this.grabbing) return;
event.preventDefault();
const x = pageX - this.slider.nativeElement.offsetLeft;
const diff = this.startX - x;
const diffPerc = 100 * diff / this.slider.nativeElement.offsetWidth;
this.translateX = this.startXPerc - diffPerc;
}
onMouseMove(event: MouseEvent): void {
this.move(event.pageX);
}
onTouchMove(event: TouchEvent): void {
this.move(event.changedTouches[0].pageX);
}
onMouseLeave(event: MouseEvent): void {
if (!this.grabbing) return;
this.grabbing = false;
this.end();
}
get translateXValue(): string {
return `translateX(${this.translateX}%)`
}
private translate(startX: number, endX: number): AnimationMetadata[] {
return [
style({ transform: `translateX(${startX}%)` }),
animate(`${this.animationDurance}ms ease-out`, style({ transform: `translateX(${endX}%)` })),
];
}
在您的情况下,我会放弃 angular 动画,而只使用 css 动画。 所以在你的情况下它会是这样的:
.slider
...
transition-duration: 500ms
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1)
我遇到了和你一样的问题。仅销毁动画是不够的,因为样式 属性 被重置为动画之前的状态,因此具有不希望的行为。在 onDone
回调中,您应该在销毁动画之前,将新样式 属性 设置为元素:
// ...
animation.onDone(() => {
this.container.nativeElement.style.transform = this.translate(
this.translateX,
endX,
);
animation.destroy();
});