使用animation实现卡片翻转动效,效果如下(iPhone转的gif有卡顿,实际效果流畅):

先上全部代码,再在最后给出代码解析,分步说明实现原理。
html
<div class="visual-card"><div class="contain"><div class="section-box"><div class="card-box"><img src="../../assets/images/1.png" /></div><div class="card-box"><img src="../../assets/images/2.png" /></div><div class="card-box"><img src="../../assets/images/3.png" /></div><div class="card-box"><img src="../../assets/images/4.png" /></div><div class="card-box"><img src="../../assets/images/5.png" /></div><div class="card-box"><img src="../../assets/images/6.png" /></div></div></div>
</div>
less(此代码less版本为4.*,其他版本less自行替换语法,防止报错[Unrecognised input]):
body {background-color: rgb(16, 14, 14);
}/* ------------------------------------* 注释一:设置父级div显示在屏幕正中间* ------------------------------------*/
.visual-card {position: absolute;bottom: 375px;width: 100%;left: 50%;transform: translateX(-50%);
}.contain {margin: 0;padding: 0;/* 设置flex布局 */display: flex;/* 在主轴上居中 */justify-content: center;/* 在测轴上居中 */align-items: center;height: 100%;width: 100%;/* ------------------------------------* 注释五a:透视* ------------------------------------*/perspective: 900px;
}.section-box {width: 300px;height: 400px;position: relative;/* ------------------------------------* 注释五b:所有子元素在3D空间中呈现* ------------------------------------*/transform-style: preserve-3d;/* ------------------------------------* 注释二:设置图片位置及样式* ------------------------------------*/.card-box {position: absolute !important;left: 0;top: 0;width: 100%;height: 100%;display: flex;vertical-align: middle;/* 图片居中 */text-align: center;/* ------------------------------------* 注释三:设置图片倒影* ------------------------------------*/-webkit-box-reflect: below 15px linear-gradient(transparent 10%, rgba(255, 255, 255, 0.3));/* ------------------------------------* 注释六:添加除animation-name外的animation属性* ------------------------------------*/animation-duration: 15s;animation-timing-function: linear;animation-iteration-count: infinite;animation-delay: 3s;img {width: 300px;height: 400px;}}
}/* 以下为animation的关键代码 */
@transforms: rotateY(45deg) translateZ(-800px),rotateY(45deg) translateZ(-600px),rotateY(45deg) translateZ(-400px),rotateY(-45deg) translateZ(-400px),rotateY(-45deg) translateZ(-600px),rotateY(-45deg) translateZ(-800px);/* ------------------------------------* 注释七:设置每个图片的关键动画帧* ------------------------------------*/
// 1. 循环生成@keyframes的核心函数(Less 4.x 兼容版)
.generate-keyframes(@index) when (@index <= 6) {@keyframe-name: ~"dh@{index}";// 计算六个阶段transform的索引(核心:超出长度自动回绕到1)@len: length(@transforms);// 0% 阶段索引 = 当前循环索引@start-index: @index;// 16.66% 阶段索引:当前+1,若等于长度+1则回绕到1@second-index: if(@index + 1 > @len, 1, @index + 1);// 33.32% 阶段索引:当前+2,若超出长度则取模回绕@third-index: if(@index + 2 > @len, @index + 2 - @len, @index + 2);// 49.98% 阶段索引:当前+3,若超出长度则取模回绕@fourth-index: if(@index + 3 > @len, @index + 3 - @len, @index + 3);// 66.64% 阶段索引:当前+4,若超出长度则取模回绕@fifth-index: if(@index + 4 > @len, @index + 4 - @len, @index + 4);// 83.3% 阶段索引:当前+5,若超出长度则取模回绕@end-index: if(@index + 5 > @len, @index + 5 - @len, @index + 5);// 通过变量引用生成@keyframes(Less 4.x 识别此写法)@keyframes @keyframe-name {// 自定义动画逻辑0% {transform: extract(@transforms, @start-index);}8.33% {transform: extract(@transforms, @start-index);}16.66% {transform: extract(@transforms, @second-index);}24.99% {transform: extract(@transforms, @second-index);}33.32% {transform: extract(@transforms, @third-index);}41.65% {transform: extract(@transforms, @third-index);}49.98% {transform: extract(@transforms, @fourth-index);}58.31% {transform: extract(@transforms, @fourth-index);}66.64% {transform: extract(@transforms, @fifth-index);}74.97% {transform: extract(@transforms, @fifth-index);}83.3% {transform: extract(@transforms, @end-index);}91.63% {transform: extract(@transforms, @end-index);}100% {transform: extract(@transforms, @start-index);}}// 递归自增,完成6次循环.generate-keyframes(@index + 1);
}
.generate-keyframes(1);/* ------------------------------------* 注释四:设置每个图片的transform属性值* ------------------------------------*/
.card-box-loop(@index) when (@index <= 6) {// 生成:nth-child选择器(插值语法兼容所有版本).card-box:nth-child(@{index}) {// 从数组中提取对应索引的颜色(核心修复点)transform: extract(@transforms, @index);animation-name: ~"dh@{index}"}// 递归自增(循环核心).card-box-loop(@index + 1);
}// 3. 启动循环(从第1个开始)
.card-box-loop(1);
接下来一步步解析如何实现:
1、设置父级div显示在屏幕正中间(注释一代码),效果如图:

2、设置图片位置及样式,全部居于正中间重叠(注释二代码),效果如图:

3、给图片设置倒影(注释三代码),丰富画面,效果如图:

4、设置每个图片的transform属性值,让图片在动画执行的第一帧位置(注释四代码),效果如图

5、此时所有的图片都在一个2D的空间上展示,效果不明显,若要在3D空间展示,需要在父元素上添加样式属性
perspective(注释五.a代码),子元素添加样式属性transform-style(注释五.b代码),添加后即可看见在Y、Z轴上的旋转,效果如下:

6、给每个需要旋转动画的元素添加上除动画名外的动画属性(注释六代码);
7、设置animation-name,并赋值给对应的元素(注释七代码)。
此效果关键是需要使用perspective配合transform-style: preserve-3d实现旋转交互,其兼容性以及设置倒影box-reflect兼容性如下:



简述box-reflect语法:
box-reflect:direction(方向)、offset(偏移量)和mask-box-image(遮罩图像)
direction:定义倒影的方向,决定了倒影相对于原元素的位置。可选值:above(上方)、below(下方)、left(左侧)和right(右侧)。
offset:定义倒影与原元素之间的偏移距离。可以是数值,百分比,百分比是根据原元素的尺寸来计算的。偏移量可以为负值,表示倒影会向相反方向偏移。
mask-box-image:定义遮罩图像,用于覆盖在倒影上,创造出不同的视觉效果。可以是绝对或相对地址指定的图像,线性渐变或径向渐变创建的图像。如果不设置该值,则倒影将没有遮罩。
以上。