vue2 視頻時間軸/時間刻度尺組件

20230325_134435_convert_1.gif

借鑒代碼gitee地址午阵,vue3版本,改寫成vue2并修改部分方法

<video-timeline ref="videoTimeLine" @changCurrentTime="changCurrentTime" :videoRecords="videoRecords" />

data() {
    return {
      videoRecords: {}
    };
  },
methods: {
  changCurrentTime(time) {
      console.log(this.$moment(new Date(time * 1000)).format('YYYY-MM-DD hh:mm:ss'))
    }
}

<template>
  <div>
    <div v-if="tipShow" id="tooltip_div">{{ pointTime }}</div>
    <canvas id="is_select_time" :width="width" height="50"></canvas>
    <canvas id="time_line" :width="width" height="50"></canvas>
    <canvas id="time_line_layer" :width="width" height="50"></canvas>
  </div>
</template>

<script>
export default {
  props: {
    width: {
      //時間軸寬度
      default: 1000
    },
    videoRecords: {
      type: Object,
      default: () => {
        return {};
      }
    }
  },
  data() {
    return {
      currentTime: parseInt(new Date().getTime() / 1000),
      mouseSite: 0,
      tipShow: false,
      allowDarw: true
    };
  },
  computed: {
    pointTime() {
      let d = this.getTime(
        this.currentTime +
          this.mouseSite * 2 -
          (this.currentTime % 2) -
          parseInt(this.width)
      );
      return `${d[0]}-${d[1]}-${d[2]} ${d[3]}:${d[4]}:${d[5]}`;
    }
  },
  watch: {
    currentTime(val) {
      if (this.allowDarw) {
        this.timeChange(this.width, val);
      }
    },
    width(val) {
      if (this.allowDarw) {
        this.timeChange(val, this.currentTime);
      }
    },
    videoRecords(val) {
      if (this.allowDarw) {
        const currentTime = (val.startTime + val.endTime) / 2;
        this.currentTime = currentTime;
        this.timeChange(this.width, currentTime);
      }
    }
  },
  mounted() {
    this.timeChange(this.width, this.currentTime);
    this.addanvasEvent();
  },
  methods: {
    drawLine(beginX, beginY, endX, endY, color, width) {
      let canvasId = document.getElementById("time_line");
      let ctx = canvasId.getContext("2d");
      ctx.beginPath();
      ctx.moveTo(beginX, beginY);
      ctx.lineTo(endX, endY);
      ctx.strokeStyle = color;
      ctx.lineWidth = width;
      ctx.stroke();
    },
    pointSite(e) {
      this.mouseSite = e.layerX;
      this.tipShow = true;
      this.$nextTick(() => {
        let ele = document.getElementById("tooltip_div");
        ele.style.left = e.x - 200 + "px";
        ele.style.top = e.y - e.layerY - 132 + "px";
      });
    },
    // canvas 事件
    addanvasEvent() {
      let canvasId = document.getElementById("time_line_layer");
      canvasId.onmouseleave = e => {
        this.tipShow = false;
        canvasId.onmousemove = e => {
          this.pointSite(e);
        };
      };
      // 鼠標按下時的位置轴总;
      let start = 0;
      // 鼠標按下時的currentTime
      let oldTime = 0;
      canvasId.onmousedown = e => {
        // this.allowDarw = false;
        start = e.layerX;
        oldTime = this.currentTime;
        canvasId.onmousemove = e1 => {
          this.tipShow = false;
          let end = e1.layerX;
          let current = (start - end) / 2 + oldTime;

          this.currentTime = current;
          // this.timeChange(this.width, current);
        };
      };
      // 鼠標彈起向外傳出當前時間
      canvasId.onmouseup = e => {
        let end = e.layerX;
        let current = (start - end) / 2 + oldTime;
        this.$emit("changCurrentTime", current);
        this.allowDarw = true;
        canvasId.onmousemove = e1 => {
          this.pointSite(e1);
        };
      };

      canvasId.onmousemove = e => {
        this.pointSite(e);
      };
    },
    // 計算時間偏移并畫線,時間刻度線,半時短線料仗,小時長線,2像素代表1秒鐘
    carveTimeScale(width, currentTime) {
      let canvasId = document.getElementById("time_line");
      let ctx = canvasId.getContext("2d");
      ctx.clearRect(0, 0, width, 50);
      ctx.font = "12px Arial";

      // 將當前時間減去到時間軸中部所需秒,得到時間軸起點秒數(shù)
      let remainder = parseInt(currentTime) - parseInt((width / 2) * 2);
      for (var i = 0; i < width * 2; i++) {
        // 分状婶;
        if ((remainder + i) % 60 == 0) {
          this.drawLine(i / 2, 0, i / 2, 5, "white", 1);
        }
        // 刻意敛;
        if ((remainder + i) % (60 * 15) == 0) {
          this.drawLine(i / 2, 0, i / 2, 10, "white", 1);
          let d = this.getTime(remainder + i);
          ctx.fillStyle = "white";
          ctx.fillText(`${d[3]}:${d[4]}:${d[5]}`, i / 2, 25);
        }

        // 半時;
        if ((remainder + i) % (60 * 30) == 0) {
          this.drawLine(i / 2, 0, i / 2, 15, "white", 1);
          let d = this.getTime(remainder + i);
          ctx.fillStyle = "white";
          ctx.fillText(`${d[3]}:${d[4]}:${d[5]}`, i / 2, 25);
        }

        // 時膛虫;
        if ((remainder + i) % (60 * 60) == 0) {
          this.drawLine(i / 2, 0, i / 2, 20, "white", 1);
          let d = this.getTime(remainder + i);
          ctx.fillStyle = "white";
          ctx.fillText(`${d[3]}:${d[4]}:${d[5]}`, i / 2, 25);
        }
      }
    },
    // 有視頻的區(qū)域渲染顏色
    carveVideoScope(width, currentTime) {
      let canvas = document.getElementById("is_select_time");
      let ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, width, 50);

      if (this.$isEmpty(this.videoRecords)) {
        return;
      }
      let startPoint =
        parseInt(this.videoRecords.startTime) -
        currentTime +
        parseInt(width / 2);
      let endPoint =
        parseInt(this.videoRecords.endTime) - currentTime + parseInt(width / 2);

      // 起點不能為負數(shù)草姻,
      startPoint = startPoint > 0 ? startPoint : 0;
      // 終點不能超出時間尺總長度。
      endPoint = endPoint < width ? endPoint : width;
      let w = endPoint - startPoint;
      ctx.fillStyle = "rgba(230,162,60, 0.7)";
      ctx.fillRect(startPoint, 0, w, 50);
    },
    getTime(timeStamp) {
      let date = new Date(timeStamp * 1000);
      let year = date.getFullYear();
      let month =
        date.getMonth() + 1 < 10
          ? "0" + (date.getMonth() + 1)
          : date.getMonth() + 1;
      let currentDate =
        date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
      let hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
      let minute =
        date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
      let second =
        date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
      return [year, month, currentDate, hour, minute, second];
    },
    // 時間軸中間指示當前時間刻度
    pointCurrent(width, time) {
      let canvasId = document.getElementById("is_select_time");
      let ctx = canvasId.getContext("2d");
      ctx.beginPath();
      ctx.moveTo(parseInt(width / 2), 0);
      ctx.lineTo(parseInt(width / 2), 35);
      ctx.strokeStyle = "blue";
      ctx.lineWidth = 1;
      ctx.stroke();
      ctx.font = "12px Arial";
      ctx.fillStyle = "white";
      let d = this.getTime(time);
      ctx.fillText(
        `${d[0]}-${d[1]}-${d[2]} ${d[3]}:${d[4]}:${d[5]}`,
        parseInt(width / 2) - 50,
        48
      );
    },
    // 當前時間改變稍刀,重繪刻度碴倾,指針,時間
    timeChange(width, time) {
      this.carveVideoScope(width, time);
      this.carveTimeScale(width, time);
      this.pointCurrent(width, time);
    }
  }
};
</script>

