角度转换

Rah*_*ngh 16 css-transitions angular angular-animations

我已经在Angular中创建了一个布局管理器,它可以接收组件,然后在视图中显示它,并在视图中显示每个组件时将动画添加到视图中.

在单个时刻,可以在视图中显示一个面板或最多两个面板.

这是Stackblitz link同样的问题,这是过渡不平滑,它也显示为流线型,因为它应该是设计如下.

设计

现在我想要实现的是当应用程序加载1-2时默认显示但是当我更改面板时,转换会像

1-3当2移动到视野之外它应该向左滑动和缓和而且3应该进入并且缓和.然后,如果从1-3开始我们进入2-3 1应该向右缓和,2应该滑入.

此外,面板可以占屏幕宽度的一些百分比(33%,66%或100%).

我不确定我是否能够正确地解释它我已经被困在这几个星期过渡如果有人可以帮助它会很棒,谢谢

感谢萨达姆帮助创建了这个动画,这正是我想要的动画 - https://imgur.com/a/qZ3vtDb这仅用于视觉目的

Ale*_*esD 7

我已经更改了PanelComponentStackBlitz示例,以便按照提供的动画显示的方式工作.

你只需要三个州.一个组件最初位于右侧外侧.从那里它进入视野这是第二个状态.之后,它向左移动到第三个状态.一旦它离开左侧视图,您将其移回正确的初始状态,以便在需要时可以返回.

以下是更改的面板组件的代码:

import { Component, ContentChild, QueryList,HostBinding,Input,ElementRef } from '@angular/core';
import {
  trigger,
  state,
  style,
  animate,
  transition
} from '@angular/animations';

@Component({
  selector: 'my-panel',
  templateUrl: './panel.component.html',
  styleUrls:['./panel.component.css'],
  animations: [
    trigger('transition', [
      state('right', style({
        transform: 'translateX(100%)',
        opacity: 0
      })),
      state('inview', style({
      })),
      state('left', style({
        transform: 'translateX(-100%)',
        opacity: 0
      })),
      transition('right => inview', [
        animate(`${PanelComponent.ANIMATION_DURATION}ms 0ms ease-out`,style({ 
          transform: 'translateX(0)',
          opacity: 1 }))
      ]),
      transition('inview => left', [
        animate(`${PanelComponent.ANIMATION_DURATION}ms 0ms ease-in`,style({ 
          transform: 'translateX(-100%)',
          opacity: 0 }))
      ])
    ])]
})
export class PanelComponent  {
  public static readonly ANIMATION_DURATION = 500;
  @Input() destroyOnHidden: boolean = false;
  @Input() id : string = null;
  @ContentChild('layout') contentChild : QueryList<ElementRef>;
  @HostBinding('style.width') componentWidth = null;
  @HostBinding('style.height') componentHeight = null;
  @HostBinding('style.overflow') componentOverflow = null;
  public state: string = null;

  public getId() {
    return this.id;
  }

  constructor() {
    this.state = 'right';
  }

  public setInViewStyle(width: string, height: string, overflow: string): void {
    this.componentWidth = width + '%';
    this.componentHeight = height + '%';
    this.componentOverflow = overflow;
    this.state = 'inview';
  }

  public setDefault(): void {
    this.state = 'right';
  }

  public moveOut(): void {
    this.state = 'left';
  }


