上一篇只是简单演示了’下一张’的操作和整体的设计思路,这两天把剩余功能补全了,代码经过精简,可封装当成轮播组件使用,详细如下.
代码
<template>
<div class="container">
<button @click="checkNext('last')">上一张</button>
<button @click="checkNext('next')">下一张</button>
<div class="windows" @mousemove="stopPlay" @mouseleave="autoPlay">
<div class="scrollBox">
<div class="scrollItem">
<div class="img">
<el-image :src="initialData.imgUrl"></el-image>
</div>
<div class="messBox">{{ initialData.mess }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
localData: [
{ imgUrl: '', mess: '11111' },
{ imgUrl: '', mess: '2222' },
{ imgUrl: '../assets/dz.png', mess: '3333' },
{ imgUrl: '../assets/logo.png', mess: '44444' },
{ imgUrl: '', mess: '55555' },
{ imgUrl: '', mess: '66666' }
],
initialData: '', // 初始展示数据
nowIndex: 0, // 当前展示数据的索引
progressControler: false, // 控制切换的变量
autoPlayTimer: '', // 自动播放定时器id
nextShowData: { imgUrl: '', mess: '' }// 下一批展示的数据
}
},
mounted () {
this.initData()
},
beforeRouteLeave (to, from, next) {
// 清除定时器
clearInterval(this.autoPlayTimer)
console.log('离开当前页面')
next()
},
methods: {
initData () {
// 初始赋值
this.initialData = this.localData[this.nowIndex]
// 自动播放
this.autoPlay()
},
// 查看上一张/下一张
checkNext (type) {
// 信息展示列表无数据或只有一条数据时,不执行
if (!this.localData || this.localData.length <= 1) return
// 防止猛点
if (this.progressControler) {
console.log('当前操作过快')
return
}
this.progressControler = true // 将当前操作进程锁死,完成后才允许下一次操作
this.readyBox(type)// 准备新的dom元素
let removeDomIndex = ''
let createDomIndex = ''
if (type === 'last') {
console.log('查看上一张')
removeDomIndex = 1
createDomIndex = 0
this.nowIndex--
if (this.nowIndex < 0) { this.nowIndex = this.localData.length - 1 }// 循环播放
}
if (type === 'next') {
console.log('查看下一张')
removeDomIndex = 0
createDomIndex = 1
this.nowIndex++
if (this.localData.length < this.nowIndex + 1) { this.nowIndex = 0 }// 循环播放
}
// 获取dom,准备移动和删除节点
const fatherDom = document.querySelector('.windows')
const moveDistanceX = fatherDom.offsetWidth
const domArr = fatherDom.querySelectorAll('.scrollBox')
// 根据类名判断要移除的子盒子的偏移值
const isRealDom = domArr[removeDomIndex].classList.contains('newScrollBox')
const isRightCreatDom = domArr[removeDomIndex].classList.contains('RightnewScrollBox')
const isLeftCreatDom = domArr[removeDomIndex].classList.contains('LeftnewScrollBox')
// 实现走马灯移动效果
if (!isRealDom) {
domArr[removeDomIndex].style.transform = `translate(${type === 'next' ? -moveDistanceX : moveDistanceX}px,0px)`
}
if ((type === 'next' && isRightCreatDom) || (type === 'last' && isLeftCreatDom)) {
domArr[removeDomIndex].style.transform = `translate(${type === 'next' ? -moveDistanceX * 2 : moveDistanceX * 2}px,0px)`
}
if ((type === 'next' && isLeftCreatDom) || (type === 'last' && isRightCreatDom)) {
domArr[removeDomIndex].style.transform = 'translate(0px,0px)'
}
domArr[createDomIndex].style.transform = `translateX(${type === 'next' ? -moveDistanceX : moveDistanceX}px)`
const timeId1 = setTimeout(() => {
fatherDom.removeChild(domArr[removeDomIndex])
this.progressControler = false // 允许进行下一次操作
clearTimeout(timeId1)
}, 501)
},
// 为下一次移动准备dom元素
readyBox (type) {
let nextShowData = ''// 上一张或下一张要展示的数据
const fatherDom = document.querySelector('.windows')// 获取父元素
const newDom = document.createElement('div')// 创建新元素
// 设置新元素的样式
newDom.className = 'scrollBox'
newDom.classList.add('newScrollBox')
newDom.style.width = '100%'
newDom.style.height = '100%'
newDom.style.position = 'absolute'
newDom.style.transition = 'all 0.5s'
// 上一张
if (type === 'last') {
// 确定下一条播放数据的取值
if (this.nowIndex === 0) {
nextShowData = this.localData[this.localData.length - 1]
} else {
nextShowData = this.localData[this.nowIndex - 1]
}
newDom.style.left = '-100%'
newDom.classList.add('LeftnewScrollBox')
// 插入子元素
newDom.innerHTML = manageHtml(nextShowData)
fatherDom.insertBefore(newDom, fatherDom.firstChild)
}
// 下一张的数据
if (type === 'next') {
// 确定下一条播放数据的取值
if (this.localData.length === this.nowIndex + 1) {
nextShowData = this.localData[0]
} else {
nextShowData = this.localData[this.nowIndex + 1]
}
newDom.style.left = '100%'
newDom.classList.add('RightnewScrollBox')
// 插入子元素
newDom.innerHTML = manageHtml(nextShowData)
fatherDom.appendChild(newDom)
}
// 管理动态页面结构
function manageHtml (nextShowData) {
// 新元素的内部结构
const innerHtml = `
<div class="scrollItem" style=" display: flex; width: 100%; height: 100%; background-color: pink;">
<div class="img" style="width:50%; height:100%" >
<el-image src="${nextShowData.imgUrl}"></el-image>
</div>
<div class="messBox" style=" font-size: 16px; width:50%; height:100%; background-color: skyblue; ">
${nextShowData.mess}
</div>
</div>
`
return innerHtml
}
},
// 自动播放
autoPlay () {
this.autoPlayTimer = setInterval(() => {
this.checkNext('next')
}, 3000)
},
// 暂停播放
stopPlay () {
if (this.progressControler) {
console.log('鼠标移入时进程被打断')
this.progressControler = !this.progressControler
}
clearInterval(this.autoPlayTimer)
}
}
}
</script>
<style lang='scss' scoped>
.container {
width: 100%;
height: 100%;
}
.container .windows {
position: relative;
left: 30%;
top: 30%;
font-size: 0px;
overflow: hidden;
width: 40%;
height: 40%;
}
.scrollBox {
position: absolute;
width: 100%;
height: 100%;
transition: all 0.5s;
}
.windows .scrollItem {
display: flex;
width: 100%;
height: 100%;
background-color: pink;
}
.windows .scrollItem .img {
width: 50%;
height: 100%;
}
.windows .messBox {
font-size: 16px;
width: 50%;
height: 100%;
background-color: skyblue;
}
</style>