源码点击
效果图

目录
1 搭结构
1.1 基本结构
无论3d还是2d轮播图的结构都是相同的,并引入以写图片
<section class="wrapper">
<ul class="carousel">
<li><img src="./images/1.jpg" alt=""></li>
<li><img src="./images/2.jpg" alt=""></li>
<li><img src="./images/3.jpg" alt=""></li>
<li><img src="./images/4.jpg" alt=""></li>
</ul>
</section>
1.2 通过定位让图片折叠起来
- 折叠之后最后一张图片在最上面
- 这里使用了
vh单位 - 开启3d效果
*{
margin: 0;
padding: 0;
}
/* 去除滚动条 */
html,body{
height: 100%;
overflow: hidden;
}
.wrapper{
position: relative;
width: 100%;
height: 100vh;
}
.carousel{
height: 100%;
//开启3d效果
perspective: 1000px;
transform-style: preserve-3d;
li{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
img{
display: block;
width: 100%;
height: 100%;
}
}
}
2 动画
2.1 分析动画
这个动画可以分为
- 消失
- 隐藏
设计到的API
- 移动
translateX - 旋转
rotateY - 缩放
scale
我们观察效果图
移动时
消失:动画中:左移40%,动画末:隐藏到z轴200px处
出现:动画中:右移40%
旋转时
消失:动画中:逆时针30deg
出现:动画中:顺时针30deg
缩放
动画中:都缩放0.8
共分为两组
- 左移消失的同时,右侧出现
- 右侧消失的同时,左侧出现
根据上面的分析,我们写出一下动画
@keyframes leftHide {
0% {visibility: visible;}
50%{transform: translateX(-40%) rotateY(30deg) scale(.8);}
100%{transform: translateZ(-200px);}
}
@keyframes rightShow {
0% {visibility: hidden; transform: translateZ(-200px);}
50%{transform: translateX(40%) rotateY(-30deg) scale(.8);}
100%{}
}
@keyframes leftShow{
0%{visibility: hidden;transform: translateZ(-200px);}
50%{transform: translateX(-40%) rotateY(30deg) scale(.8);}
100%{}
}
@keyframes rightHide{
0%{visibility: visible;}
50%{transform: translateX(40%) rotateY(-30deg) scale(.8);}
100%{transform: translateZ(-200px);}
}
2.2 使用JS操作动画
这里主要用JS来操作属性,这里有两对四个属性
- 他们执行的动画,如下所示
// 第一对
.leftShow{visibility: visible;animation:1s leftShow 1 linear;}
.rightHide{visibility: hidden;animation:1s rightHide 1 linear;}
// 第二对
.leftHide{visibility: hidden;animation:1s leftHide 1 linear;}
.rightShow{visibility: visible;animation:1s rightShow 1 linear;}
- 自动轮播的核心是定时器与活动的样式
const CarliNodes = document.querySelectorAll('.wrapper > .carousel > li')
/* autoIndex 为执行动画的, oldIndex 为同时执行动画的另一张 */
let autoIndex = 0
let oldIndex = 0
setInterval(() => {
autoIndex++
/* autoIndex 不能一直增加 */
if (autoIndex === 4) {
autoIndex = 0
}
CarliNodes[autoIndex].classList.remove('rightHide')
CarliNodes[autoIndex].classList.remove('leftHide')
CarliNodes[autoIndex].classList.remove('leftShow')
CarliNodes[autoIndex].classList.add('rightShow')
CarliNodes[oldIndex].classList.remove('leftShow')
CarliNodes[oldIndex].classList.remove('rightHide')
CarliNodes[oldIndex].classList.remove('rightShow')
CarliNodes[oldIndex].classList.add('leftHide')
/* 新执行动画的变成旧的执行动画 */
oldIndex = autoIndex
}, 2000)
将上面的代码写完后就可以轮播了,但是这个时候有一个缺点,两张图轮播的时候相互折叠,并没有层级(translateZ较大的遮住较小的),这是因为我们的translateZ过于小,景深不够深造成的。

