Dynamically create Angular animations

ε祈祈猫儿з 提交于 2019-12-22 06:48:46

问题


I am creating a paging component that slides to next or previous fullscreen page. Because issues with different browsers and devices I have abandoned just using CSS transitions for now. I have a working angular animate solution but the new problem is that it doesn't scale.

import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
    trigger('slideTransition', [
      state('firstPage', style({ transform: 'translateX(0)' })),
      state('secondPage', style({ transform: 'translateX(-100%)' })),
      transition('firstPage=>secondPage', animate('0.6s ease')),
      transition('secondPage=>firstPage', animate('0.6s ease'))
  ])]
})
export class AppComponent {

  state = 'firstPage';

  nextPage() {
    this.state = 'secondPage';
  }

  previousPage() {
    this.state = 'firstShowing';
  }

}

The problem is, as you see, when I have for example 9 pages. I do not want to define 9 states and 18 transitions. How can I do reusable states or generate the states and transitions runtime based on the number of pages? Any ideas?

The template would look something like this

<div class="container">
  <div [@slideTransition]="state" class="page">
    <h1>Page 1</h1>
    <div class="clicker" (click)="nextPage()">clickity</div>
  </div>
  <div [@slideTransition]="state" class="page">
    <h1>Page 2</h1>
    <div class="clicker" (click)="previousPage()">clackity</div>
  </div>
</div>

回答1:


What you need is sending params to the state. This is possible by adding a class member and keep updating it depending on your page number. Then wire that in your HTML.

Now the following is potential additions to your existing code:

animations: [
  trigger('slideTransition', [
    // ...
    state('*',
          style({ marginLeft: '{{pageMarginValue}}%' }), 
          {params: {pageMarginValue: 0}}),
    transition('*=>*', animate('0.6s ease')),
    // ...
])

]

Then add this to your class:

export class AppComponent {
  // ...
  private currentMargin = 0;
  private step = 10; // replace with actual value

  next(): void { this.currentMargin += this.step; }
  previous(): void { this.currentMargin -= this.step; }

  // ...
}

In your HTML, pass the currentMargin like so:

<div [@slideTransition]="{value: state, params: { pageMarginValue: currentMargin }}"></div>



回答2:


I have now found a possible solution. Though because I am using margin-left for the transition the performance isn't as good as it should be.

import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
    trigger('slideTransition', [
      state('previous', style({ marginLeft: '-100%', display: 'none' })),
      state('current', style({ marginLeft: '0' })),
      state('next', style({ display: 'none' })),
      transition('current=>previous', animate('0.6s ease')),
      transition('current=>next', animate('0.6s ease')),
      transition('next=>current', animate('0.6s ease')),
      transition('previous=>current', animate('0.6s ease'))
    ])
  ]
})
export class AppComponent {

  state = ['current', 'next', 'next'];
  current = 0;

  next() {
    this.current = this.current + 1;
    this.updateState();
  }

  previous() {
    this.current = this.current - 1;
    this.updateState();
  }

  private updateState() {
    for (let i = 0; i < this.state.length; i++) {
      if (i < this.current) {
        this.state[i] = 'previous';
      } else if (i === this.current) {
        this.state[i] = 'current';
      } else {
        this.state[i] = 'next';
      }
    }
  }
}

and the template

<div class="the-host">
  <div [@slideTransition]="state[0]" class="fullscreen first">
    <h1>Page 1</h1>
    <div class="clicker" (click)="next()">next</div>
  </div>
  <div [@slideTransition]="state[1]" class="fullscreen second">
    <h1>Page 2</h1>
    <div class="clicker" (click)="previous()">previous</div>
    <div class="clicker" (click)="next()">next</div>
  </div>
  <div [@slideTransition]="state[2]" class="fullscreen third">
    <h1>Page 3</h1>
    <div class="clicker" (click)="previous()">previous</div>
  </div>
</div>


来源:https://stackoverflow.com/questions/44323258/dynamically-create-angular-animations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!