如何解决无法使用 Angular Animations 正确设置 Carousel
我使用 Angular Animations 创建了以下旋转木马:
我创建了 5 个变量来定义每个状态的位置:
但是当我尝试添加更多数据时,有些项目只是从动画中消失了(如上图中的“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 举报,一经查实,本站将立刻删除。