ngStyle + анимационный переход - PullRequest
0 голосов
/ 02 июля 2019

Я хочу создать анимацию в Angular 8.0.0, которая выполняет следующие действия, когда пользователь перетаскивает ее по экрану:

  1. элемент уменьшается в течение x мс, для чегоЯ использую анимации;
  2. элемент перетаскивается в положение касания пользователя, для чего я использую ngStyle.

Отдельно, они работают нормально;но когда я объединяю их, анимация переопределяет ngStyle.Как объединить два события?

Файл TS:

import { Component, OnInit, HostListener } from '@angular/core';
import { trigger, state, transition, style, animate, animateChild, group, query } from '@angular/animations';

@Component({
  selector: 'app-action-card',
  templateUrl: './action-card.component.html',
  styleUrls: ['./action-card.component.scss'],
  animations:
  [
        trigger('detailedCardTransition', 
        [
            state('small', style
            ({
                transform : 'translate({{position_x}}px, {{position_y}}px) scale(1) rotate({{rot}}deg)'
            }), {params: {position_x: 0, position_y: 0, rot: 0}}),
            state('large', style(
            {
                margin: '-10vh -5vw 10vh -5vw',
                transform: 'translate({{to_position_x}}px, 40vh) scale(2.5) rotate(0deg)',
            }), {params: {to_position_x: 0, rot: 0}}),
            state('move', style(
            {
                transform : 'translate({{position_x}}px, {{position_y}}px) scale(1.1)'
            }), {params: {position_x: 0, position_y: 0}}),
            state('reset', style(
            {
                transform : 'scale(0)'
            })),
            transition('small => large', 
            [
                group
                ([
                    query('@detailedCardIconTransition', animateChild()),
                    query('@detailedCardExplanationTransition', animateChild()),
                    animate('175ms ease-out')
                ])
            ]),
            transition('large => small, none => small', 
            [
                group
                ([
                    query('@detailedCardIconTransition', animateChild()),
                    query('@detailedCardExplanationTransition', animateChild()),
                    animate('150ms cubic-bezier(.92, -.43, .15, 1.03)')
                ])
            ]),
            transition('large => move', animate('33ms ease-out')),
            transition('small <=> reset', animate('0ms'))
        ]),
        trigger('detailedCardIconTransition',
        [
            state('small', style
            ({
                width: '60%'
            })),
            state('large', style
            ({
                width: '50%'
            })),
            transition('small => large', animate('250ms ease-out')),
            transition('large => small', animate('333ms cubic-bezier(.92, -.43, .15, 1.03)'))
        ]),
        trigger('detailedCardExplanationTransition',
        [
            state('small', style
            ({
                transform: 'scale(0)'
            })),
            state('large', style
            ({
                transform: 'scale(1)'
            })),
            transition('small => large', animate('250ms ease-out')),
            transition('large => small', animate('333ms cubic-bezier(.92, -.43, .15, 1.03)'))
        ])
  ]
})

export class ActionCardComponent implements OnInit 
{
    constructor() { }

    cards = 
    [
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'},
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'},
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'},
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'},
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'},
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'},
        {deg: 0, posX: 0, posY: 0, name: 'Move Forward', icon: '../../assets/images/icon_score.svg', description: 'moves your tank one tile forward.'}
    ];

    slots = [];

    getCardByIndex(index): any 
    {
        return this.cards[index];
    }

    //animations
    state:          String = 'reset';
    detailedCard:   any = {name: '', description: '', icon: ''};

    viewWidth:      number = 0;
    viewHeight:     number = 0;

    detailedPosX:   number;
    positionX:      number;
    positionY:      number;
    startPosX:      number;
    startPosY:      number;
    rotation:       number;

    targetNode:     any;
    animationNode:  any;

    ngOnInit() 
    {
        document.addEventListener('contextmenu', event => event.preventDefault());
        this.animationNode = document.getElementById('override-drag');
        this.viewWidth = document.documentElement.clientWidth;
        this.viewHeight = document.documentElement.clientHeight;

        this.calculateCardsTransform();
        this.calculateSlotsTransform();
    }

    private calculateCardsTransform() : void
    {
        let startPosition = 12;
        let startDegrees = -12;
        for (let i = 0; i < this.cards.length; i++)
        {
            let c = this.cards[i];

            c.posX = startPosition;
            c.posY = this.viewHeight - 100;
            c.deg = startDegrees;
            startPosition += 50;
            startDegrees += 2;

            setInterval(() => 
            {
                //c.deg += 5;
            }, 16);
        }
    }

    onSlotCreated(slotElement, index): void
    {
        this.slots[index].rect = slotElement.getBoundingClientRect();
    }

    private calculateSlotsTransform() : void
    {
        let step = this.viewWidth / 5;
        for (let i = 0; i < 5; i++)
        {
            this.slots[i] = { value: null, posX: step * i + 10, posY: 10 };
        }
    }

    openDetailedCard(card)
    {
        if (this.state === 'reset')
        {
            this.detailedCard = card;
            this.animationNode.style.bottom = 0;
            this.targetNode = card.target;

            this.targetNode.style.opacity = 0;
            let rect = this.targetNode.getBoundingClientRect();
            this.startPosX = rect.x;
            this.startPosY = rect.y;
            this.rotation = card.deg;
            this.detailedPosX = Math.min(Math.max(this.startPosX, .2 * this.viewWidth), this.viewWidth - .25 * this.viewWidth);
            this.state = 'small';
        }
    }

    move: boolean = false;
    @HostListener('touchmove', ['$event'])
    movable_ontouchmove(event: TouchEvent) 
    {
        //this.dragging = true;
        if (!this.move)
            this.state = 'move';

        this.move = true;
        let startPos = this.detailedCard.startDragPosition;
        let touch = event.touches[0];
        this.positionX = touch.clientX - startPos.x;
        this.positionY = touch.clientY - startPos.y;
    }

    @HostListener('touchend', ['$event'])
    mnovable_ontouchend(event: TouchEvent) 
    {
        this.move = false;
        this.state = 'small';
    }

    closeDetailedCard(event)
    {
        if (this.state === 'large')
        {
            this.state = 'small';
        }
        event.stopPropagation();
    }

    detailedCardAnimationEnd(event)
    {
        if (event.toState === 'small')
        {
            if (event.fromState === 'reset')
            {
                this.state = 'large';
            }
            else
            {
                this.animationNode.style.bottom = '';
                this.targetNode.style.opacity = 1;
                this.state = 'reset';
            }
        } else if (event.toState === 'move')
        {
            this.state = 'none';
        }
    }
}

Файл HTML:

<div id="override-drag" class="override-drag">
    <div 
    class="action-card text-dark detailed-action-card"
    [ngStyle]="{'transform': 'translate(' + positionX + 'px, ' + positionY + 'px) scale(1.1)'}"
    [@detailedCardTransition] = "{value: state, params: {position_x: startPosX, position_y: startPosY, to_position_x: detailedPosX, rot: rotation}}"
    (@detailedCardTransition.done) = "detailedCardAnimationEnd($event)">
        <img class="draggable-action-card" src="../../assets/images/image_card_template.png">
        <div class="card-img-overlay">
            <h5 class="text-center action-name">{{detailedCard.name}}</h5>
            <img [@detailedCardIconTransition] = "{value: state}" src={{detailedCard.icon}} class="detailed-action-icon disable-pointer-events"/>
            <h5 [@detailedCardExplanationTransition] = "{value: state}" class="text-center action-explanation">{{detailedCard.description}}</h5>
        </div>
    </div>
</div>
...