1. 程式人生 > 程式設計 >Vue.js實現時間軸功能

Vue.js實現時間軸功能

本文例項為大家分享了.實現時間軸功能的具體程式碼,供大家參考,具體內容如下

Vue.js實現時間軸功能

時間軸元件封裝

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,// 定時器
      dateTimeIndexes: [],// 日期列表
      playing: false,// 播放
      activeIndex: 0,// 當前的時間位置
      hoverIndex: 0 // 滑鼠移入的時間位置
    }
  },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: 初始化時間軸
     */
    renderTimeline() {
      // 時間軸的寬度
      const timelineWidth = this.$el.offsetWidth - 40
      // 日期個數
      const dateTimesSize = this.dateTimes.length
      // 如果時間全部顯示,時間軸的理想寬度
      const dateTimesWidth = dateTimesSize * this.interval
      // 如果時間軸的寬度小於理想寬度
      if (timelineWidth >= dateTimesWidth) {
        this.dateTimeIndexes = this.dateTimes.map((dateTime,index) => {
          return index
        })
        return
      }
      // 當前時間軸的寬度最大能容納多少日期刻度
      const maxTicks = Math.floor(timelineWidth / this.interval)
      // 間隔刻度數
      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
      // 最後一項需要特殊處理
      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: 點選刻度
   BCgmTLCqFo
* @param {time} * @param {index} */ tickClick(time,index) { if (this.playing) { return } this.activeIndex = index },/** * @name: 播放和暫停 */ togglePlay() { this.playing = !this.playing },/** * @name: 時間退後一日 */ backward() { if (this.playing) { return } this.activeIndex = this.activeIndex - 1 if (this.activeIndex === -1) { this.activeIndex = this.dateTimes.length - 1 } },/** * @name: 時間前進一日 */ 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="s"> .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.5); } .axis-item { position: relative; display: flex; flex-direction: column; align-items: center; .axis-item-tick { disp
lay: inline-block; width: 4px; height: 20px; background: rgba(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.5); white-space: nowrap; color: #fff; } } } .timeline-control { margin-top: 40px; text-align: center; i { cursor: pointer; display: inline-block; http://www.cppcns.com
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',BCgmTLCqFo       '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>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。