純js-普通輪播圖、卡片式輪播圖

記錄一下作輪播圖插件的過程...css

效果圖html

普通輪播圖

卡片式輪播圖

普通輪播圖

功能:git

* 可控制是否自動輪播
* 左右箭頭切換上一張,下一張,節流處理
* 鼠標放到箭頭上,圖片中止自動輪播,鼠標移開接着繼續播放
* 點擊小圓點可跳轉到對應順序的圖片
* 移動端可左滑、右滑切換
複製代碼

普通輪播圖-演示github

普通輪播圖-源碼數組

思路:

如上圖所示,假設有三張圖片進行輪播,綠色區域是顯示區域,其它部分都是隱藏的bash

  • 頁面渲染時,會多選擇兩張圖片,圖中數字1,2,3分別表示第幾張圖片,A,B,C,D分別表明不一樣時間的圖片列表div的狀態
  • A矩形框爲頁面啓動時的效果,展現第一張圖片
  • B爲下一張的效果圖,展現第二張圖片
  • 一直下一張直到展現第一張時,如C中所示,這時已是當前圖片列表的最後一張了,因此要將C的狀態變爲D的狀態,展現的仍是第一張圖片,至關於只是悄悄把圖片列表div的left值變化了,展現的圖片並無變仍是第一張圖片
  • 上一張也是相同的思路

頁面佈局

  • class="swiper-list" 這個div爲視口div,大小和圖片的大小相同,其他部分隱藏
  • class="swiper-main" 這個div爲圖片列表div,經過不斷變化left值來切換上一張圖片和下一張圖片
  • 切換下一張圖片時,圖片列表div的left值在原有的基礎上減去一個圖片的寬度
  • 切換上一張圖片時,圖片列表div的left值在原有的基礎上加去一個圖片的寬度

源碼

上一張,下一張核心方法

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及如下版本
	&emsp;&emsp;var target = e.target || e.srcElement;
	&emsp;&emsp;if (target.tagName.toLowerCase() === "li") {
&emsp;&emsp;&emsp;&emsp;    var ret = this.querySelectorAll("li");
&emsp;&emsp;&emsp;&emsp;    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`;
	&emsp;&emsp;}
	})
    
    ...
}
複製代碼

判斷點擊的是哪個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>
複製代碼
相關文章
相關標籤/搜索