概述
<template>
<div class="chart-out-wrapper">
<div class="chart-wrapper"
ref="swiper"
@mouseover="mouseHover"
@mouseout="mouseOut"
>
<barChart v-for="(item, index) in categoryDataList"
:key="index"
class="chart-size"
:chartData="item"
:chartLeft="20"
:color="linearColor[index]"
ref="barchart"
>
</barChart>
<barChart class="chart-size"
:chartData="categoryDataList[0]"
:chartLeft="20"
:color="linearColor[0]"
ref="barchart"
>
</barChart>
</div>
</div>
</template>
<script>
import barChart from './barChart'
export default {
name: 'chart',
components: {
barChart
},
props: {
categoryDataList: {
type: Array,
default: function () {
return []
}
}
},
data() {
const self = this
return {
activeChartIndex: 0,
linearColor: [
new this.$echarts.graphic.LinearGradient(0, 0, 1, 1, [{
offset: 0,
color: '#394FFD' // 0% 处的颜色
}, {
offset: 1,
color: '#0AFFC5' // 100% 处的颜色
}], false),
new this.$echarts.graphic.LinearGradient(0, 0, 1, 1, [{
offset: 0,
color: '#FFCB14'
}, {
offset: 1,
color: '#0DE4C2'
}], false),
new this.$echarts.graphic.LinearGradient(0, 0, 1, 1, [{
offset: 0,
color: '#B62A2B'
}, {
offset: 1,
color: '#EBBC15'
}], false)
],
carouselTimer: null,
animating: false,
transitionTimer: null
}
},
watch: {
categoryDataList(curVal) {
}
},
mounted() {
this.handleCarousel()
},
methods: {
/**
* @description 自动轮播
*/
handleCarousel() {
this.$nextTick(() => {
this.carouselTimer = setInterval(() => {
this.move()
}, 2000)
})
},
move() {
let swiper = this.$refs.swiper
this.activeChartIndex++
swiper.style.transform = `translate3d(-${this.activeChartIndex * 100}%, 0, 0)`
swiper.style.transition = 'transform 1s'
if (this.activeChartIndex === this.categoryDataList.length) {
this.activeChartIndex = 0
this.animating = true
clearTimeout(this.transitionTimer)
this.transitionTimer = setTimeout(() => {
swiper.style.transform = 'translate3d(0%, 0, 0)'
swiper.style.transition = ''
this.animating = false
}, 1000)
}
},
// 鼠标移上去停止滚动
mouseHover() {
clearInterval(this.carouselTimer)
this.carouselTimer = null;
},
// 鼠标移出后继续滚动
mouseOut() {
this.carouselTimer = setInterval(() => {
this.move()
}, 2000)
},
// 当点击切换的时候的操作
changeActiveIndex(index) {
let swiper = this.$refs.swiper
let interval = 0
if (this.animating) {
clearTimeout(this.transitionTimer)
this.transitionTimer = null
swiper.style.transform = 'translate3d(-300%, 0, 0)'
swiper.style.transition = ''
setTimeout(() => {
swiper.style.transform = 'translate3d(0%, 0, 0)'
swiper.style.transition = ''
}, 0)
this.animating = false
interval = 50
}
setTimeout(() => {
clearInterval(this.carouselTimer)
this.carouselTimer = null;
this.activeChartIndex = index
swiper.style.transform = `translate3d(-${this.activeChartIndex * 100}%, 0, 0)`
swiper.style.transition = 'transform 0.5s'
this.carouselTimer = setInterval(() => {
this.move()
}, 2000)
}, interval)
}
}
}
</script>
<style scoped lang="less">
.chart-out-wrapper {
width: 100%;
height: 100%;
overflow: hidden;
.chart-wrapper {
display: -webkit-box;
width: 100%;
height: 100%;
.chart-size {
width: 100%;
height: 100%;
}
}
}
</style>
都知道,实现无缝轮播,一般都会将第一个节点及其子节点使用cloneNode(true)克隆一份拼接到末尾,但是这样子会有一个问题,它只克隆节点所有属性以及它们的值,但不包括事件,而且也不会随着数据更新而更新(个人认为:可以通过在无缝过渡的时候强制去更新节点的数据,可参考:https://www.jianshu.com/p/fc8df1229b52 虽然我没有实现这个,但是别人贴出来了说明一般情况下是可以的,我是在init部分报错,而且时间较紧,耐心也用完,笔者没办法做下去了==||)。因此,通过显示的克隆节点(也就是直接将数据拼接到后面啦!!),这样就可以解决数据不变的问题
实现无缝轮播的方式有很多,笔者用的是tansition+transform的方式,参考了另一个博客,他的写法会更简单
参考的链接:
https://zhuanlan.zhihu.com/p/32822928
笔者实现如下:
handleCarousel() {
this.$nextTick(() => {
this.carouselTimer = setInterval(() => {
this.move()
}, 2000)
})
},
move() {
let swiper = this.$refs.swiper
this.activeChartIndex++
swiper.style.transform = `translate3d(-${this.activeChartIndex * 100}%, 0, 0)`
swiper.style.transition = 'transform 1s'
if (this.activeChartIndex === this.categoryDataList.length) {
this.activeChartIndex = 0
this.animating = true
clearTimeout(this.transitionTimer) // 当处于过渡时,清除定时器,这个是点击切换页面的点时触发的定时器
this.transitionTimer = setTimeout(() => { // 当过渡完成后就将第一个tab移至可视区域,看到博客有人建议使用transitionend时间来监听过渡完成的时间,则不用使用setTimout来计算时间
swiper.style.transform = 'translate3d(0%, 0, 0)'
swiper.style.transition = ''
this.animating = false
}, 1000)
}
}
当页面包含有分页器的时候,会产生一个问题:“在transition结束后Timeout切换有个bug,从最后一张(算上过渡区是倒数第二张),以少于transition-duration的时间间隔连点两次,它会切回去。”
笔者的解决方式是使用先触发立即移至最后一页(也就是克隆的那一页),延时将第一页移至可视区域,最后再加延时过渡到点击的那一页,实现如下:
changeActiveIndex(index) {
let swiper = this.$refs.swiper
let interval = 0
if (this.animating) {
clearTimeout(this.transitionTimer)
this.transitionTimer = null
swiper.style.transform = 'translate3d(-300%, 0, 0)'
swiper.style.transition = ''
setTimeout(() => {
swiper.style.transform = 'translate3d(0%, 0, 0)'
swiper.style.transition = ''
}, 0)
this.animating = false
interval = 50
}
setTimeout(() => {
clearInterval(this.carouselTimer)
this.carouselTimer = null;
this.activeChartIndex = index
swiper.style.transform = `translate3d(-${this.activeChartIndex * 100}%, 0, 0)`
swiper.style.transition = 'transform 0.5s'
this.carouselTimer = setInterval(() => {
this.move()
}, 2000)
}, interval)
}
文章可能有不正确的地方,希望能够指正,或者提出更好的实现方式,多多交流。
最后
以上就是勤恳衬衫为你收集整理的vue项目中实现无缝轮播并动态更新数据的全部内容,希望文章能够帮你解决vue项目中实现无缝轮播并动态更新数据所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复