Angular 6 Transform Animation 不会改变 Element 上的样式

Posted

技术标签:

【中文标题】Angular 6 Transform Animation 不会改变 Element 上的样式【英文标题】:Angular 6 Transform Animation doesn't change styles on Element 【发布时间】:2019-01-10 14:09:12 【问题描述】:

要点

我正在使用 Angular 6 创建一个图像滑块,可以通过拖动来移动它。位置通过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.animationDurancems ease-out`, style( transform: `translateX($endX%)` )),
        ];
    

【问题讨论】:

【参考方案1】:

在您的情况下,我会转储角度动画并简单地使用 css 动画。 所以在你的情况下,它会是这样的:

.slider
    ...
    transition-duration: 500ms
    transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1)

【讨论】:

【参考方案2】:

我和你有同样的问题。仅销毁动画是不够的,因为样式属性会重置为动画之前的状态,因此会出现不良行为。在onDone 回调中,您应该在销毁动画之前,为元素设置新的样式属性:

// ...

animation.onDone(() => 
  this.container.nativeElement.style.transform = this.translate(
    this.translateX,
    endX,
  );
  animation.destroy();
);

【讨论】:

以上是关于Angular 6 Transform Animation 不会改变 Element 上的样式的主要内容,如果未能解决你的问题,请参考以下文章

在 Angular 2+ 中绑定 translateX() 变换

Angular4无效的管道参数

angular自定义管道

scss animaçãoprosoadanimado

css AnimaçãoCapítuloTrocando

Unity即将内置骨骼动画插件Anima2D