本来是不想画轮子的,接口搜一些文章要么没有自己想要的,要么就是开通VIP才能观看。本着白嫖党永不为奴的原则,只能自己搞了开源给大家提供思路一起进步了!!!

本组件使用vue+canvas构建,开箱即用,模仿海康视频监控中心类似的功能一把手搭建,有大大优化或者改进了更好的版本也请求开源共享哦。

视频监控时间进度条

<template>
    <div>
        <div>
            <button @click="onTime(12, 24)">12小时</button>
            <button @click="onTime(24, 12)">24小时</button>
            <button @click="onTime(48, 6)">30分钟</button>
            <button @click="onTime(144, 2)">10分钟</button>
            <button @click="onTime(288, 1)">5分钟</button>
        </div>
        <canvas
            style="background: #fff"
            id="mymyCanvas"
            :width="width"
            :height="height"
            ref="canvasRef"
        ></canvas>
    </div>
</template>

<script>
export default {
    data() {
        return {
            // 画布实例
            myCanvas: null,
            ctx: null,
            width: 1200,
            height: 50,

            // 偏移量的copy
            curOffset: {
                x: 600,
            },
            // 最终偏移量,默认600(width/2为画布的中心)
            offset: {
                x: 600,
            },
            x: 0,//鼠标按下的e.x值(用于计算最终偏移量)

            timeNum: 12,//时间间隙 12=2小时一个间隔 1px=24s;24=1小时 1=12s;48=30分钟 1=6s;144=10分钟 1=2s;288=5分钟 1=1s
            timeRatio: 24,//时间比值,1px等于多少秒
            ymd: '2022-10-27',//根据选中的日期进行传入
            hms: null,//存中心基准线上的时分秒-转换成秒后根据切换的时间比值来得到px偏移量

        };
    },
    watch: {
        hms(val) {
            // console.log('监听的时分秒===',val,this.offset.x)
        },
        timeNum(val) {
            // console.log('-----timeNum----',val)
        },
        timeRatio(val) {
            // console.log('-----timeRatio----',val)
        },
    },
    mounted() {
        // 画布初始化
        this.canvasInit();
        this.canvasSize();

        // 画布坐标便宜量
        this.ctx.translate(this.offset.x, 0);
        // 基准线
        this.baselineFun(this.offset.x)
        // 水平线
        this.horizontalLine();
        // 刻度线
        this.scaleLine();

        // 模拟播放效果
        // this.playFun()
    },
    methods: {
        // 画布初始化
        canvasInit() {
            this.myCanvas = this.$refs.canvasRef;
            this.ctx = this.myCanvas.getContext("2d");
            console.log("ctx=", this.ctx, "myCanvas=", this.myCanvas);

            if (this.myCanvas) {
                // 鼠标移入滑动移出事件
                this.myCanvas.addEventListener("mouseover", overFun);
                this.myCanvas.addEventListener("mouseleave", leaveFun);
                // 添加按下,滑动,抬起事件
                this.myCanvas.addEventListener("mousedown", downFun);

                const _this = this;
                // 按下
                function downFun(e) {
                    _this.x = e.x;
                    window.addEventListener("mousemove", moveFun);
                    window.addEventListener("mouseup", upFun);
                };
                // 按下滑动
                function moveFun(e) {
                    _this.vueMoveFun(e);
                };
                // 抬起
                function upFun(e) {
                    _this.curOffset.x = _this.offset.x;
                    window.removeEventListener("mousemove", moveFun);
                    window.removeEventListener("mouseup", upFun);
                };

                // 移入
                function overFun(e) {
                    // console.log('移入===',)
                    window.addEventListener("mousemove", slidingFun);
                };
                // 移入滑动
                function slidingFun(e) {
                    // console.log('---移入滑动',e)
                };
                // 移出
                function leaveFun(e) {
                    // console.log('移出===',)
                    window.removeEventListener("mousemove", slidingFun);
                };
            }

        },
        // 重设canvas尺寸会清空地图并重置canvas
        canvasSize() {
            this.myCanvas.width = this.width;
        },
        // 中心基准线
        baselineFun(x) {
            // 绘制一条在固定在中心竖着的基准线,并且带有时间
            this.ctx.beginPath();
            this.ctx.strokeStyle = "#FF0000";
            this.ctx.lineWidth = 1;
            this.ctx.moveTo(600-x, 0);
            this.ctx.lineTo(600-x, 50);
            // 基准线固定时间
            this.ctx.font = "14px SimSun, Songti SC";
            this.ctx.fillText( this.fixedTime(this.offset.x), 600-x-73, 25 );
            this.ctx.stroke();
        },
        // 水平线
        horizontalLine() {
            // 绘制一条直线
            this.ctx.beginPath();
            this.ctx.strokeStyle = "#000";
            this.ctx.lineWidth = 1;
            this.ctx.lineCap = "round";
            this.ctx.moveTo(0, 50);
            this.ctx.lineTo(this.timeNum * 300, 50);
            this.ctx.stroke();
        },
        // 刻度线
        scaleLine() {
            for (var i = 0; i <= this.timeNum; ++i) {
                this.ctx.beginPath(); //新建一条path
                this.ctx.lineWidth = 1;
                this.ctx.moveTo((0 + i) * 300, 50); //把画笔移动到指定的坐标
                this.ctx.lineTo((0 + i) * 300, 40); //绘制一条从当前位置到指定坐标的直线.
                this.ctx.font = "12px SimSun, Songti SC";
                this.ctx.fillText(
                    this.computationTime(i),
                    (0 + i) * 300 - 15,
                    37
                );
                this.ctx.stroke(); //绘制路径。
            }
        },
        // 事件处理
        // 滑动
        vueMoveFun(e) {
            this.canvasSize();
            this.offset.x = this.curOffset.x + e.x - this.x;
            //  默认先让00:00居中,并且控制不能在向右移(600),左移的最大长度为num-2的长度(600),一个间隔为300
            if (this.offset.x > 600) {
                this.offset.x = 600;
            } else if (this.offset.x < -(this.timeNum - 2) * 300) {
                this.offset.x = -(this.timeNum - 2) * 300;
            }
            this.ctx.translate(this.offset.x, 0);
            this.baselineFun(this.offset.x)
            this.horizontalLine();
            this.scaleLine();
            console.log("滑动==", this.offset.x, this.curOffset.x, e.x, this.x);
        },
        // 切换时间间隔
        onTime(num, gap) {
            console.log('timeNum---',num)
            this.timeNum = num;
            // 转换时间计算比值 12=2小时一个间隔 1px=24s;24=1小时 1=12s;48=30分钟 1=6s;144=10分钟 1=2s;288=5分钟 1=1s
            this.timeRatio = gap

            console.log('查看时间',this.hms)
            var date = this.hms.split(':')
            var h = date[0]
            var m = date[1]
            var s = date[2]
            var all = (s-0) + (m*60-0) + (h*3600-0)
            console.log('总共秒=',all,'-=-=-',h*3600,m*60,s,'----this.offset.x=', Math.round(600- all/this.timeRatio) )
            this.offset.x = Math.round(600- all/this.timeRatio)
            this.curOffset.x =  Math.round(600- all/this.timeRatio)
            
            // 刷新画布
            this.canvasSize();
            this.ctx.translate(this.offset.x, 0);
            this.baselineFun(this.offset.x)
            this.horizontalLine();
            this.scaleLine();
        },
        // 计算时间
        computationTime(num) {
            if (this.timeNum === 12) {
                return `${num * 2 < 10 ? "0" + num * 2 : num * 2}:00`;
            } else if (this.timeNum === 24) {
                return `${num < 10 ? "0" + num : num}:00`;
            } else if (this.timeNum === 48) {
                return this.toHourMinute(num * 30);
            } else if (this.timeNum === 144) {
                return this.toHourMinute(num * 10);
            } else if (this.timeNum === 288) {
                return this.toHourMinute(num * 5);
            }
        },
        // 分钟转化 时:分
        toHourMinute(minutes) {
            let h, m;
            h = Math.floor(minutes / 60);
            m = minutes % 60;
            return `${h < 10 ? "0" + h : h}:${m < 10 ? "0" + m : m}`;
        },
        // 水平固定时间
        fixedTime(x) {
            let origin = x - 600;
            if(origin === 0){
                this.hms = '00:00:00'
                return `${this.ymd} 00:00:00`
            }else{
                let h,m,s,time;
                time = Math.abs( origin ) * this.timeRatio
                h = Math.floor( time / 3600 )
                m = Math.floor( time / 60 % 60)
                s = time % 60;
                this.hms = `${h < 10 ? "0" + h : h}:${m < 10 ? "0" + m : m}:${s < 10 ? "0" + s : s}`
                return `${this.ymd} ${h < 10 ? "0" + h : h}:${m < 10 ? "0" + m : m}:${s < 10 ? "0" + s : s}`;
            }
        },

















        // 模拟播放
        playFun() {
            setInterval(() => {
                this.offset.x -= 1;
                this.canvasSize();
                this.ctx.translate(this.offset.x, 0);
                this.horizontalLine();
                this.scaleLine();
            }, 100);
        },
    },
};
</script>

<style lang="scss" scoped>

</style>