原生js开发一个swiper
前言
最近没啥事儿干,想着在公司闲着也是闲着,写个轮播图来玩玩儿吧,还没手写过呢,想法有了,再来想想思路,嗯......有几张图片,要知道当前浏览的是哪一个,相邻的之间有个大小透明的差异化,再来两个切换按钮,嗯......就很ok啦,开撸!!!
先看效果图
一个可以左右切换,点击图片切换的轮播图
准备
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>轮播图</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="swiper-wrap">
<div class="prev">
<img src="./image/方向-左-双线.png" alt="" />
</div>
<div class="swiper-content">
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:0
</span>
<img src="./image/1.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:1
</span>
<img src="./image/3.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:2
</span>
<img src="./image/2.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:3
</span>
<img src="./image/4.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:4
</span>
<img src="./image/5.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:5
</span>
<img src="./image/6.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:6
</span>
<img src="./image/7.png" alt="" />
</div>
<div class="swiper-item">
<span style="position: absolute; top: 50px; left: 50px">
index:7
</span>
<img src="./image/8.png" alt="" />
</div>
</div>
<div class="next">
<img src="./image/方向-右-双线.png" alt="" />
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
css
body {
background: rgba(0, 0, 0, 0.7);
}
.swiper-wrap {
position: relative;
width: 1000px;
height: 500px;
}
.swiper-wrap .prev,
.swiper-wrap .next {
position: absolute;
width: 50px;
height: 50px;
cursor: pointer;
z-index: 999;
opacity: 0.5;
}
.swiper-wrap .prev:hover,
.swiper-wrap .next:hover {
opacity: 1;
}
.swiper-wrap .prev img,
.swiper-wrap .next img {
width: 100%;
height: 100%;
}
.swiper-wrap .prev {
top: 50%;
left: 20px;
transform: translateY(-50%);
}
.swiper-wrap .next {
top: 50%;
right: 20px;
transform: translateY(-50%);
}
.swiper-wrap .swiper-content {
perspective: 1000px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.swiper-wrap .swiper-content .swiper-item {
position: absolute;
transition: all 0.33s;
}
.swiper-wrap .swiper-content .swiper-item img {
width: 400px;
height: 300px;
}
js核心逻辑
具体的逻辑实现我在注释中已基本说明,主要就是用transform来改变元素的位置,在加点动画,就完事儿。
js
// 获取按钮每一张轮播图
const swiperItems = document.querySelectorAll('.swiper-item')
// 获取按钮
const prev = document.querySelector('.prev')
const next = document.querySelector('.next')
// 当前显示的索引号
let index = 3
// 布局
const layout = () => {
let xStep = 100 // 水平方向的边偏移
const scaleStep = 0.6 // 缩放的倍数
const opacitytep = 0.4 // 透明度的倍数
const len = swiperItems.length // 轮播图数据的长度
for (let i = 0; i < swiperItems.length; i++) {
const item = swiperItems[i]
const diff = i - index // 计算在显示元素的左边或右边的第几个身位
const sign = Math.sign(diff) // 取正负值 返回 -1 或 1
let offsetX = xStep * diff // 计算与当前显示元素的边偏移
if (i !== index) {
// 这里是为了兼容边偏移距离过近或者过远的补偿,如果倍数与尺寸设计的好,也可以不必这样写,可以直接使用
offsetX = offsetX + 100 * sign
}
// 计算rotate沿y轴的旋转角度,如果是当前显示的则不旋转,旋转45度
// sign为负数则逆时针,为正数则顺时针
// 注意:记得在样式加入perspective属性,好久没写3d了,上了它的鬼日当,不然没有视距差异
const rotate = i === index ? 0 : 45 * (-sign)
// 计算缩放大小,这里一定要取绝对值,不然就是放大了,详细见图形分解
const scale = Math.pow(scaleStep, Math.abs(diff))
item.style.transform = `translateX(${offsetX}px) scale(${scale}) rotateY(${rotate}deg)`
// zIndex的计算与scale同理,可以用任何数值来计算,len可以等于1000,也可以100,主要还是看有没有其他元素层级的影响
item.style.zIndex = len - Math.abs(diff)
// opacity的计算也与scale同理
const opacity = Math.pow(opacitytep, Math.abs(diff))
item.style.opacity = opacity
}
}
// 初始化布局
layout()
// 事件处理,不过多赘述
for (let i = 0; i < swiperItems.length; i++) {
const item = swiperItems[i]
item.addEventListener('click', function () {
index = i
layout()
})
}
prev.addEventListener('click', function () {
index--
if (index < 0) {
index = swiperItems.length - 1
}
layout()
})
next.addEventListener('click', function () {
index++
if (index >= swiperItems.length) {
index = 0
}
layout()
})
这里主要就是运用了数学的幂次方
算法,偏移几个身位,就是多少次方,计算两个相邻的元素的大小,及透明图的变化
计算大小的逻辑实现,图解:
结尾
是不是很简单!!!
别人问我为啥我这个不可以滑动切换,别问,问就是还没想好怎么写,等我想好了再加进来!!!