概述
知识点:
- 【css】transform、transition
- 【js】touchstart、touchmove、touchend
原理
拖动的时候改变transfrom: translateX(x)来改变元素的位置
使用transform移动元素时会启用硬件加速渲染画面,性能更好
实现
实现样式
基本样式
1个swiper容器,宽度300px,溢出隐藏
1个swiper,宽度900px
3个swiper-item,宽度300px
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.swiper-wrapper {
width: 300px;
margin: 0 auto;
border: indianred 1px solid;
margin-top: 60px;
}
.swiper {
width: 900px;
display: flex;
}
.swiper-item {
width: 300px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-color: rgb(225, 235, 234);
font-size: 60px;
font-weight: bold;
}
.bg-color-2 {
background-color: rgb(226, 236, 250);
}
</style>
</head>
<body>
<div class="swiper-wrapper">
<div class="swiper" id="swiper">
<div class="swiper-item">1</div>
<div class="swiper-item bg-color-2">2</div>
<div class="swiper-item">3</div>
</div>
</div>
</body>
</html>
复制代码
父容器使用溢出隐藏
.swiper-wrapper {
width: 300px;
margin: 0 auto;
overflow: hidden;
border: indianred 1px solid;
margin-top: 60px;
}
复制代码
隐藏后就无法拖动了,接下来就需要用js实现拖动的效果了。
实现拖动效果
要实现拖动效果,这里通过改变css的transform的translateX属性的值的方式实现拖动效果。
整体思路,拿到滑动的起始点、滑动结束点、计算滑动的长度
实现拖动需要监听触摸的3个事件:touchstart、touchmove、touchend
给swiper添加触摸监听事件
<script>
let swiper = document.getElementById('swiper');
swiper.ontouchstart = e => {
console.log('touchstart', e);
}
swiper.ontouchmove = e => {
console.log('touchmove', e);
}
swiper.ontouchend = e => {
console.log('touchend', e);
}
</script>
复制代码
touchstart和touchend事件
如上图所示,点击一下就会触发2个事件(touchstart和touchend),此时回调函数中打印了e的内容,我们只要拿到changedTouches或者targetTouches数组里的第一个Touch对象就行,这里我们取changedTouches数组的第一个对象,可以看到,这个对象包含了一些屏幕相关的属性,这里我们只处理横向拖动,所以我们只要拿clientX或者pageX的属性就可以了,这里我们去pageX的属性。
拿到触摸起始点
let start = 0; // 触摸起始点
swiper.ontouchstart = e => {
start = e.changedTouches[0].pageX;
console.log('start', start);
}
复制代码
通过touchstart,我们可以拿到第1次触摸的水平位置pageX/clientX
计算滑动距离
接下来看下touchmove
可以看到,移动的时候会一直触发touchmove事件,每移动一个像素点就会触发一次,回调函数中拿到的是Touch对象,该对象中的pageX/clienX属性就是当前位置所在的像素位置。
滑动距离 = 最后1次move的pageX – 触摸起始点
let moveDistance = 0; // 滑动距离
swiper.ontouchmove = e => {
moveDistance = e.changedTouches[0].pageX - start;
console.log('moveDistance', moveDistance);
}
复制代码
这个距离还可以判断滑动方向,从图中可以看到,往右滑动距离是正数,往左滑动,距离是负数。
通过js可以拿到滑动的距离了,接下来就需要动态改变元素的位置(transform: translateX(x))了
改变元素的位置
改变元素的位置,只要将移动的距离设置到translateX里就行了
let moveDistance = 0; // 滑动距离
let moveX = 0; // 元素需移动的距离
swiper.ontouchmove = e => {
moveDistance = e.changedTouches[0].pageX - start;
console.log('moveDistance', moveDistance);
moveX = moveDistance;
// 改变元素的位置
swiper.style = `transform: translateX(${moveX}px);`;
}
复制代码
上面实现了元素跟随鼠标移动的效果,但是有个问题,就是每次重新滑动时都会回到原点,从原点开始滑。
现在解决从原点开始滑的问题,原理就是每次开始滑动时,获取到上一次滑动的位置。
1.标记是否滑动过
- 滑动过
下次滑动开始位置 = 上次滑动结束位置 + 本次滑动的距离
- 未滑动
下次滑动开始位置 = 本次滑动的距离
2.在touchstart的时候赋值上次滑动的距离
<script>
let swiper = document.getElementById('swiper');
let start = 0; // 触摸起始点
let moveDistance = 0; // 滑动距离
let moveX = 0; // 元素需移动的距离
let lastMove = 0; // 上次移动的位置
let isMoved = false; // 标记是否移动过
swiper.ontouchstart = e => {
start = e.changedTouches[0].pageX;
// 拿到上次滑动的距离
lastMove = moveX;
}
swiper.ontouchmove = e => {
// 设置滑动的距离
moveDistance = e.changedTouches[0].pageX - start;
// 重新设置滑动的距离
moveX = isMoved ? (lastMove + moveDistance) : moveDistance;
// 改变元素的位置
swiper.style = `transform: translateX(${moveX}px);`;
// 标记已经滑动
isMoved = true;
}
swiper.ontouchend = e => {
console.log('touchend', e);
}
</script>
复制代码
到这里已经实现了下次滑动从原点开始滑的问题,但是这里还有个问题,就是边界的问题。
可以看到滑动左边或右边边界的时候会拉出白色的区域,并且停留在白色区域的位置,所以我们要做的是处理滑动边界的问题。
处理滑动边界
先观察,swiper里有3个swiper-item,起始位置时0px,结束位置是-600px,往右滑动的时候translateX的值从小变大的,往左滑的时候translateX的值从大变小的。
实现方式很简单,超出边界将滑动距离设置为边界即可。
swiper.ontouchend = e => {
console.log('touchend', e);
// 处理左边界
if(moveX > 0) {
moveX = 0;
}
// 处理右边界
if(moveX < -600) {
moveX = -600;
}
// 更新样式
swiper.style = `transform: translateX(${moveX}px);`;
// 滑动距离恢复为0
moveDistance = 0;
}
复制代码
边界问题处理了,但是效果很生硬,接下来我们来实现边界回弹效果吧
边界回弹也很简单,只有加上过渡效果transition即可。
swiper.ontouchend = e => {
console.log('touchend', e);
// 处理左边界
if(moveX > 0) {
moveX = 0;
}
// 处理右边界
if(moveX < -600) {
moveX = -600;
}
// 更新样式
swiper.style = `transform: translateX(${moveX}px); transition: transform 600ms`;
// 滑动距离恢复为0
moveDistance = 0;
}
复制代码
加上transition: transform 600ms
,边界回弹效果看起来就生动多了。这样边界问题处理好了,但是还有单个swiper-item之间的效果没有处理好。
接下来处理每个swiper-item之间的效果,实现放开拖动时加速滑到下一页效果。
实现放开拖动时加速滑到下一页效果
先观察第2个swiper-item的边界
我们还需要判断滑动方向
当moveDistance > 0时,从左往右滑动(→)
当moveDistance < 0时,从右往左滑动(←)
所以当滑动超出一定阈值时将translateX的值增加到上一个或下一个swiper-item即可。
例如:
当moveX > -200px时(从左往右滑动(→)),将moveX设置为0(即滑动到上一个swiper-item),否则将moveX设置为-300(原来的位置)。
当moveX < -400px时(从右往左滑动(←)),将moveX设置为-600(即滑动到下一个swiper-item),否则将moveX设置为-300(原来的位置)。
swiper.ontouchend = e => {
// 处理左边界
if(moveX > 0) {
moveX = 0;
}
// 处理右边界
if(moveX < -600) {
moveX = -600;
}
// 处理中间swiper-item的边界
if(moveDistance > 0) { // 从左往右滑动(→)
if(moveX > -200) {
// 滑到上一个swiper-item
moveX = 0;
}else {
// 停留在当前swiper-item
moveX = -300;
}
}else if(moveDistance < 0) { // 从右往左滑动(←)
if(moveX < -400) {
// 滑到下一个swiper-item
moveX = -600;
}else {
// 停留在当前swiper-item
moveX = -300;
}
}
// 更新样式
swiper.style = `transform: translateX(${moveX}px); transition: transform 600ms`;
// 滑动距离恢复为0
moveDistance = 0;
}
复制代码
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.swiper-wrapper {
width: 300px;
margin: 0 auto;
overflow: hidden;
border: indianred 1px solid;
margin-top: 60px;
}
.swiper {
width: 900px;
display: flex;
}
.swiper-item {
width: 300px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-color: rgb(225, 235, 234);
font-size: 60px;
font-weight: bold;
}
.bg-color-2 {
background-color: rgb(226, 236, 250);
}
</style>
</head>
<body>
<div class="swiper-wrapper">
<div class="swiper" id="swiper">
<div class="swiper-item">1</div>
<div class="swiper-item bg-color-2">2</div>
<div class="swiper-item">3</div>
</div>
</div>
<script>
let swiper = document.getElementById('swiper');
let start = 0; // 触摸起始点
let moveX = 0; // 元素需移动的距离
let moveDistance = 0; // 滑动距离
let lastMove = 0; // 上次移动的位置
let isMoved = false; // 标记是否移动过
swiper.ontouchstart = e => {
start = e.changedTouches[0].pageX;
console.log('start', start);
// 拿到上次滑动的距离
lastMove = moveX;
}
swiper.ontouchmove = e => {
// 设置滑动的距离
moveDistance = e.changedTouches[0].pageX - start;
// 重新设置滑动的距离
moveX = isMoved ? (lastMove + moveDistance) : moveDistance;
// 改变元素的位置
swiper.style = `transform: translateX(${moveX}px);`;
// 标记已经滑动
isMoved = true;
}
swiper.ontouchend = e => {
console.log('touchend', e);
// 处理左边界
if(moveX > 0) {
moveX = 0;
}
// 处理右边界
if(moveX < -600) {
moveX = -600;
}
// 处理中间swiper-item的边界
if(moveDistance > 0) { // 从左往右滑动(→)
if(moveX > -200) {
// 滑到上一个swiper-item
moveX = 0;
}else {
// 停留在当前swiper-item
moveX = -300;
}
}else if(moveDistance < 0) { // 从右往左滑动(←)
if(moveX < -400) {
// 滑到下一个swiper-item
moveX = -600;
}else {
// 停留在当前swiper-item
moveX = -300;
}
}
// 更新样式
swiper.style = `transform: translateX(${moveX}px); transition: transform 600ms`;
// 滑动距离恢复为0
moveDistance = 0;
}
</script>
</body>
</html>
复制代码
进阶
实现动态计算swiper宽度
把固定的数值换成动态计算的数字即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.swiper-wrapper {
width: 300px;
margin: 0 auto;
overflow: hidden;
border: indianred 1px solid;
margin-top: 60px;
position: relative;
}
.swiper {
/* width: 900px; */
display: flex;
}
.swiper-item {
width: 100%;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-color: rgb(225, 235, 234);
font-size: 60px;
font-weight: bold;
}
.bg-color-2 {
background-color: rgb(226, 236, 250);
}
</style>
</head>
<body>
<div id="swiper-wrapper" class="swiper-wrapper">
<div class="swiper" id="swiper">
<div class="swiper-item">1</div>
<div class="swiper-item bg-color-2">2</div>
<div class="swiper-item">3</div>
</div>
</div>
<script>
let swiperWrapper = document.getElementById('swiper-wrapper'); // swiper容器
let swiper = document.getElementById('swiper'); // swiper
let swiperItems = document.getElementsByClassName('swiper-item'); // swiper-item数组
let swiperItemCount = swiperItems.length; // swiper-item数量
let swiperItemWidth = swiperWrapper.offsetWidth; // 单个swiper-item的宽度
let swiperWidth = swiperWrapper.offsetWidth * swiperItems.length; // 整个swiper的宽度
let swiperWidthStyle = `width: ${swiperWidth}px; `; // swiper宽度样式变量
swiper.style = swiperWidthStyle; // 设置整个swiper的宽度
let rightBound = swiperWrapper.offsetWidth * (swiperItems.length - 1); // 右边界(最后一个swiper-item的起始位置)
let slideThreshold = swiperItemWidth / 4; // 滑动切换的阈值,这里取swiper-item宽度的1/4
let start = 0; // 触摸起始点
let moveX = 0; // 元素需移动的距离
let moveDistance = 0; // 滑动距离
let lastMove = 0; // 上次移动的位置
let isMoved = false; // 标记是否移动过
let currntItemIndex = 0; // 当前是第几个item
swiper.ontouchstart = e => {
start = e.changedTouches[0].pageX;
// 拿到上次滑动的距离
lastMove = moveX;
}
swiper.ontouchmove = e => {
// 设置滑动的距离
moveDistance = e.changedTouches[0].pageX - start;
// 重新设置滑动的距离
moveX = isMoved ? (lastMove + moveDistance) : moveDistance;
// 改变元素的位置
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px);`;
// 标记已经滑动
isMoved = true;
}
swiper.ontouchend = e => {
// 处理左边界
if (moveX > 0) {
moveX = 0;
}
// 处理右边界
if (moveX < -rightBound) {
moveX = -rightBound;
}
// 处理中间swiper-item的边界
if (moveDistance > 0) { // 从左往右滑动(→)
if (moveX > -(swiperItemWidth * currntItemIndex) + slideThreshold) {
// 滑到上一个swiper-item
moveX = -(swiperItemWidth * (currntItemIndex - 1));
} else {
// 停留在当前swiper-item
moveX = -(swiperItemWidth * currntItemIndex);
}
} else if (moveDistance < 0) { // 从右往左滑动(←)
if (moveX < -(swiperItemWidth * currntItemIndex) - slideThreshold) {
// 滑到下一个swiper-item
moveX = -(swiperItemWidth * (currntItemIndex + 1));
} else {
// 停留在当前swiper-item
moveX = -(swiperItemWidth * currntItemIndex);
}
}
// 更新样式
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px); transition: transform 600ms;`;
// 计算当前index
currntItemIndex = Math.abs(Math.round(moveX / swiperItemWidth));
// 滑动距离恢复为0
moveDistance = 0;
}
</script>
</body>
</html>
复制代码
3个swiper-item
5个swiper-item
<div id="swiper-wrapper" class="swiper-wrapper">
<div class="swiper" id="swiper">
<div class="swiper-item">1</div>
<div class="swiper-item bg-color-2">2</div>
<div class="swiper-item">3</div>
<div class="swiper-item bg-color-2">4</div>
<div class="swiper-item">5</div>
</div>
</div>
复制代码
实现指示点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.swiper-wrapper {
width: 300px;
margin: 0 auto;
overflow: hidden;
border: indianred 1px solid;
margin-top: 60px;
position: relative;
}
.swiper {
/* width: 900px; */
display: flex;
}
.swiper-item {
width: 100%;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-color: rgb(225, 235, 234);
font-size: 60px;
font-weight: bold;
}
.bg-color-2 {
background-color: rgb(226, 236, 250);
}
.indicator-wrapper {
position: absolute;
left: 0;
bottom: 20px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.3);
margin: 0 4px;
}
.dot-active {
background-color: rgba(255, 255, 255, 1);
}
</style>
</head>
<body>
<div id="swiper-wrapper" class="swiper-wrapper">
<div class="swiper" id="swiper">
<div class="swiper-item">1</div>
<div class="swiper-item bg-color-2">2</div>
<div class="swiper-item">3</div>
<div class="swiper-item bg-color-2">4</div>
<div class="swiper-item">5</div>
<div class="swiper-item bg-color-2">6</div>
<div class="swiper-item">7</div>
</div>
<div class="indicator-wrapper" id="indicator-wrapper"></div>
</div>
<script>
let swiperWrapper = document.getElementById('swiper-wrapper'); // swiper容器
let swiper = document.getElementById('swiper'); // swiper
let swiperItems = document.getElementsByClassName('swiper-item'); // swiper-item数组
let swiperItemCount = swiperItems.length; // swiper-item数量
let swiperItemWidth = swiperWrapper.offsetWidth; // 单个swiper-item的宽度
let swiperWidth = swiperWrapper.offsetWidth * swiperItems.length; // 整个swiper的宽度
let swiperWidthStyle = `width: ${swiperWidth}px; `; // swiper宽度样式变量
swiper.style = swiperWidthStyle; // 设置整个swiper的宽度
let rightBound = swiperWrapper.offsetWidth * (swiperItems.length - 1); // 右边界(最后一个swiper-item的起始位置)
let slideThreshold = swiperItemWidth / 4; // 滑动切换的阈值,这里取swiper-item宽度的1/4
let start = 0; // 触摸起始点
let moveX = 0; // 元素需移动的距离
let moveDistance = 0; // 滑动距离
let lastMove = 0; // 上次移动的位置
let isMoved = false; // 标记是否移动过
let currntItemIndex = 0; // 当前是第几个item
// 创建指示点
function createIndicator() {
let dot = document.createElement('span');
let indicatorWrapper = document.getElementById('indicator-wrapper');
for(let i = 0; i < swiperItemCount; i++) {
dot.setAttribute('class', `dot ${currntItemIndex === i ? 'dot-active' : ''}`);
indicatorWrapper.appendChild(dot.cloneNode(true));
}
}
// 创建指示点
createIndicator();
swiper.ontouchstart = e => {
start = e.changedTouches[0].pageX;
// 拿到上次滑动的距离
lastMove = moveX;
}
swiper.ontouchmove = e => {
// 设置滑动的距离
moveDistance = e.changedTouches[0].pageX - start;
// 重新设置滑动的距离
moveX = isMoved ? (lastMove + moveDistance) : moveDistance;
// 改变元素的位置
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px);`;
// 标记已经滑动
isMoved = true;
}
swiper.ontouchend = e => {
// 处理左边界
if(moveX > 0) {
moveX = 0;
}
// 处理右边界
if(moveX < -rightBound) {
moveX = -rightBound;
}
// 处理中间swiper-item的边界
if(moveDistance > 0) { // 从左往右滑动(→)
if(moveX > -(swiperItemWidth * currntItemIndex) + slideThreshold) {
// 上一个item
moveX = -(swiperItemWidth * (currntItemIndex - 1));
}else {
// 停留在当前item
moveX = -(swiperItemWidth * currntItemIndex);
}
}else if(moveDistance < 0) { // 从右往左滑动(←)
if(moveX < -(swiperItemWidth * currntItemIndex) - slideThreshold) {
// 下一个item
moveX = -(swiperItemWidth * (currntItemIndex + 1));
}else {
// 停留在当前item
moveX = -(swiperItemWidth * currntItemIndex);
}
}
// 更新样式
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px); transition: transform 600ms;`;
// 计算当前index
currntItemIndex = Math.abs(Math.round(moveX / swiperItemWidth));
// 滑动距离恢复为0
moveDistance = 0;
let dots = document.getElementsByClassName('dot');
for(let i = 0; i < dots.length; i++) {
dots[i].setAttribute('class', `dot ${currntItemIndex === i ? 'dot-active' : ''}`);
}
}
</script>
</body>
</html>
复制代码
实现自动播放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.swiper-wrapper {
width: 300px;
margin: 0 auto;
overflow: hidden;
border: indianred 1px solid;
margin-top: 60px;
position: relative;
}
.swiper {
/* width: 900px; */
display: flex;
}
.swiper-item {
width: 100%;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-color: rgb(225, 235, 234);
font-size: 60px;
font-weight: bold;
}
.bg-color-2 {
background-color: rgb(226, 236, 250);
}
.indicator-wrapper {
position: absolute;
left: 0;
bottom: 20px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.3);
margin: 0 4px;
}
.dot-active {
background-color: rgba(255, 255, 255, 1);
}
</style>
</head>
<body>
<div id="swiper-wrapper" class="swiper-wrapper">
<div class="swiper" id="swiper">
<div class="swiper-item">1</div>
<div class="swiper-item bg-color-2">2</div>
<div class="swiper-item">3</div>
<div class="swiper-item bg-color-2">4</div>
<div class="swiper-item">5</div>
<div class="swiper-item bg-color-2">6</div>
<div class="swiper-item">7</div>
</div>
<div class="indicator-wrapper" id="indicator-wrapper"></div>
</div>
<script>
let swiperWrapper = document.getElementById('swiper-wrapper'); // swiper容器
let swiper = document.getElementById('swiper'); // swiper
let swiperItems = document.getElementsByClassName('swiper-item'); // swiper-item数组
let swiperItemCount = swiperItems.length; // swiper-item数量
let swiperItemWidth = swiperWrapper.offsetWidth; // 单个swiper-item的宽度
let swiperWidth = swiperWrapper.offsetWidth * swiperItems.length; // 整个swiper的宽度
let swiperWidthStyle = `width: ${swiperWidth}px; `; // swiper宽度样式变量
swiper.style = swiperWidthStyle; // 设置整个swiper的宽度
let rightBound = swiperWrapper.offsetWidth * (swiperItems.length - 1); // 右边界(最后一个swiper-item的起始位置)
let slideThreshold = swiperItemWidth / 4; // 滑动切换的阈值,这里取swiper-item宽度的1/4
let start = 0; // 触摸起始点
let moveX = 0; // 元素需移动的距离
let moveDistance = 0; // 滑动距离
let lastMove = 0; // 上次移动的位置
let isMoved = false; // 标记是否移动过
let currntItemIndex = 0; // 当前是第几个item
// 创建指示点
function createIndicator() {
let dot = document.createElement('span');
let indicatorWrapper = document.getElementById('indicator-wrapper');
for(let i = 0; i < swiperItemCount; i++) {
dot.setAttribute('class', `dot ${currntItemIndex === i ? 'dot-active' : ''}`);
indicatorWrapper.appendChild(dot.cloneNode(true));
}
}
// 创建指示点
createIndicator();
swiper.ontouchstart = e => {
start = e.changedTouches[0].pageX;
// 拿到上次滑动的距离
lastMove = moveX;
}
swiper.ontouchmove = e => {
// 设置滑动的距离
moveDistance = e.changedTouches[0].pageX - start;
// 重新设置滑动的距离
moveX = isMoved ? (lastMove + moveDistance) : moveDistance;
// 改变元素的位置
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px);`;
// 标记已经滑动
isMoved = true;
}
swiper.ontouchend = e => {
// 处理左边界
if(moveX > 0) {
moveX = 0;
}
// 处理右边界
if(moveX < -rightBound) {
moveX = -rightBound;
}
// 处理中间swiper-item的边界
if(moveDistance > 0) { // 从左往右滑动(→)
if(moveX > -(swiperItemWidth * currntItemIndex) + slideThreshold) {
// 上一个item
moveX = -(swiperItemWidth * (currntItemIndex - 1));
}else {
// 停留在当前item
moveX = -(swiperItemWidth * currntItemIndex);
}
}else if(moveDistance < 0) { // 从右往左滑动(←)
if(moveX < -(swiperItemWidth * currntItemIndex) - slideThreshold) {
// 下一个item
moveX = -(swiperItemWidth * (currntItemIndex + 1));
}else {
// 停留在当前item
moveX = -(swiperItemWidth * currntItemIndex);
}
}
// 更新样式
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px); transition: transform 600ms;`;
// 计算当前index
currntItemIndex = Math.abs(Math.round(moveX / swiperItemWidth));
// 滑动距离恢复为0
moveDistance = 0;
let dots = document.getElementsByClassName('dot');
for(let i = 0; i < dots.length; i++) {
dots[i].setAttribute('class', `dot ${currntItemIndex === i ? 'dot-active' : ''}`);
}
}
let timer = null;
// 自动切换
function autoplay() {
if(timer) clearInterval(timer);
timer = setInterval(() => {
moveX -= swiperItemWidth;
if(moveX < -rightBound) {
moveX = 0;
}
swiper.style = `${swiperWidthStyle} transform: translateX(${moveX}px); transition: transform 600ms;`;
// 计算当前index
currntItemIndex = Math.abs(Math.round(moveX / swiperItemWidth));
let dots = document.getElementsByClassName('dot');
for(let i = 0; i < dots.length; i++) {
dots[i].setAttribute('class', `dot ${currntItemIndex === i ? 'dot-active' : ''}`);
}
}, 2000);
}
// 自动切换
autoplay();
</script>
</body>
</html>
复制代码