对不起,我想我是作者。我解释得很糟糕的代码。看到你在轮播中看到了 5 个项目,所以画一个圆圈并分成 8 个部分。编号所以最底部为 0,左侧为 1、2、... 一些类似
4
3 5
2 6
1 7
0
动画(您看到的面孔)是 0、1、2、6 和 7
animates = [0, 1,2,6,7];
位置是
movements = [
{ pos: 0, right: [1], left: [7] },
{ pos: 1, right: [2], left: [0] },
{ pos: 2, right: [3,4,5,6], left: [1] },
{ pos: 6, right: [7], left: [5,4,3,2] },
{ pos: 7, right: [0], left: [6] },
];
那个,例如
脸部在位置 0,向右转到位置 1,向左转到位置 7
脸部在位置 1,向右转到位置 1,向左转到位置 0
人脸位于位置 2,右侧为位置 3、4、5 和 6,左侧为位置 1。
好吧,你需要小心,当我们计算角度时,你除以8(不是9)
const animations = mov[direction].map(m => {
const angle = (m * 2 * Math.PI) / 8; //<--see the "8"
....
}
您可以选择,而不是除以 8,除以 16,以使运动更逼真。在这种情况下,您会看到面孔
8
7 9
6 10
5 11
4 12
3 13
2 14
1 15
0
看到在这种情况下可见的面是 0,2,4,12 y 14
animates=[0,2,4,12,14]
职位是
movements = [
{ pos: 0, right: [1,2], left: [15,14] },
{ pos: 2, right: [3,4], left: [1,0] },
{ pos: 4, right: [5,6,7,8,9,10,11,12], left: [3,2] },
{ pos: 12, right: [13,14], left: [11,10,9,8,7,6,5,4] },
{ pos: 14, right: [15,0], left: [13,12] },
];
你需要除以 16
const animations = mov[direction].map(m => {
const angle = (m * 2 * Math.PI) / 16; //<--see the "16"
....
}
我分叉了 stackblitz here
更新轮播仅向左移动,仅一步。如果我们定义其他动作允许左右两步移动,我们可以改进它
movementsTwo=[
{ pos: 0, right: [1,2,3,4], left: [15,14,13,12] },
{ pos: 2, right: [3,4,5,6,7,8,9,10,11,12], left: [1,0,15,14] },
{ pos: 4, right: [5,6,7,8,9,10,11,12,13,14], left: [3,2,1,0] },
{ pos: 12, right: [13,14,15,0], left: [11,10,9,8,7,6,5,4,3,2] },
{ pos: 14, right: [15,0,1,2], left: [13,12,11,10,9,8,7,6,5,4] },
]
并更改函数 animateViews 以允许移动一两步
animateViews(direction: string,steps:number=1) {
this.animates.forEach((x: number, index: number) => {
//here use one or another array
const movements=steps==1?this.movements:this.movementsTwo;
const mov = movements.find(m => m.pos == x);
...
}
这允许我们编写一个函数来“移动到前面”一个元素
indexToFront(index: any) {
index = +index;
const pos = this.animates[+index];
if (pos) {
const mov = this.movements.find((x) => x.pos == pos);
const mov2 = this.movementsTwo.find((x) => x.pos == pos);
const anim = { direction: 'right', steps: 1 };
if (
mov.left[mov.left.length - 1] == 0 ||
mov2.left[mov2.left.length - 1] == 0
)
anim.direction = 'left';
if (
mov2.left[mov2.left.length - 1] == 0 ||
mov2.right[mov2.right.length - 1] == 0
)
anim.steps = 2;
this.animateViews(anim.direction, anim.steps);
}
}
好吧,唯一的就是写一个选择
<select #select (change)="indexToFront(select.value)">
<option *ngFor="let i of [0,1,2,3,4]">{{i}}</option>
</select>
或将(click) 事件添加到我们的“轮播”
<div style="position:relative;margin-top:150px">
<div class="carousel" >
<div #element *ngFor="let i of [0,2,4,12,14];let index=index"
(click)="animates[index]!=0 && indexToFront(index)"
class="carousel__cell">{{index}}
</div>
</div>
我创建another stackblitz
注意:真正“编码”的 movemnet 不太喜欢。如果我有一点时间,我会尝试创建一个组件,但我不能保证什么时候:(
更新 2 我为 5 张图片制作了一个组件伪轮播。主要的变化是,在这一个中,我使用变换来移动“卡片”。所以函数 animateView 就变成了
animateViews(direction: string, steps: number = 1) {
this.animates.forEach((x: number, index: number) => {
const movements = steps == 1 ? this.movements : this.movementsTwo;
const mov = movements.find((m) => m.pos == x);
const item = this.itemsView.find((_x, i) => i == index);
const animations = mov[direction].map((m) => {
const angle = (m * 2 * Math.PI) / 16;
const scale =
(1 + this.minScale) / 2 + ((1 - this.minScale) / 2) * Math.cos(angle);
const applystyle = {
transform:'translate('+
(this.radius * Math.sin(angle)) + 'px,'+
(Math.floor(this.top * scale)-this.top)+'px)
scale('+scale+')',
'z-index': Math.floor(100 * scale),
};
return animate(
this.timer / mov[direction].length + 'ms',
style(applystyle)
);
});
....
});
}
这使得 .css 更简单
.carousel{
display:flex;
margin-left:auto;
margin-right:auto;
margin-top:20px;
}
.carousel::after{
content:' ';
display: block;
clear: both;
}
.carousel>div{
float:left;
margin-right:-100%;
cursor:pointer;
transform-origin: top left;
}
.carousel>div img {
border-radius: 1rem;
box-shadow: 0 .5rem 1rem rgba(0,0,0,.35);
}
因此组件对图像大小的依赖性不大。另请参阅我添加了一个 trasnformY 以给“从上方查看”的感觉
new stackblitz中的变化
注意:目前,如果我们想更改 .css,我们可以使用 styles.css 并编写,例如
.custom .carousel>div img {
border-radius: 50%!important;
border:2px solid white;
}