1. Swiper.vue
<template>
<div class="swiper">
<!-- 显示轮播图片区域 -->
<div class="slide" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove">
<slot></slot>
</div>
<!-- 小圆点显示区 -->
<div>
<ul class="indicator" v-show="showIndicator && slideNum > 1">
<li v-for="(item,i) in slideNum" :key="i" :class="{active:i === currentIndex-1}" class="indi-item"></li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: "Swiper",
props:{
interval: {
type: Number,
default: 3000
},
moveRatio: {
type: Number,
default: 0.25
},
animDuration: {
type: Number,
default: 300
},
showIndicator: {
type: Boolean,
default: true
}
},
data(){
return{
slideNum: 0,
currentIndex: 1,
totalWidth: 0,
timer: null,
slideStyle:{},
scrolling: false
}
},
mounted(){
this.handleDom();
this.startTimer();
},
methods:{
startTimer:function(){
this.timer = window.setInterval(()=>{
this.currentIndex++;
this.scrollContent(-this.currentIndex * this.totalWidth);
},this.interval)
},
stopTimer:function(){
window.clearInterval(this.timer);
},
handleDom:function(){
let swiperEl = document.querySelector('.slide');
let swiperitems = swiperEl.getElementsByClassName('swiperitem');
this.slideNum = swiperitems.length;
if (this.slideNum > 1) {
let firstClone = swiperitems[0].cloneNode(true);
let lastClone = swiperitems[this.slideNum-1].cloneNode(true);
swiperEl.insertBefore(lastClone, swiperitems[0]);
swiperEl.appendChild(firstClone);
this.totalWidth = swiperEl.offsetWidth;
this.slideStyle = swiperEl.style;
}
this.animate(-this.totalWidth);
var firstTimer = null;
window.onresize = ()=>{
if (firstTimer) {
clearTimeout(firstTimer);
}
firstTimer = setTimeout(()=>{
this.totalWidth = swiperEl.offsetWidth;
this.animate(-this.totalWidth);
this.currentIndex = 1;
},100)
}
},
animate:function(target){
this.slideStyle.transform = `translate3d(${target}px, 0, 0)`;
this.slideStyle['-webkit-transform'] = `translate3d(${target}px), 0, 0`;
this.slideStyle['-ms-transform'] = `translate3d(${target}px), 0, 0`;
},
checkPosition:function(){
window.setTimeout(()=>{
this.slideStyle.transition = '0ms';
if(this.currentIndex >= this.slideNum + 1){
this.currentIndex = 1;
this.animate(-this.currentIndex * this.totalWidth);
}else if(this.currentIndex <= 0){
this.currentIndex = this.slideNum;
this.animate(-this.currentIndex * this.totalWidth);
}
}, this.animDuration)
},
scrollContent: function(position){
this.scrolling = true;
this.slideStyle.transition ='transform '+ this.animDuration + 'ms';
this.animate(position);
this.checkPosition();
this.scrolling = false;
},
touchstart:function(e){
if(this.scrolling) return
this.stopTimer();
this.startX = e.touches[0].pageX;
},
touchmove:function(e){
this.currentX = e.touches[0].pageX;
this.distance = this.currentX - this.startX;
let currentPosition = -this.currentIndex * this.totalWidth;
let moveDistance = this.distance + currentPosition;
this.animate(moveDistance);
this.scrolling = true;
},
touchend:function(){
if(this.scrolling){
let currentMove = Math.abs(this.distance);
if (this.distance === 0) {
return
}else if (this.distance > 0 && currentMove > this.totalWidth * this.moveRatio) {
this.currentIndex--;
} else if(this.distance < 0 && currentMove > this.totalWidth * this.moveRatio){
this.currentIndex++;
}
}
this.scrollContent(-this.currentIndex * this.totalWidth);
this.startTimer();
}
}
}
</script>
<style scoped>
.swiper{
overflow: hidden;
position: relative;
}
.slide{
display: flex;
}
.indicator {
display: flex;
justify-content: center;
position: absolute;
width: 100%;
bottom: 8px;
}
.indi-item {
box-sizing: border-box;
width: 8px;
height: 8px;
border-radius: 4px;
background-color: #fff;
line-height: 8px;
text-align: center;
font-size: 12px;
margin: 0 5px;
}
.indi-item.active {
background-color: rgba(212,62,46,1.0);
}
</style>
2. SwiperItem.vue
<template>
<div class="swiperitem">
<slot></slot>
</div>
</template>
<script>
export default {
name: "SwiperItem",
}
</script>
<style>
.swiperitem{
width: 100%;
flex-shrink: 0;
}
.swiperitem img{
width: 100%;
}
</style>
3. index.js
index.js
:导出Swiper.vue
和SwiperItem.vue
import Swiper from './Swiper'
import SwiperItem from './SwiperItem'
export {
Swiper, SwiperItem
}
4. HomeSwiper.vue
<template>
<div class="homeswiper">
<swiper>
<swiper-item v-for="(item,i) in imgMessage" :key="i">
<a :href="item.url">
<img :src="item.path" alt="">
</a>
</swiper-item>
</swiper>
</div>
</template>
<script>
import {Swiper, SwiperItem} from "../../components/swiper"
export default {
name: "HomeSwiper",
components:{
Swiper, SwiperItem
},
props:{},
data(){
return{
imgMessage:[
{path: require("@/assets/img/slide_1.jpg"), url: "javascript:;" },
{path: require("@/assets/img/slide_2.jpg"), url: "javascript:;" },
{path: require("@/assets/img/slide_3.jpg"), url: "javascript:;" },
{path: require("@/assets/img/slide_4.jpg"), url: "javascript:;" }
],
}
}
}
</script>
<style scoped>
a{
display: block;
height: 100%;
}
</style>