Vue.js實(shí)現(xiàn)時(shí)間軸功能
本文實(shí)例為大家分享了Vue.js實(shí)現(xiàn)時(shí)間軸功能的具體代碼,供大家參考,具體內(nèi)容如下

時(shí)間軸組件封裝
Main.js
<template>
<div class="timeline-main">
<div class="timeline-axis">
<div class="axis-item"
v-for="(time, index) in dateTimes"
:key="index">
<div class="axis-item-tick"
:class="{ 'axis-item-tick-active': index === highlightIndex }"
@mouseenter="hoverIndex = index"
@mouseleave="hoverIndex = -1"
@click="tickClick(time, index)">
</div>
<div class="axis-item-label"
v-if="dateTimeIndexes.indexOf(index) >= 0">
{{ time }}</div>
<div class="axis-item-tip"
v-if="index === highlightIndex || index === hoverIndex">
{{ time }}</div>
</div>
</div>
<div class="timeline-control">
<i class="menu-icon icon-left"
:class="{'menu-icon-disabled': playing}"
@click="backward"></i>
<i class="menu-icon"
:class="{'icon-play': !playing, 'icon-pause': playing}"
@click="togglePlay"
@mouseleave="hoverIndex = -1"></i>
<i class="menu-icon icon-right"
:class="{'menu-icon-disabled': playing}"
@click="forward"></i>
<i class="menu-icon icon-up"
:class="{'menu-icon-disabled': playing}"
@click="speedSlow"></i>
<i
class="menu-icon speed">{{ options.speed }}</i>
<i class="menu-icon icon-down"
:class="{'menu-icon-disabled': playing}"
@click="speedQuick"></i>
</div>
</div>
</template>
<script>
import { dateFormat } from '../util/formatdate.js' // 日期格式化
export default {
data() {
return {
intervalTimer: null, // 定時(shí)器
dateTimeIndexes: [], // 日期列表
playing: false, // 播放
activeIndex: 0, // 當(dāng)前的時(shí)間位置
hoverIndex: 0 // 鼠標(biāo)移入的時(shí)間位置
}
},
props: {
options: {
type: Object,
default() {
return {}
}
},
dateTimes: {
type: Array,
default() {
return []
}
},
interval: {
type: Number,
default() {
return 100
}
}
},
computed: {
highlightIndex() {
return (
(this.activeIndex === -1 && this.dateTimes.length - 1) ||
this.activeIndex
)
}
},
watch: {
options: {
handler() {
this.renderTimeline()
},
deep: true
},
playing() {
if (this.playing) {
this.intervalTimer = setInterval(() => {
this.activeIndex = (this.activeIndex + 1) % this.dateTimes.length
}, this.options.speed * 1000)
} else {
if (this.intervalTimer) {
clearInterval(this.intervalTimer)
this.intervalTimer = null
}
}
},
activeIndex() {
const time = this.dateTimes[this.activeIndex].split(' ')[0]
this.$emit('getDateFun', time)
}
},
mounted() {
this.renderTimeline()
let that = this
window.onresize = function () {
that.renderTimeline()
}
},
filters: {
formatDatetime(dateTime) {
dateTime = dateFormat(dateTime, 'MM.dd')
return dateTime
}
},
methods: {
/**
* @name: 初始化時(shí)間軸
*/
renderTimeline() {
// 時(shí)間軸的寬度
const timelineWidth = this.$el.offsetWidth - 40
// 日期個(gè)數(shù)
const dateTimesSize = this.dateTimes.length
// 如果時(shí)間全部顯示,時(shí)間軸的理想寬度
const dateTimesWidth = dateTimesSize * this.interval
// 如果時(shí)間軸的寬度小于理想寬度
if (timelineWidth >= dateTimesWidth) {
this.dateTimeIndexes = this.dateTimes.map((dateTime, index) => {
return index
})
return
}
// 當(dāng)前時(shí)間軸的寬度最大能容納多少日期刻度
const maxTicks = Math.floor(timelineWidth / this.interval)
// 間隔刻度數(shù)
const gapTicks = Math.floor(dateTimesSize / maxTicks)
// 記錄需要顯示的日期索引
this.dateTimeIndexes = []
for (let t = 0; t <= maxTicks; t++) {
this.dateTimeIndexes.push(t * gapTicks)
}
const len = this.dateTimeIndexes.length
// 最后一項(xiàng)需要特殊處理
if (len > 0) {
const lastIndex = this.dateTimeIndexes[len - 1]
if (lastIndex + gapTicks > dateTimesSize - 1) {
this.dateTimeIndexes[len - 1] = dateTimesSize - 1
} else {
this.dateTimeIndexes.push(dateTimesSize - 1)
}
}
},
/**
* @name: 點(diǎn)擊刻度
* @param {time}
* @param {index}
*/
tickClick(time, index) {
if (this.playing) {
return
}
this.activeIndex = index
},
/**
* @name: 播放和暫停
*/
togglePlay() {
this.playing = !this.playing
},
/**
* @name: 時(shí)間退后一日
*/
backward() {
if (this.playing) {
return
}
this.activeIndex = this.activeIndex - 1
if (this.activeIndex === -1) {
this.activeIndex = this.dateTimes.length - 1
}
},
/**
* @name: 時(shí)間前進(jìn)一日
*/
forward() {
if (this.playing) {
return
}
this.activeIndex = (this.activeIndex + 1) % this.dateTimes.length
},
/**
* @name: 減慢速度
*/
speedSlow() {
if (this.playing || this.options.speed >= this.options.speedMax) {
return
}
this.options.speed = this.options.speed + 1
},
/**
* @name: 加快速度
*/
speedQuick() {
if (this.playing || this.options.speed <= 1) {
return
}
this.options.speed = this.options.speed - 1
}
}
}
</script>
<style scoped lang="scss">
.timeline-main {
padding: 10px;
box-sizing: border-box;
.timeline-axis {
position: relative;
display: flex;
justify-content: space-around;
padding: 8px 0;
&::before {
content: '';
width: 100%;
height: 10px;
position: absolute;
left: 0;
bottom: 8px;
display: inline-block;
background: rgba(0, 0, 0, 0.5);
}
.axis-item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
.axis-item-tick {
display: inline-block;
width: 4px;
height: 20px;
background: rgba(0, 0, 0, 0.5);
transition: background 0.3s;
cursor: pointer;
&:hover {
background: #000;
}
}
.axis-item-tick-active {
background: #000;
}
.axis-item-label {
position: absolute;
bottom: -30px;
white-space: nowrap;
}
.axis-item-tip {
position: absolute;
top: -25px;
padding: 2px 6px;
border-radius: 2px;
background: rgba(0, 0, 0, 0.5);
white-space: nowrap;
color: #fff;
}
}
}
.timeline-control {
margin-top: 40px;
text-align: center;
i {
cursor: pointer;
display: inline-block;
font-style: normal;
}
.menu-icon {
font-size: 20px;
width: 20px;
height: 20px;
background-size: cover;
background-repeat: no-repeat;
&.icon-left {
background-image: url('../assets/icon-left.png');
}
&.icon-right {
background-image: url('../assets/icon-right.png');
}
&.icon-play {
background-image: url('../assets/icon-play.png');
}
&.icon-pause {
background-image: url('../assets/icon-pause.png');
}
&.icon-up {
background-image: url('../assets/icon-up.png');
}
&.icon-down {
background-image: url('../assets/icon-down.png');
}
&.menu-icon-disabled {
cursor: no-drop;
opacity: 0.5;
}
}
}
}
</style>
使用組件
App.vue
<template>
<div>
<h2
style="margin:0;text-align:center;">
{{this.date}}
</h2>
<Main :options="options"
:dateTimes="dateTimes"
@getDateFun="getDateFun"
:interval="interval"></Main>
</div>
</template>
<script>
import { dateFormat } from './util/formatdate.js'
import Main from './components/Main'
export default {
name: 'app',
data() {
return {
date: '',
options: {
speed: 1, // 速度
speedMax: 10 // 速度最大值
},
interval: 20, // 日期間的間隔
dateTimes: [
'03-04',
'03-05',
'03-06',
'03-07',
'03-08',
'03-09',
'03-10',
'03-11',
'03-12',
'03-13'
]
}
},
components: {
Main
},
mounted() {
// 獲取最近 10 天的日期
let list = []
for (let i = 0; i < 10; i++) {
list.unshift(
dateFormat(
new Date(
new Date().setDate(new Date().getDate() - i)
).toLocaleDateString(),
'MM-dd'
)
)
}
this.date = list[0]
this.dateTimes = list
},
methods: {
// 接收父組件傳值
getDateFun(time) {
console.log(time)
this.date = time
},
}
}
</script>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
VUE : vue-cli中去掉路由中的井號(hào)#操作
這篇文章主要介紹了VUE : vue-cli中去掉路由中的井號(hào)#操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Vue3?基礎(chǔ)概念與環(huán)境搭建過(guò)程詳解
本文介紹了Vue3的基礎(chǔ)概念,包括響應(yīng)式系統(tǒng)、組合式API和更好的TypeScript支持,同時(shí),文章手把手教你如何搭建Vue3開發(fā)環(huán)境,使用Vite創(chuàng)建項(xiàng)目,并解析了項(xiàng)目的結(jié)構(gòu),通過(guò)這些內(nèi)容,讀者可以快速上手Vue3,并為后續(xù)的學(xué)習(xí)打下堅(jiān)實(shí)的基礎(chǔ),感興趣的朋友一起看看吧2025-02-02
vue通過(guò)style或者class改變樣式的實(shí)例代碼
這篇文章主要介紹了vue通過(guò)style或者class改變樣式的實(shí)例代碼,在文中給大家提到了vue的一些樣式(class/style)綁定,需要的朋友可以參考下2018-10-10
vue elementui el-table 表格里邊展示四分位圖效果(功能實(shí)現(xiàn))
這篇文章主要介紹了vue elementui el-table 表格里邊展示四分位圖效果(功能實(shí)現(xiàn)),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-04-04
vue項(xiàng)目打包發(fā)布到Nginx后無(wú)法訪問(wèn)后端接口的解決辦法
這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目打包發(fā)布到Nginx后無(wú)法訪問(wèn)后端接口的解決辦法,記錄一下項(xiàng)目需要注意的地方,方便以后快速使用,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04
vue3實(shí)現(xiàn)問(wèn)卷調(diào)查的示例代碼
本文主要介紹了vue3實(shí)現(xiàn)問(wèn)卷調(diào)查的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
Vue項(xiàng)目中input框focus時(shí)不調(diào)出鍵盤問(wèn)題的解決
這篇文章主要介紹了Vue項(xiàng)目中input框focus時(shí)不調(diào)出鍵盤問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue.js實(shí)現(xiàn)簡(jiǎn)單動(dòng)態(tài)數(shù)據(jù)處理
本篇文章主要介紹了Vue.js實(shí)現(xiàn)簡(jiǎn)單動(dòng)態(tài)數(shù)據(jù)處理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
vue點(diǎn)擊彈窗自動(dòng)觸發(fā)點(diǎn)擊事件的解決辦法(模擬場(chǎng)景)
本文通過(guò)案例場(chǎng)景給大家介紹vue點(diǎn)擊彈窗自動(dòng)觸發(fā)點(diǎn)擊事件的解決辦法,通過(guò)兩種方法給大家分享vue 自動(dòng)觸發(fā)點(diǎn)擊事件的處理方法,對(duì)vue自動(dòng)觸發(fā)點(diǎn)擊事件相關(guān)知識(shí)感興趣的朋友一起看看吧2021-05-05

