记录一下作轮播图插件的过程...css
效果图html
功能:git
* 可控制是否自动轮播
* 左右箭头切换上一张,下一张,节流处理
* 鼠标放到箭头上,图片中止自动轮播,鼠标移开接着继续播放
* 点击小圆点可跳转到对应顺序的图片
* 移动端可左滑、右滑切换
复制代码
普通轮播图-演示github
普通轮播图-源码数组
如上图所示,假设有三张图片进行轮播,绿色区域是显示区域,其它部分都是隐藏的bash
nowIndex 用来标记当前展现的是第几张图片,初始值为0ide
// 上一张
prevSlider(aniTIme) {
let that = this;
if (this.imgArr.length===1) return;
this.mainDom.style.transition = `left ${aniTIme / 1000}s`
this.mainDom.style.left = `${parseInt(this.mainDom.style.left) + this.moveWidth}px`; // 图片列表div的left值变化
if (this.nowIndex === 0) {
that.nowIndex = (that.imgArr.length-1);
that.setActiveSpot();
setTimeout(function() {
that.mainDom.style.transitionProperty = 'none'; // 悄悄换left值时,要设置这个属性,否则会播放动画
that.mainDom.style.left = `${-that.imgArr.length * that.moveWidth}px`;
}, aniTIme) // 当前展现第一张,上一张再没有了,悄悄把图片列表页left值变化,展现的图片仍是第一张图片
} else {
this.nowIndex--;
this.setActiveSpot();
}
},
// 下一张
nextSlider(aniTIme) {
let that = this;
if (this.imgArr.length===1) return;
this.nowIndex++;
this.mainDom.style.transition = `left ${aniTIme / 1000}s`
this.mainDom.style.left = `${parseInt(this.mainDom.style.left) - this.moveWidth}px`;
if (this.nowIndex === (this.imgArr.length)) {
that.nowIndex = 0;
that.setActiveSpot();
setTimeout(function() {
that.mainDom.style.transitionProperty = 'none';
that.mainDom.style.left = `${-that.moveWidth}px`;
}, aniTIme) // 当前展现最后一张,下一张再没有了,悄悄把图片列表div的left值变化,展现的图片仍是最后一张图片
} else {
this.setActiveSpot();
}
},
// 设置原点样式
setActiveSpot: function() {
for (let i = 0; i < this.swiperSpotDom.childElementCount; i++) {
if (i === Math.abs(this.nowIndex)) {
document.getElementsByClassName('spot-item')[i].style.backgroundColor = '#ff5c1f'
} else {
document.getElementsByClassName('spot-item')[i].style.backgroundColor = '#ccc'
}
}
},
复制代码
eventBind() {
...
// 下一张按钮事件绑定
this.rightBtn.addEventListener('mouseover', function() {
clearInterval(that.timer);
})
this.rightBtn.addEventListener('mouseout', function() {
that.timer = setInterval(that.nextSlider.bind(that, that.aniTIme), that.intervalTime);
})
this.rightBtn.addEventListener('click', function() {
that.throttle(that.nextSlider, 300, 300);
})
...
}
// 节流:时间戳版
throttle(handle, delay, val) {
var now = Date.now();
if (now - this.prev >= delay) {
handle.call(this, val);
this.prev = Date.now();
}
},
复制代码
节流:使事件均匀间隔时间触发布局
这里的节流和其余的节流写的有点不同,能够根据本身的来flex
eventBind() {
...
// 小圆点事件绑定
this.swiperSpotDom.addEventListener('mouseover', function() {
clearInterval(that.timer);
})
this.swiperSpotDom.addEventListener('mouseout', function() {
that.timer = setInterval(that.nextSlider.bind(that, that.aniTIme), that.intervalTime);
})
this.swiperSpotDom.addEventListener('click', function(e) {
e = e || window.event; //这一行及下一行是为兼容IE8及如下版本
  var target = e.target || e.srcElement;
  if (target.tagName.toLowerCase() === "li") {
     var ret = this.querySelectorAll("li");
     let index = Array.prototype.indexOf.call(ret, target);
that.nowIndex = index;
that.setActiveSpot();
that.mainDom.style.transition = `left .8s`
that.mainDom.style.left = `${-(that.nowIndex+1) * that.moveWidth}px`;
  }
})
...
}
复制代码
判断点击的是哪个li, 并把下标值赋给nowIndex,图片列表div(mainDom)的left值变化,更新原点的样式动画
eventBind() {
...
this.mainDom.addEventListener('touchstart', function(e) {
clearInterval(that.timer);
that.startX = e.changedTouches[0].clientX;
that.startY = e.changedTouches[0].clientY;
})
this.mainDom.addEventListener('touchmove', function(e) {
clearInterval(that.timer);
that.endX = e.changedTouches[0].clientX;
that.endY = e.changedTouches[0].clientY;
})
this.mainDom.addEventListener('touchend', function(e) {
if (!that.mainDom.style.transition) {
that.mainDom.style.transition = `left ${that.aniTIme / 1000}s`
}
let angle = that.angle({ X: that.startX, Y: that.startY }, { X: that.endX, Y: that.endY });
if (Math.abs(angle) > 30) return;
if (that.endX > that.startX){ // 右滑
that.prevSlider();
} else { // 左滑
that.nextSlider();
}
that.timer = setInterval(that.nextSlider.bind(that, that.aniTIme), that.intervalTime);
})
...
},
/**
* 计算滑动角度
* @param {Object} start 起点坐标
* @param {Object} end 终点坐标
*/
angle: function (start, end) {
var _X = end.X - start.X,
_Y = end.Y - start.Y
//返回角度 /Math.atan()返回数字的反正切值
return 360 * Math.atan(_Y / _X) / (2 * Math.PI);
}
复制代码
左滑调用nextSlider(),右滑调用prevSlider()
引入slider.js
<div class="swiper-list"></div>
复制代码
let imgArr = [
{
url: '#',
imgPath: '../i.jpg'
},
{
url: '#',
imgPath: '../o.jpg'
},
{
url: '#',
imgPath: '../q.jpeg'
},
{
url: '#',
imgPath: '../w.jpg'
},
{
url: '#',
imgPath: '../z.png'
}
];
// let imgArr = ['i.jpg', 'o.jpg', 'q.jpeg'];
// let imgArr = ['i.jpg', 'o.jpg'];
// let imgArr = ['i.jpg'];
new Swiper({
imgArr: imgArr, // 图片数组
aniTIme: 1000, // 动画执行的时间
intervalTime: 1000, // 图片停留的时间
autoplay: true // 是否自动播放
}).init();
复制代码
css
<style>
ul{padding: 0; list-style: none;}
.swiper-list{
width: 640px;
height: 360px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
.swiper-main {
height: 100%;
position: relative;
overflow: hidden;
}
.swiper-item{
height: 100%;
display: inline;
position: absolute;
}
img {
width: 100%;
height: 100%;
display: block;
}
.swiper-spot{
width: 100%;
height: 15px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 10px;
}
.swiper-spot .spot-item{
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #ccc;
margin-left: 10px;
}
.swiper-spot .spot-item:nth-of-type(1) {
margin-left: 0;
}
.leftBtn{
position: absolute;
left: 15px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
}
.rightBtn{
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
}
</style>
复制代码
功能:
* 可控制是否自动轮播
* 左右箭头切换上一张,下一张,节流处理
* 鼠标放到箭头上,图片中止自动轮播,鼠标移开接着继续播放
* 移动端可左滑、右滑切换
复制代码
与普通轮播图思路相同,不过这个头和末尾分别加了两张图片用来过渡,也是图片移动到临界值时,图片列表div的left值改变,展现的是同一张图片,可是图片列表div的left值不一样
这里的nowIndex默认值为3, 因为头追加了两张图片,要使下标为3的元素是中间的图片,而且没有进行缩放,其他图片是缩小的
prevSlider: function(aniTime) {
// 图片小于三张时特殊处理
if (this.imgArr.length ===2) {
this.nowIndex = this.nowIndex ? 0 : 1;
this.setScale()
} else if (this.imgArr.length ===1) {
return;
} else {
this.nowIndex--;
this.mainDom.style.transition = `left ${aniTime/1000}s`
this.mainDom.style.left = `${parseInt(this.mainDom.style.left)+(this.gap + this.imgWidth)}px`;
if (this.nowIndex === 1) {
this.setScale()
setTimeout(function() {
this.nowIndex = (this.imgArr.length+1);
this.setScale()
this.mainDom.style.transitionProperty = 'none';
this.mainDom.style.left = `${-(parseInt(this.imgDoms[this.nowIndex].style.left) - (this.gap*2 + this.imgWidth))}px`;
}.bind(this), aniTime)
} else {
this.setScale()
}
}
},
nextSlider: function(aniTime) {
// 图片小于三张时特殊处理
if (this.imgArr.length ===2) {
this.nowIndex = this.nowIndex ? 0 : 1;
this.setScale()
} else if (this.imgArr.length ===1) {
return;
} else {
if (this.nowIndex >=2) {
this.mainDom.style.transition = `left ${aniTime/1000}s`
this.mainDom.style.left = `${parseInt(this.mainDom.style.left)-(this.gap + this.imgWidth)}px`;
}
if (this.nowIndex === (this.imgArr.length+1)) {
this.nowIndex = (this.imgArr.length+2);
this.setScale()
setTimeout(function() {
this.nowIndex = 2;
this.setScale()
this.mainDom.style.transitionProperty = 'none';
this.mainDom.style.left = `${-this.imgWidth + this.gap}px`;
}.bind(this), aniTime)
} else {
this.nowIndex++;
this.setScale()
}
}
},
// 设置图片的缩放样式
setScale: function() {
for (let i = 0; i < this.imgDoms.length; i++) {
if (this.imgArr.length ===2) {
this.imgDoms[0].style.left = `${(this.containerWidth/4) - (this.imgWidth/2)}px`;
this.imgDoms[1].style.left = `${(this.containerWidth/4)*3 - (this.imgWidth/2)}px`;
} else if (this.imgArr.length ===1) {
this.imgDoms[i].style.left = `${(this.containerWidth/2) - (this.imgWidth/2)}px`;
} else {
if (i === 0) {
this.imgDoms[i].style.left = `0px`;
} else {
this.imgDoms[i].style.left = `${i * (this.imgWidth + this.gap) - this.gap}px`;
}
}
if (i === this.nowIndex) {
this.imgDoms[i].style.transform = 'scale(1)';
} else {
this.imgDoms[i].style.transform = `scale(${this.scale})`;
}
}
},
复制代码
<div class="swiper-list">
<div class="swiper-main"></div>
<img id="prev" class="leftBtn" src="../left.png" alt="">
<img id="next" class="rightBtn" src="../right.png" alt="">
</div>
复制代码
// 引入slider_card.js
<script src="./slider_card.js"></script>
复制代码
let imgArr = [{
url: '#',
imgPath: '../i.jpg'
},
{
url: '#',
imgPath: '../o.jpg'
},
{
url: '#',
imgPath: '../q.jpeg'
},
{
url: '#',
imgPath: '../w.jpg'
},
{
url: '#',
imgPath: '../z.png'
}
];
// let imgArr = ['i.jpg', 'o.jpg', 'q.jpeg'];
// let imgArr = ['i.jpg', 'o.jpg'];
// let imgArr = ['i.jpg'];
new Swiper({
imgArr: imgArr, // 图片数组
imgWidth: 200, // 图片宽度
aniTime: 1000, // 动画切换时间
intervalTime: 1500, // 停留的时间
scale: 0.8, // 图片缩放
autoplay: true, // 是否自动播放
gap: 0 // 图片之间间隔
}).init();
复制代码
css
<style>
.swiper-list{
height: 200px;
position: relative;
overflow: hidden;
top: 100px;
left: 100px;
border: 1px solid #eee;
padding: 30px 0;
}
.swiper-main{
height: 100%;
position: relative;
}
.swiper-main img{
height: 100%;
display: block;
position: absolute;
top: 0px;
border-radius: 4px;
display: inline-block;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.leftBtn{
position: absolute;
left: 0px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
}
.rightBtn{
position: absolute;
right: 0px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
}
</style>
复制代码