vue2 视频时间轴/时间刻度尺组件

2023-03-24  本文已影响0人  时间煮鱼
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";

      // 将当前时间减去到时间轴中部所需秒,得到时间轴起点秒数
      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);
        }
      }
    },
    // 有视频的区域渲染颜色
    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);

      // 起点不能为负数,
      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;
}
上一篇下一篇

猜你喜欢

热点阅读