基于VUE的可以滚动的横向时间轴
这个时间轴可以播放,翻篇,进行一些配置,
HTML:
<div class="timeline-container"> <div class="item"> <div class="list" v-for="(item, index) in dataChart" :key="item.id" @click="go(index, '')" :style="{ width: option.itemWidth ? `${option.itemWidth}px` : `100px`, height:option.itemHeight ? `${option.itemHeight}px` : `auto`, transform: `translateX(${translateNum}px)`, }" > <!-- 内容部分 --> <div :class="`text ${index === currentIndex?'active':''}`" :style="itemStyle(index)" :title="item.text" > {{ item.text }} </div> </div> </div> <!-- 播放/暂停,showPlayBtn:是否显示播放按钮 --> <div class="btn-play" @click="play" :style="btnStyle" v-if="option.showPlayBtn" > {{option.btnPlayName||'播放/暂停'}} </div> </div>
scss:
.timeline {
width: 100%;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
.line {
width: 100%;
height: 1px;
background: #ccc;
}
.timeline-container {
width: 100%;
position: relative;
height: 100%;
display: flex;
align-items: center;
.item {
width: 100%;
display: -webkit-box;
align-items: center;
overflow: hidden;
margin-right: 10px;
.list {
text-align: center;
cursor: pointer;
transition: 0.5s all linear;
display: flex;
justify-content: center;
.text {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
position: relative;
}
.active {
transition: 0.5s all linear;
}
}
.item-prev,
.item-next {
width: 45px;
height: 45px;
border-radius: 50%;
color: #909090;
background-color: #e9e9e9;
cursor: pointer;
margin: -24px auto 0;
display: flex;
align-items: center;
justify-content: center;
border: none;
outline: none;
&:hover {
color: #fff;
background-color: red;
}
&.item-disabled {
background: #666;
cursor: no-drop;
}
}
}
.btn-play{
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
}
}
JS:
<script> //dataChart:数据源 export default { name: 'timeline', data() { return { currentIndex: 0, timer: null, onIsActive: true, translateNum: 0, }; }, watch: { autoPlay(val) { if (val) { this.setGo() } else { clearInterval(this.timer); } } }, computed: { prevIndex() { if (!this.loop) { if (this.currentIndex == 0) { return 0; } else { return this.currentIndex - 1; } } else { if (this.currentIndex == 0) { return this.dataChart.length - 1; } else { return this.currentIndex - 1; } } }, nextIndex() { if (!this.loop) { if (this.currentIndex == this.dataChart.length - 1) { return this.dataChart.length - 1; } else { return this.currentIndex + 1; } } else { if (this.currentIndex == this.dataChart.length - 1) { return 0; } else { return this.currentIndex + 1; } } }, /** * 自动播放 */ autoPlay: { get() { return this.option.autoPlay || false }, set(val) { this.option.autoPlay = val; } }, /** * 循环 */ loop() { return this.option.loop || false }, /** * 一次显示几个列表项 */ timelineNum() { return this.option.timelineNum || 6 }, /** * 一次滚动的宽度 */ timelineWidth() { return ((this.option.itemWidth||0)/this.timelineNum).toFixed(0)*(this.option.timelineNum||0) || 1 }, /** * 按钮样式 */ btnStyle() { let obj = { fontSize: this.option.btnFontSize ? `${this.option.btnFontSize}px` : '16px', color: this.option.btnColor || '#fff', width: this.option.btnWidth ? `${this.option.btnWidth}px` : 'auto', height: this.option.btnHeight ? `${this.option.btnHeight}px` : 'auto', } if (this.option.useBtnBgImg) { if (this.autoPlay) { obj.background = `url(${this.option.btnActiveBg}) no-repeat center/100% 100%` } else { obj.background = `url(${this.option.btnBg}) no-repeat center/100% 100%` } } else { if (this.autoPlay) { obj.backgroundColor = `${this.option.btnActiveBg || '#00FB69'}` } else { obj.backgroundColor = `${this.option.btnBg || '#22E47F'}` } } return obj; } }, methods: { /** * 当前节点的发送事件 */ go(index, str) { if(this.currentIndex>index){ str="prev" }else{ str="next" } this.currentIndex = index; this.onIsActive = true; if (this.autoPlay) { this.setGo(); } this.calcTranslateNum(str); const data = { type: 'timeLine', itemData: this.dataChart[index] }; }, /** * 自动切换方法 * goSpeed:切换速度 */ setGo() { clearInterval(this.timer); this.timer = setInterval(() => { this.go(this.nextIndex); // this.calcTranslateNum("next"); }, this.option.goSpeed || 2000); }, /** * 滚动计算法 */ calcTranslateNum(str) { if (str === "next") { // timelineNum的倍数的时候就翻一次 if (this.currentIndex % this.timelineNum == 0) { this.translateNum += this.timelineNum * -this.timelineWidth; return; } if (this.currentIndex === 0) { this.translateNum = 0; return; } } else if (str === "prev") { if (this.currentIndex <= this.timelineNum) { this.translateNum = 0; return; } if (this.currentIndex % this.timelineNum == 0) { this.translateNum -=this.timelineNum * -this.timelineWidth; return; } } }, /** * 列表项样式 */ itemStyle(index) { let obj = { width: '100%', fontSize: this.option.fontSize ? `${this.option.fontSize}px` : '16px', color: this.option.color || '#fff', marginRight: `${this.option.marginRight || 0}px`, padding: `${this.option.paddingTop || 0}px ${this.option.paddingRight || 0}px ${this.option.paddingDown || 0}px ${this.option.paddingLeft || 0}px`, boxSizing: "border-box" } if (this.option.useBgImg) { obj.background = `url(${index === this.currentIndex ? this.option.bgActive : this.option.bg}) no-repeat center/100% 100%` } else { obj.backgroundColor = `${index === this.currentIndex ? this.option.bgActive || '#00B7FB' : this.option.bg || '#00FB69'}` } return obj; }, /** * 播放/暂停 */ play() { this.autoPlay = !this.autoPlay; }, }, mounted() { if (this.autoPlay) { this.setGo(); } }, beforeDestroy() { clearInterval(this.timer); }, } </script>
调用:
<timeline :autoPlay="false" :option="option" :data="apiData"></timeline>
new Vue({ el: '#app', data() { return { option: { itemWidth: 30, itemHeight: 30, useBgImg:true, bgActive:'red', bg:'yellow', useBtnBgImg:true, btnActiveBg:'red', btnBg:'yellow', fontSize:10, color:'#00F1FB', timelineWidth:20, autoPlay:false, loop:true, goSpeed:1000, txtLength:2, btnWidth:85, btnHeight:30, showPlayBtn:false, }, apiData:[ { id: 1, text: "2020-09-28", }, { id: 2, text: "2020-09-30 12:00:002020-09-28 12:00:00", }, { id: 3, text: "2020-10-2 ", }, { id: 4, text: "2020-10-3", }, { id: 5, text: "2020-10-4", }, { id: 6, text: "2020-10-5", }, { id: 7, text: "2020-10-6", }, { id: 8, text: "2020-10-7", }, { id: 9, text: "2020-10-8", }, { id: 10, text: "2020-10-9", }, ] } } })
效果:
积累小的知识,才能成就大的智慧,希望网上少一些复制多一些原创有用的答案