Угловая, как отложить/разбить анимацию внутри дочерних компонентов
У меня есть дочерний компонент с анимацией
child.component.ts
@Component({
selector: 'child',
animations:[
// animations
]
})
export class ChildComponent { ... }
И родительский компонент, который имеет 2 дочерних компонента в HTML
parent.component.hmtl.ts
...
<child></child>
<child></child>
...
Пример Stackblitz
Чего я хочу добиться, так это ошеломить анимацию дочерних компонентов в родительском компоненте. Поэтому второй дочерний компонент должен запустить анимацию через X секунд.
Похоже, что animateChild() может работать, но я не могу понять, как его использовать. Это правильное решение? Если так, то пример был бы действительно полезен.
заранее спасибо
РЕДАКТИРОВАТЬ: animateChild(), кажется, не работает для этого случая. Очевидно, он работает только с анимациями, которые определены в родительском компоненте.
РЕДАКТИРОВАТЬ 2: Я думаю, что может быть обходной путь, добавив задержку для анимации внутри дочерних компонентов.
child.component.ts
@Component({
selector: 'child',
animations:[
animate(x),
// animations
]
})
export class ChildComponent { ... }
X будет переменной, которая будет увеличиваться для каждого дочернего компонента. Этот обходной путь выглядит мне немного грязно
РЕДАКТИРОВАТЬ 3: ответы до сих пор являются более или менее решением, которое я упомянул во втором моем редактировании. Хотя они работают, я все равно считаю их обходными путями.
Я ищу решение, которое включает только родительский компонент, поэтому дочерний компонент должен оставаться таким же, как в этом нерабочем примере
Ответы
Ответ 1
По угловой документации в анимационной функции.
Второй аргумент, задержка, имеет тот же синтаксис, что и длительность. Например:
Подождите 100 мс, а затем запустите 200 мс: "0,2 с 100 мс"
Полное чтение здесь
Итак, наша цель - передать второй параметр примерно так
animate('2000ms {{delay}}ms'
во-первых, добавьте параметр ввода в дочерний компонент, чтобы мы могли принимать входные значения от родительских:
export class ChildComponent implements OnInit {
@Input() delay: number = 0;
constructor() { }
}
Теперь давайте спустим значение параметра из родительского компонента
<p>child1</p>
<app-child [delay]="0"></app-child>
<p>child2</p>
<app-child [delay]="1000"></app-child>
<p>child2 should have a delay</p>
В вашем дочернем компоненте мы должны передать этот параметр в триггер анимации, чтобы он выглядел следующим образом:
<p [@childAnimation]="{value:'',params:{delay:delay}}">
IIIIIIIIIIIIIIIIII
</p>
И, наконец, мы можем изменить нашу анимацию, чтобы поддержать это значение параметра
animations: [
trigger('childAnimation', [
transition(':enter', [
animate('2000ms {{delay}}ms', style({ transform: 'translateX(80%)' })),
animate('2000ms', style({ transform: 'translateX(0)' })),
], { params: { delay: 0 } })
])
]
теперь все хорошо, теперь вы должны откладывать на входы.
Просмотрите демо здесь
Ответ 2
Это не единственные варианты, но я знаю их. Угловой 7 совместимый.
Рабочая демонстрация Stackblitz
Вариант 1: привязка узла и состояния
В дочернем компоненте объявите состояние анимации как привязку к узлу.
@HostBinding('@animationState') animstate : string = 'preanimationstate';
Затем используйте обычный ввод в дочернем компоненте, чтобы получить задержку:
@Input('delay') delay : number;
Передайте задержку так:
<child-component [delay]="500"></child-component>
Итак, теперь в OnInit вы можете просто использовать таймаут:
let self = this;
window.setTimeout(function () {
self.animstate = 'newstate';
}, self.delay);
Обоснование:
Кажется, что анимированный ребенок также может быть вашей спасительной грацией, но этот путь довольно прост и прост. Надеюсь, поможет.
Вариант 2: переместить анимацию в HostComponent и вручную применить состояние
Вы также можете перенести определение анимации (если оно использует состояния и переходы) с child.component.ts на parent.component.ts, а затем запустите все дочерние компоненты с помощью начального модификатора состояния следующим образом:
<child [@animstate]="initial"></child>>
Затем получите свои элементы через ViewChildren:
@ViewChildren(ChildComponent) childComponents as QueryList<ChildComponent>;
Это доступно с помощью AfterViewInit. Примените свои состояния в init после представления с помощью цикла for/each и функции window.setTimeout
.
Ответ 3
Аутсорсинг - эти ресурсы могут вам помочь.
1.) Существует демо -версия Stackblitz от ZouYouShun, которая показывает, как использовать animateChild().
2.) Анимация Stagger от Coursetro с использованием запроса перехода
3.) Sub Анимация с animateChild из yearmmoo
Ответ 4
На всякий случай, когда кто-то снова наткнется на эту проблему: если вы хотите, чтобы обе анимации играли одновременно, вам просто нужно использовать group
и animateChild
. В принципе, в плункере, связанном в первом посте, вы должны заменить outerTransition
следующим:
const outerTransition = transition('void => *', [
style({opacity: 0}),
group([
animate(2000, style({opacity: 1})),
query('@inner', [
animateChild()
]),
]),
]);