微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法使用 Angular Animations 正确设置 Carousel

如何解决无法使用 Angular Animations 正确设置 Carousel

我使用 Angular Animations 创建了以下旋转木马:

enter image description here

我创建了 5 个变量来定义每个状态的位置:

enter image description here

enter image description here

但是当我尝试添加更多数据时,有些项目只是从动画中消失了(如上图中的“Joe”和“Hidde”)。

我正在努力实现以下目标:

(i) 如果数据更多,我需要继续动画(从右侧从无处进入 DOM,我想我们可以使用 ':enter' 和 ':leave' 别名来做到这一点,但不能在这里应用它们。)

(ii) 假设只有两个项目,那么项目应该在“当前”和“下一个”状态之间进行动画处理,但不会移动到最右侧。

这是 Stackblitz link

这是代码

.ts:

animations: [
    trigger("carousel",[
      state(
        "current",style({
          position: "absolute",top: "16%",right: "54%",bottom: "39%",left: "40%"
        })
      ),state(
        "next",top: "51%",right: "77%",bottom: "calc(2% + 3px)",left: "calc(1% + 6px)"
        })
      ),state(
        "futureNext",left: "calc(26% + 5px)"
        })
      ),state(
        "postFutureNext",right: "31%",left: "calc(51% + 5px)"
        })
      ),state(
        "nextToPostFutureNext",right: "8%",left: "calc(76% + 4px)"
        })
      ),transition(
        "current <=> nextToPostFutureNext",animate("2000ms ease-in-out")
      ),transition(
        "nextToPostFutureNext <=> postFutureNext",transition(
        "postFutureNext <=> futureNext",transition("futureNext <=> next",animate("2000ms ease-in-out")),transition("next <=> current",animate("2000ms ease-in-out"))
    ])
  ]
    clearTimeOutvar: any;
      current = 0;
      next = 1;
      futureNext = 2;
      postFutureNext = 3;
      nextToPostFutureNext = 4;

  ngOnInit() {
    this.runSlideShow();
  }

  runSlideShow() {
    this.clearTimeOutvar = setTimeout(() => {
      this.updateAnimationVariables();
      this.runSlideShow();
    },3000);
  }

  updateAnimationVariables() {
    if (this.current === 4) {
      this.current = 0;
    } else if (this.current < 4) {
      this.current++;
    }

    if (this.next === 4) {
      this.next = 0;
    } else if (this.next < 4) {
      this.next++;
    }

    if (this.futureNext === 4) {
      this.futureNext = 0;
    } else if (this.futureNext < 4) {
      this.futureNext++;
    }

    if (this.postFutureNext === 4) {
      this.postFutureNext = 0;
    } else if (this.postFutureNext < 4) {
      this.postFutureNext++;
    }

    if (this.nextToPostFutureNext === 4) {
      this.nextToPostFutureNext = 0;
    } else if (this.nextToPostFutureNext < 4) {
      this.nextToPostFutureNext++;
    }
  }

  ngOnDestroy() {
    clearTimeout(this.clearTimeOutvar);
  }

.html:

<div class="container">
    <div class="header">
        A Simple Carousel
    </div>
    <div class="data">
        <div class="cards" *ngFor="let item of data; let i = index;" [@carousel]="
        i == current ? 'current' :
        i == next ? 'next' : 
        i == futureNext ? 'futureNext' : 
        i == postFutureNext ? 'postFutureNext' : 
        i == nextToPostFutureNext ? 'nextToPostFutureNext' : ''
      ">
            <div class="name">{{ item.name }}</div>
            <div class="age">{{ item.age }}</div>
        </div>
    </div>
</div>

如果我无法解释我的方法中的任何一点,请告诉我。

谢谢。

解决方法

我很难想象你想做什么样的动画。顺便说一句(我希望不要让您感到困惑),您只能通过代码创建动画。有些人喜欢this SO

这个想法是在构造函数中注入动画生成器

  constructor(private builder: AnimationBuilder) {}

在它总是相同之后,我们使用 ViewChildren 获取要动画的元素,使用 ViewChild 获取其他元素

  @ViewChildren("card") items: QueryList<ElementRef>;
  @ViewChild("container") container: ElementRef;
  @ViewChild("dataInit") dataInit: ElementRef;

我们创建了一个函数来计算辅助变量,允许我们计算项目的最终位置

  calculateDimensions() {
    this.rectElement = this.items.first.nativeElement.getBoundingClientRect();
    const rect = this.dataInit.nativeElement.getBoundingClientRect();
    const rectContainer = this.container.nativeElement.getBoundingClientRect();

    this.rect = {};
    this.rect.height = rectContainer.height - rect.y;
    this.rect.y = rect.y;
    this.rect.width = rectContainer.width - this.rectElement.width;
  }

在 ngAfterViewInit 中调用这个函数和一个动画函数

  ngAfterViewInit() {
    this.calculateDimensions();
    this.animateCarousel();
  }

让我们使用 animateCarousel 函数

  animateCarousel() {
    //with each element in ViewChildren
    this.items.forEach((item: ElementRef,index: number) => {

      //I calcule the "order" to change the z-index of the element
      this.order[index] =this.items.length-
        ((index + this.selectedIndex) % this.items.length);

      //Calcule the style final
      const itemStyle = this.getStyle2(index);

      //create an animation using this.builder.build
      const myAnimation = this.builder.build([
        animate(this.timing,style(itemStyle))
      ]);

      //Use a variable "player" declared: private player: AnimationPlayer;
      //and the animation.create over the "nativeElement"
      this.player = myAnimation.create(item.nativeElement);

      //As we want an infinite carousel,with one element (I choose the first)
      if (index == 0)
        //when finish,this.player.onDone(() => {
          this.calculateDimensions(); //recalcule the dimensions
                                      //this makes that if resize the navigator
                                      //the animation works well
                  
          //add or substract the "selectedIndex" using % operator
          //to always gets values from 0 to this.items.length-1
          this.selectedIndex =
            (this.selectedIndex + this.items.length - 1) % this.items.length;

          //and call to the function again
          this.animateCarousel();
        });

       //Finally say player.play()
      this.player.play();
    });
  }

好吧,函数 getStyles 可以是我们想要的,但总是有办法

  getStyle(index: number) {
    //get the "pos" that it's always
    const pos = (index + this.selectedIndex) % this.items.length;

    //now we return the style we want,e.g.
    if (pos == 0)
      return { top: this.rect.y + "px",left: this.rect.width / 2 + "px" };

    return {
      top: this.rect.height - this.rectElement.height / 2 + "px",left: pos * (this.rect.width / this.items.length) + "px"
    };
  }

.html

<div #container class="container">

    <div class="header">
        A Simple Carousel
    </div>
    <!--this div it's only to situate the carousel-->
    <div #dataInit class="data"></div>

    <!--see how change the "z-index"
    <div #card class="cards" [ngStyle]="{'z-index':order[i]}" 
       *ngFor="let item of data; let i = index;">
            <div class="name">{{ item.name }}</div>
            <div class="age">{{ item.age }}</div>
    </div>
</div>

你可以看到the final result

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。