Я хочу создать анимацию в Angular 8.0.0, которая выполняет следующие действия, когда пользователь перетаскивает ее по экрану:
- элемент уменьшается в течение x мс, для чегоЯ использую анимации;
- элемент перетаскивается в положение касания пользователя, для чего я использую 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>