  public transitionDoneHide(): void {
    if(this.state === 'right') {
      console.log('hiding transition done');
      this.componentWidth = '0' + '%';
      this.componentHeight = '0' + '%';
      this.componentOverflow = 'hidden';
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

正如你看到的我已经分裂setStyle成两个方法setInViewStyle和moveOut.该setInViewStyle套面板风格,它移动到视图.该moveOut方法将面板移出视图左侧.因此我也改变了布局管理器方法panelTransformation.

这是更改的代码:

panelTransformation(transitions) {
    if (transitions) {
      let movement = null;
      let panelsToRemove = [];
      let panelsToAdd = [];
      if (this.previousPanels) {
        panelsToRemove = this.previousPanels.filter((panel) => transitions.panel.indexOf(panel) < 0);
        panelsToAdd = transitions.panel.filter((panel) => this.previousPanels.indexOf(panel) < 0);
      } else {
        panelsToAdd = transitions.panel
      }

      if (panelsToRemove.length > 0) {
        for (let panelToRemove of panelsToRemove) {
          this.idPanelMap.get(panelToRemove).moveOut();
        }
        // wait for fade out to finish then start fade in
        timer(PanelComponent.ANIMATION_DURATION + 100).subscribe(() => {
          for (let panelToAdd of panelsToAdd) {
            this.idPanelMap.get(panelToAdd).setInViewStyle(transitions.width[transitions.panel.indexOf(panelToAdd)], '100', 'initial');
          }
          for (let panelToRemove of panelsToRemove) {
            this.idPanelMap.get(panelToRemove).setDefault();
          }
        });
      } else { // first time so just fade in
        for (let panelToAdd of panelsToAdd) {
          this.idPanelMap.get(panelToAdd).setInViewStyle(transitions.width[transitions.panel.indexOf(panelToAdd)], '100', 'initial');
        }
      }

      this.previousPanels = transitions.panel;
    }
  }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我已完全更改了逻辑,因此我首先移出必须删除的面板,等待动画完成,然后移动到新面板中.这是我的StackBlitz示例的链接,它实现了所有这些,因此您也可以看到它正常工作.

根据评论中的要求,我还提供了另一个双向移动的样本.这使事情变得更加复杂.我不得不为另一个方向的移动添加一个过渡.并增加了在moveOut方法中设置方向的可能性.在我看来,它看起来不太好,因为它可能有一些闪烁.新面板组件代码:

import { Component, ContentChild, QueryList,HostBinding,Input,ElementRef } from '@angular/core';
import {
  trigger,
  state,
  style,
  animate,
  transition
} from '@angular/animations';
import { timer } from 'rxjs';

@Component({
  selector: 'my-panel',
  templateUrl: './panel.component.html',
  styleUrls:['./panel.component.css'],
  animations: [
    trigger('transition', [
      state('right', style({
        transform: 'translateX(100%)',
        opacity: 0
      })),
      state('inview', style({
      })),
      state('left', style({
        transform: 'translateX(-100%)',
        opacity: 0
      })),
      transition('right => inview', [
        animate(`${PanelComponent.ANIMATION_DURATION}ms 0ms ease-out`,style({ 
          transform: 'translateX(0)',
          opacity: 1 }))
      ]),
      transition('inview => left', [
        animate(`${PanelComponent.ANIMATION_DURATION}ms 0ms ease-in`,style({ 
          transform: 'translateX(-100%)',
          opacity: 0 }))
      ]),
      transition('inview => right', [
        animate(`${PanelComponent.ANIMATION_DURATION}ms 0ms ease-in`,style(         { 
          transform: 'translateX(100%)',
          opacity: 0
       }))
      ]),
      transition('left => inview', [
        animate(`${PanelComponent.ANIMATION_DURATION}ms 0ms ease-out`,style({ 
          transform: 'translateX(0)',
          opacity: 1 }))
      ])
    ])]
})
export class PanelComponent  {
  public static readonly ANIMATION_DURATION = 500;
  public static readonly ANIMATION_DELAY = 100;
  @Input() destroyOnHidden: boolean = false;
  @Input() id : string = null;
  @ContentChild('layout') contentChild : QueryList<ElementRef>;
  @HostBinding('style.width') componentWidth = null;
  @HostBinding('style.height') componentHeight = null;
  @HostBinding('style.overflow') componentOverflow = null;
  public state: string = null;
  private lastDirection: 'left' | 'right';

  public getId() {
    return this.id;
  }

  constructor() {
    this.state = 'right';
  }

  public setInViewStyle(width: string, height: string, overflow: string): void {
    this.componentWidth = width + '%';
    this.componentHeight = height + '%';
    this.componentOverflow = overflow;
    this.state = 'inview';
  }

  public setDefault(): void {
    this.state = 'right';
  }

  public moveOut(direction: 'left' | 'right'): void {
    this.lastDirection = direction;
    this.state = direction;
  }


  public transitionDoneHide(): void {
    if(this.state === this.lastDirection) {
      if (this.lastDirection === 'right') {
        timer(PanelComponent.ANIMATION_DELAY).subscribe(() => this.hide());
      } else {
        this.hide();
      }
      console.log('hiding transition done');

    }
  }

  private hide() {
    this.componentWidth = '0' + '%';
    this.componentHeight = '0' + '%';
    this.componentOverflow = 'hidden';
  }
}
Run Code Online (Sandbox Code Playgroud)

在panelTransformation方法中,我添加了逻辑来设置向右移动的方向,如果它是第一个面板.这是更新的代码:

panelTransformation(transitions) {
  if (transitions) {
    let movement = null;
    let panelsToRemove = [];
    let panelsToAdd = [];
    if (this.previousPanels) {
      panelsToRemove = this.previousPanels.filter((panel) => transitions.panel.indexOf(panel) < 0);
      panelsToAdd = transitions.panel.filter((panel) => this.previousPanels.indexOf(panel) < 0);
    } else {
      panelsToAdd = transitions.panel
    }

    if (panelsToRemove.length > 0) {
      for (let panelToRemove of panelsToRemove) {
        let direction: 'left' | 'right' = 'left';
        // if it is the first panel we move out right
        if (this.previousPanels.indexOf(panelToRemove) === 0) {
          direction = 'right';
        }
        this.idPanelMap.get(panelToRemove).moveOut(direction);
      }
      // wait for fade out to finish then start fade in
      timer(PanelComponent.ANIMATION_DURATION + PanelComponent.ANIMATION_DELAY).subscribe(() => {
        for (let panelToAdd of panelsToAdd) {
          this.idPanelMap.get(panelToAdd).setInViewStyle(transitions.width[transitions.panel.indexOf(panelToAdd)], '100', 'initial');
        }
        for (let panelToRemove of panelsToRemove) {
          this.idPanelMap.get(panelToRemove).setDefault();
        }
      });
    } else { // first time so just fade in
      for (let panelToAdd of panelsToAdd) {
        this.idPanelMap.get(panelToAdd).setInViewStyle(transitions.width[transitions.panel.indexOf(panelToAdd)], '100', 'initial');
      }
    }

    this.previousPanels = transitions.panel;
  }
}
Run Code Online (Sandbox Code Playgroud)

还有用于此实现的StackBlitz示例.