解决
- 将所有的
li隐藏,但是我们必须给第一个图片一个样式,这样不会出现空白的情况,<li class="active"><img src="./images/1.jpg" alt=""></li>当我们再次刷新就不会出现空白的情况了
/* 这个样式一定要卸载 leftHide 前面,不然 leftHide 的样式就会被覆盖掉 */
.active{
visibility: visible;
}
- 把
translateZ(-1500px)/perspective: 2000px;
当我们写有关空间的样式的时候一定要注意景深,深度有多少,可以使用直角三角形大致的估计一下,心里就有一个底
优化
- 我们可以增加以写阴影和圆角,是我们的轮播图更好看些
到这里我们简易版本的3d轮播图大致就写好了
3 指示点
3.1 结构样式
<ul class="indication">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
/* 指示点 */
.indication{
position: absolute;
left: 50%;
bottom: 50px;
display: flex;
transform: translateX(-50%);
li{
width: 60px;
height: 60px;
background-color:rgba(0, 0, 0, .5);
border-radius: 50%;
margin-right: 15px;
box-shadow: 0 0 4px rgba(25, 25, 25, 0.8);
&.active{
background-color: #000;
}
}
}
3.2 动态的样式
我们在定时器内加上
for (let index = 0; index < indicLiNodes.length; index++) {
indicLiNodes[index].classList.remove('active')
}
indicLiNodes[autoIndex].classList.add('active')
为了优化效果,我们应该在第一个li标签上加上此样式
<li class="active"></li>
4 点击监听
为每个按钮绑定点击监听,绑定之前一定要先清楚定时器
for (let index = 0; index < indicLiNodes.length; index++) {
const element = indicLiNodes[index];
/* 指示点样式 */
element.onclick = function () {
console.log('click')
clearInterval(setIntervalId)
for (let index = 0; index < indicLiNodes.length; index++) {
indicLiNodes[index].classList.remove('active')
}
this.classList.add('active')
}
4.1 方向判断
这里有两种情况,把这种判断写在点击监听函数内
/* 轮播图跳转 */
if (index > oldIndex) {
CarliNodes[index].classList.remove('rightHide')
CarliNodes[index].classList.remove('leftHide')
CarliNodes[index].classList.remove('leftShow')
CarliNodes[index].classList.add('rightShow')
CarliNodes[oldIndex].classList.remove('leftShow')
CarliNodes[oldIndex].classList.remove('rightHide')
CarliNodes[oldIndex].classList.remove('rightShow')
CarliNodes[oldIndex].classList.add('leftHide')
}
if (index < oldIndex) {
CarliNodes[index].classList.remove('rightHide')
CarliNodes[index].classList.remove('leftHide')
CarliNodes[index].classList.remove('rightShow')
CarliNodes[index].classList.add('leftShow')
CarliNodes[oldIndex].classList.remove('leftHide')
CarliNodes[oldIndex].classList.remove('leftShow')
CarliNodes[oldIndex].classList.remove('rightShow')
CarliNodes[oldIndex].classList.add('rightHide')
}
oldIndex = index
autoIndex = index
我们就实现了点击翻转到相应的图片
5 鼠标移入效果
当鼠标移入轮播图时,不再轮播,移除轮播图示再次轮播
- 这个效果其实挺简单,当我们鼠标移入是清楚定时器
- 鼠标移除是,再次运行轮播函数
所以这里要求我们要将轮播代码分装成一个函数
/* 将轮播图代码封装成一个函数 */
carouselPlay()
function carouselPlay() {
/* 在开启定时器之前清除定时器 */
clearInterval(setIntervalId)
setIntervalId = setInterval(() => {
console.log(autoIndex)
autoIndex++
/* autoIndex 不能一直增加 */
if (autoIndex === CarliNodes.length) {
autoIndex = 0
}
for (let index = 0; index < indicLiNodes.length; index++) {
indicLiNodes[index].classList.remove('active')
}
indicLiNodes[autoIndex].classList.add('active')
CarliNodes[autoIndex].classList.remove('leftShow')
CarliNodes[autoIndex].classList.remove('leftHide')
CarliNodes[autoIndex].classList.remove('rightHide')
CarliNodes[autoIndex].classList.add('rightShow')
CarliNodes[oldIndex].classList.remove('leftShow')
CarliNodes[oldIndex].classList.remove('rightShow')
CarliNodes[oldIndex].classList.remove('rightHide')
CarliNodes[oldIndex].classList.add('leftHide')
/* 新执行动画的变成旧的执行动画 */
oldIndex = autoIndex
/* 定时器时间 - 执行动画使劲啊 = 照片停留时间 */
}, 4000)
}
鼠标移入效果
主要是为ul绑定鼠标移入移出事件
carouselNode.onmouseenter = function () {
clearInterval(setIntervalId)
}
carouselNode.onmouseleave = function () {
carouselPlay()
}
6 优化
6.1 鼠标指针的优化
可点指示点鼠标移入是手,不可点击时箭头
li{
width: 60px;
height: 60px;
background-color:rgba(225, 225, 225, .5);
border-radius: 50%;
margin-right: 15px;
box-shadow: 0 0 4px rgba(25, 25, 25, 0.8);
cursor: pointer;
&.active{
background-color: #fff;
/* 改变鼠标指针 */
cursor: default;
}
}
本文详细介绍了一种基于HTML、CSS和JavaScript实现的3D轮播图制作过程,包括结构搭建、动画设置、指示点样式及点击监听等功能,旨在帮助前端开发者掌握3D轮播图的制作技巧。
1097

被折叠的 条评论
为什么被折叠?



