vue專案中用better-scroll製作輪播圖
阿新 • • 發佈:2018-12-06
主要html架構
<!- slider元件 -> <div class="slider-wrapper" ref="sliderWrapper"> <div class="slider-ul" ref="sliderUl"> <div class="slider-li" v-for="(item,index) in imgDatas"> <a href="#"> <img src="#"> </a> </div> </div> </div>
解釋:
- slider-wrapper是外層容器,它的寬度是更外層容器的寬度,比如在父元件中
<!- 父元件 ->
<div class="parent-box">
<!- slider-wrapper繼承,撐滿parent-box的寬度 -->
<slider></slider>
</div>
- slider-ul是圖片組ul的寬度,寬度是slider-li的數量 * slider-li的width
- slider-li是一個圖片項
- imgDatas是圖片的資料陣列
主要CSS程式碼
/* slider元件的主要CSS程式碼 */ .slider-wrapper { position: relative; width: 100%; /*撐滿父容器*/ height: 100%; /*撐滿父容器*/ min-height: 1px; overflow: hidden; } .slider-ul { /* mounted的時候設定ul的寬度,設定方法是100% x 多少個圖片item,如5個圖片項則是500% */ /* 如果是假資料進行樣式設定除錯,可以先設定width為多少個100% */ position: relative; white-space: nowrap; overflow: hidden; /*清除浮動*/ height: 100%; } .slider-li { /* 同樣是 mounted時設定一個item的寬度,寬度要和slider-wrapper的寬度一樣,則 500% * 0.2 = 100% */ /* 同樣是假資料的樣式除錯的時候,可以先設定width,如slider-wrapper為100%,slider-ul為500%,即有五張圖片,此時設定slider-li的width為20%,500 * 0.2 = 100,則和slider-wrppaer寬度一致 */ height: 100%; float: left; /*要設定浮動*/ box-sizing: border-box; overflow: hidden; } .slider-li a { overflow: hidden; width: 100%; height: 100%; display: block; } .slider-li img { width: 100%; height: 100%; display: block; }
元件主要部分
- 安裝:npm install better-scroll --save
- 在slider元件中引入:import BScroll from ‘better-scroll’
// props,父元件傳入子元件的引數
props: {
loop: { //是否迴圈播放
type: Boolean,
default: true
},
autoPlay: { //是否自動播放
type: Boolean,
default: true
},
interVal: { //輪播一張圖片的時間
type: Number,
default: 3000
},
imgDatas: { //傳入的imgDatas資料
type: Array,
default: []
}
}
//主要內建資料
data() {
return {
currentPageIndex: 0 //記錄當前是哪一張輪播圖圖片,下標從0開始,即第一張
}
}
//methods
methods:{
//第一步,根據傳入的imgDatas初始化slider-ul,slider-li的寬度,為百分比
//注意,better-scroll在初始化時,當你設定了loop的時候,會在前後自動增加2張圖片,例如5張圖片會變成7張
//由於這是第一步,暫時沒有初始化better-scroll,所以獲取children的時候,只是5張圖片,props的loop為true時,要加多兩個,然後設定ul,li的寬度
_setUlWidth() {
this.children = this.$refs.sliderUl.children
let childrenLength = this.loop ? this.children.length + 2 : this.children.length
this.$refs.sliderUl.style.width = childrenLength * 100 + '%'
for (var i = 0; i < this.children.length; i++) {
this.children[i].style.width = 100 / childrenLength + '%'
}
},
//第二步,初始化better-scroll
_initSlider() {
let that = this
this.slider = new BScroll(this.$refs.sliderWrapper, {
scrollX: true,
scrollY: false,
momentum: false,
snap: {
loop: this.loop,
threshold: 0.3,
speed: 400
},
probeType: 2
})
//監聽scroll結束的時候,賦值更新currentPageIndex
this.slider.on('scrollEnd', () => {
clearInterval(that.timer)
that.currentPageIndex = that.slider.getCurrentPage().pageX
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
that._setAutoplay()
})
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
//無縫
this.checkScroll(childrenLength,this.$refs.sliderWrapper.offsetWidth)
},
//第三步,設定自動播放
//這一步不需要重新設定currentPageIndex ,因為轉到下一頁時觸發了scrollEnd事件,已經自動賦值更新
_setAutoplay() {
let goToIndex = this.currentPageIndex + 1
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
//設定右滑到最後一張的無縫切換,返回到第一張
if (goToIndex >= childrenLength) {
goToIndex = 0
}
this.timer = setInterval(() => {
this.slider.goToPage(goToIndex, 0, 400)
}, this.interVal)
},
//監聽滑事件
checkScroll(childrenLength,itemWidth) {
let that = this
this.slider.on('scroll', () => {
clearInterval(that.timer)
let leftScroll = parseInt(that.$refs.sliderUl.style['transform'].substring(10, 15))
let left = -1 * itemWidth
let right = left * childrenLength
if (leftScroll >left) {
that.slider.goToPage(childrenLength, 0, 400)
}else if(leftScroll < right) {
that.slider.goToPage(1, 0, 400)
}
})
}
},
mounted() {
setTimeout(() => {
this._setUlWidth()
this._initSlider()
this._setAutoplay()
}, 20)
window.addEventListener('resize', () => {
if (!this.slider) {
return
}
this._setUlWidth()
})
}
這樣已經可以輪播了哦,更詳細的樣式和功能程式碼看下面的原始碼
原始碼
使用說明:
<div style="width:400px;height:280px;">
<slider :imgDatas="imgDatas"></slider>
</div>
imgDatas: [
{ imgSrc: require("./images/1.jpg"), linkUrl: '#' },
{ imgSrc: require("./images/2.jpg"), linkUrl: '#' },
{ imgSrc: require("./images/3.jpg"), linkUrl: '#' },
{ imgSrc: require("./images/4.jpg"), linkUrl: '#' },
]
<template>
<div class="slider-wrapper" ref="sliderWrapper">
<div class="slider-ul" ref="sliderUl">
<div class="slider-li" v-for="(item,index) in imgDatas" :key="index">
<a :href="item.linkUrl">
<img :src="item.imgSrc">
</a>
</div>
</div>
<div class="dots">
<span
:key="'b'+index"
v-for="(item,index) in imgDatas"
:class="{'dot-active' : currentPageIndex == index}"
@click="linkToPage(index)"
></span>
</div>
<div class="arrow left-arrow" @click="scrollbtnEvent('left')">
<span class="iconfont icon-xiangzuo"></span>
</div>
<div class="arrow right-arrow" @click="scrollbtnEvent('right')">
<span class="iconfont icon-xiangyou-copy"></span>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
export default {
props: {
loop: {
type: Boolean,
default: true
},
autoPlay: {
type: Boolean,
default: true
},
interVal: {
type: Number,
default: 3000
},
imgDatas: {
type: Array,
default: []
}
},
data() {
return {
currentPageIndex: 0
}
},
mounted() {
setTimeout(() => {
this._setUlWidth()
this._initSlider()
this._setAutoplay()
}, 20)
window.addEventListener('resize', () => {
if (!this.slider) {
return
}
this._setUlWidth()
})
},
methods: {
//初始化wrapper的寬度
_setUlWidth() {
this.children = this.$refs.sliderUl.children
let childrenLength = this.loop ? this.children.length + 2 : this.children.length
this.$refs.sliderUl.style.width = childrenLength * 100 + '%'
for (var i = 0; i < this.children.length; i++) {
this.children[i].style.width = 100 / childrenLength + '%'
}
},
//播放
_setAutoplay() {
let goToIndex = this.currentPageIndex + 1
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
if (goToIndex >= childrenLength) {
goToIndex = 0
}
this.timer = setInterval(() => {
this.slider.goToPage(goToIndex, 0, 400)
}, this.interVal)
},
//初始化better-scroll
_initSlider() {
let that = this
this.slider = new BScroll(this.$refs.sliderWrapper, {
scrollX: true,
scrollY: false,
momentum: false,
snap: {
loop: this.loop,
threshold: 0.3,
speed: 400
},
probeType: 2
})
//監聽scroll結束的時候,賦值更新currentPageIndex
this.slider.on('scrollEnd', () => {
clearInterval(that.timer)
that.currentPageIndex = that.slider.getCurrentPage().pageX
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
that._setAutoplay()
})
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
//左滑到最左還想輪播
this.checkScroll(childrenLength,this.$refs.sliderWrapper.offsetWidth)
},
//監聽滑事件
checkScroll(childrenLength,itemWidth) {
let that = this
this.slider.on('scroll', () => {
clearInterval(that.timer)
let leftScroll = parseInt(that.$refs.sliderUl.style['transform'].substring(10, 15))
let left = -1 * itemWidth
let right = left * childrenLength
if (leftScroll >left) {
that.slider.goToPage(childrenLength, 0, 400)
}else if(leftScroll < right) {
that.slider.goToPage(1, 0, 400)
}
})
},
//向左向右
scrollbtnEvent(type) {
clearInterval(this.timer)
let childrenLength = this.loop ? this.children.length - 2 : this.children.length
let goIndex = (type == 'left') ? this.currentPageIndex - 1 : this.currentPageIndex + 1
if (type == 'left') {
if (goIndex < 0) {
goIndex = childrenLength-1
}
} else {
if (goIndex >= childrenLength) {
goIndex = 0
}
}
this.slider.goToPage(goIndex, 0, 400)
},
//按小圓圈
linkToPage(index) {
this.slider.goToPage(index, 0, 400)
}
}
}
</script>
<style>
.slider-wrapper {
position: relative;
width: 100%;
height: 100%;
min-height: 1px;
overflow: hidden;
}
.dots {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0.1rem;
display: flex;
flex-direction: row;
}
.dots span {
cursor: pointer;
display: block;
width: 0.1rem;
height: 0.1rem;
border-radius: 0.05rem;
background: #CCCCCC;
margin-right: 0.05rem;
}
.dot-active {
width: 0.2rem !important;
background: #fff !important;
}
.arrow {
display: flex;
align-items: center;
position: absolute;
top: 0;
cursor: pointer;
color: #333;
opacity: 0.4;
font-size: 0.3rem;
width: 0.7rem;
height: 100%;
}
.arrow:hover {
opacity: 1;
background-image: linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);
color: #fff;
}
.left-arrow {
left: 0;
}
.left-arrow span {
margin-left: 0.2rem;
}
.right-arrow {
justify-content: flex-end;
right: 0;
}
.right-arrow span {
margin-right: 0.2rem;
}
.slider-ul {
position: relative;
white-space: nowrap;
overflow: hidden;
height: 100%;
}
.slider-li {
/* width: 20%; */
height: 100%;
float: left;
box-sizing: border-box;
overflow: hidden;
}
.slider-li a {
overflow: hidden;
width: 100%;
height: 100%;
display: block;
}
.slider-li img {
width: 100%;
height: 100%;
display: block;
}
@media screen and ( max-width : 500px ) {
.arrow{
display: none;
}
}
</style>