<style scoped>
#time_line {
  background-color: rgb(0, 255, 234, 0);
  position: absolute;
}
#is_select_time {
  background-color: gray;
  position: absolute;
}
#time_line_layer {
  background-color: rgb(0, 255, 234, 0);
  position: absolute;
}
#tooltip_div {
  background-color: rgb(50, 121, 115);
  color: #fff;
  position: absolute;
  width: 100px;
  text-align: center;
  padding: 10px;
  z-index: 2;
}
</style>

this.$isEmpty是判斷為空

export function isEmpty(value) {
  switch (typeof value) {
    case 'undefined':
      return true;
    case 'string':
      if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
      break;
    case 'boolean':
      if (!value) return true;
      break;
    case 'number':
      if (0 === value || isNaN(value)) return true;
      break;
    case 'object':
      if (null === value || value.length === 0) return true;
      for (var i in value) {
        return false;
      }
      return true;
  }
  return false;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掉丽,一起剝皮案震驚了整個濱河市跌榔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捶障,老刑警劉巖僧须,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異项炼,居然都是意外死亡担平,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門锭部,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暂论,“玉大人,你說我怎么就攤上這事拌禾∪√ィ” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闻蛀。 經(jīng)常有香客問我匪傍,道長,這世上最難降的妖魔是什么觉痛? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任役衡,我火速辦了婚禮,結(jié)果婚禮上薪棒,老公的妹妹穿的比我還像新娘手蝎。我一直安慰自己,他們只是感情好俐芯,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布柑船。 她就那樣靜靜地躺著,像睡著了一般泼各。 火紅的嫁衣襯著肌膚如雪鞍时。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天扣蜻,我揣著相機與錄音逆巍,去河邊找鬼。 笑死莽使,一個胖子當著我的面吹牛锐极,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芳肌,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼灵再,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了亿笤?” 一聲冷哼從身側(cè)響起翎迁,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎净薛,沒想到半個月后汪榔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡肃拜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年痴腌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燃领。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡士聪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猛蔽,到底是詐尸還是另有隱情剥悟,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站懦胞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凉泄。R本人自食惡果不足惜躏尉,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望后众。 院中可真熱鬧胀糜,春花似錦、人聲如沸蒂誉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽右锨。三九已至括堤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绍移,已是汗流浹背悄窃。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蹂窖,地道東北人轧抗。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像瞬测,于是被迫代替她去往敵國和親横媚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359