代码之家  ›  专栏  ›  技术社区  ›  Rahul Singh

角场中的跃迁

  •  16
  • Rahul Singh  · 技术社区  · 7 年前

    Stackblitz link

    Design

    现在,我试图实现的是,当应用程序加载时,默认情况下会显示1-2,但当我更改面板时,转换会像例如

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

    谁帮助创建了这个动画这正是我想要的动画- https://imgur.com/a/qZ3vtDb

    1 回复  |  直到 7 年前
        1
  •  7
  •   AleÅ¡ Doganoc    7 年前

    我改变了主意 PanelComponent

    你只需要三个州。当组件最初位于右侧的外侧时为一个。从那里进入视野,这是第二种状态。之后,它移到左边看不见的第三个状态。一旦它从左边看不见了,你就把它移回右边的初始状态,这样它可以在需要的时候回来。

    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';
        }
      }
    }
    

    正如你所看到的,我已经把这条路分开了 setStyle setInViewStyle moveOut . 这个 setInViewStyle 设置面板样式并将其移动到视图中。这个 时差 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;
        }
      }
    

    正如你所看到的,我已经完全改变了逻辑,所以我首先移出必须移除的面板,等待动画完成,然后移入新面板。 StackBlitz sample 它实现了所有这些,因此您也可以看到它正在工作。

    根据评论中的要求,我还提供了另一个双向移动的示例。这使得事情更加复杂。我不得不为另一个方向的移动增加一个过渡。并增加了确定方向的可能性 时差 新面板组件代码:

    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';
      }
    }
    

    面板转换 方法I添加了逻辑来设置向右移动的方向(如果它是第一个面板)。 这是更新的代码:

    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;
      }
    }
    

    还有 StackBlitz sample 对于此实现。

    推荐文章