css3 transform 3d轮播(张鑫旭大大2012年就发布了的动画,我才学会)
首先将大神链接放出来,非常的通俗易懂 https://www.zhangxinxu.com/wordpress/2012/09/css3-3d-transform-perspective-animate-transition/ 其次,放出想要实现的效果。
首先,要实现类似的效果,必须认识到一个属性:rotate(rotateX, rotateY, rotateZ),除了最中间的卡片,旁边的都有一定的旋转角度, 很显然,我们的卡片要围绕着Y轴旋转才会有类似的效果,可类比美女跳钢管舞。 因此,我们要用到的重要属性:rotateY
但是仅仅有rotateY属性会达到我们想要的效果吗?显然不会。 我们给第二个图片一个旋转角度:60deg 它也确实旋转了,但是为什么感觉和我们想要的效果不太一致呢??? 原因就是 视角(perspective)。 perspective决定了你的tranform是2d的还是3d的。而透视点就在浏览器的前方。 (借用张鑫旭大大的图)
除了respective,transalteZ也是一个重要的属性,它会决定元素的大小。translateZ就是元素顺着Z轴的移动,而我们的透视点也在Z轴上。 我们知道近大远小,当translateZ的值越接近(但不超过)perspective的时候,元素越大!就类似于元素已经在你眼前了! 这时最后一件事,还需要给我们舞台元素一个属性:transform-style: preserve-3d; 表示3d透视 最终的基本实现效果如下: 当我们需要的轮播卡片的数量过多时,并且需要给每个卡片设定不同但是有规律的旋转角度时,这时候写css会显得繁琐,且修改起来也存在很大的困难。 因此可尝试使用LESS。
假设我们希望所有的卡片围成一个圈,一共36张卡片,那么360deg/36 = 10deg,每张卡片相较于前一张转动10deg。有如下代码。
.transform-func(@n, @i:1) when (@i <= @n) {
&:nth-child(@{i}) {
@index: @i;
transform: rotateY(10deg * @index) translateZ(5205px);
}
.transform-func(@n, (@i+1))
}
此时我们只需要调用函数的时候将n=36传递过去
@num: 36;
.card {
.transform-func(@num);
}
并且改变变量n的大小和每一张卡片的旋转角度来调整轮播卡片的个数。是不是方便的很呢?
这时我们已经可以得到一个静态的页面了,并且元素是呈现一个圆环的分布,通过一点自己的css修饰效果就会如下: 笔者遇到的动画需求如下:
- 将前面的7张卡片显示出来,后面的是用户看不到的
- 自动轮播
下面我们就要用到javascript来控制它的显示隐藏和轮播了!!
首先让我们看看如何 将前面的7张卡片显示出来(最中间有特殊样式),隐藏剩下的元素
- 我们先给所有元素一个visibility:hidden;让所有的元素都不显示。
- 通过show函数来控制前7个元素显示
function show() {
elements.map((item, index) => {
let end = current + len - 1;
if (end > NUM) {
if(item.id >= current || item.id <= end - NUM) {
item.classList.add('--present')
} else {
item.classList.remove('--present');
}
} else {
if(item.id >= current && item.id <= end) {
item.classList.add('--present');
} else {
item.classList.remove('--present');
}
}
})
elements.map((item, index) => {
if (item.id == activeIndex) {
item.classList.add('--active');
} else {
item.classList.remove('--active');
}
})
}
其中,–present控制前7个元素的样式。 &.–present { visibility: visible; } –active控制最中间的特殊样式。 &.–active { … }
轮播是通过setInterval控制的。其中包含了中心卡片的角度旋转,以及current和activeIndex都++,再通过show函数即可变换显示的卡片。
setInterval(() => {
rotate();
show();
current = current < NUM ? current+1 : 1;
activeIndex ++;
if (activeIndex > NUM) {
activeIndex = 1;
}
}, 3000)
最终即可达到一个走马灯的轮播效果。
|