SOURCE

console 命令行工具 X clear

                    
>
console
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

const wStart = 30;
const wEnd = 670;
canvas.width = 700;
canvas.height = 80;

const timeSelectWidth = wEnd - wStart;
const totalSeconds = 86400;


let animateId;
let mouseDown = false;
let beforeSelectTime;
let beforeCurrentTime;
let currentTime;
let speed = 10;

let hPosition = 0;
let cPosition = 0;
let hTime = "";
let cTime = "";

const drawBg = () => {
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(wStart, 16);
    ctx.lineTo(wEnd, 16)
    ctx.strokeStyle = "#6bddc4";
    ctx.lineWidth = 18;
    ctx.lineCap = "round";
    ctx.stroke();
    ctx.restore();
}

const drawCurrentTime = () => {
    currentTime = moment();
    cTime = currentTime.format("HH:mm:ss");
    const startDay = moment().startOf("day").valueOf();
    const diff = Math.floor((currentTime.valueOf() - startDay) / 1000)
    cPosition = timeSelectWidth * diff / totalSeconds + wStart;
}

const drawBeforeTime = () => {
    if (!beforeCurrentTime) beforeCurrentTime = moment().valueOf();
    if (!beforeSelectTime) beforeSelectTime = moment().valueOf();
    const currentTime = moment().valueOf();
    const timeDiff = (moment().valueOf() - beforeCurrentTime) * speed;
    const startDay = moment().startOf("day").valueOf();
    if ((currentTime - beforeSelectTime) < 5000) {
        beforeSelectTime = currentTime;
        beforeCurrentTime = moment().valueOf();
        const diff = Math.floor((currentTime.valueOf() - startDay) / 1000)
        hPosition = timeSelectWidth * diff / totalSeconds + wStart;
        hTime = "";
    } else {
        beforeSelectTime = beforeSelectTime + timeDiff;
        beforeCurrentTime = moment().valueOf();
        const diff = Math.floor((beforeSelectTime - startDay) / 1000)
        hPosition = timeSelectWidth * diff / totalSeconds + wStart;
        hTime = moment(beforeSelectTime).format("HH:mm:ss");
    }
};

const drawTime = () => {
    // 绘制当前时间
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(cPosition, 6);
    ctx.lineTo(cPosition, 26);
    ctx.strokeStyle = "blue";
    ctx.stroke();
    ctx.textAlign = "center";
    ctx.fillText(cTime, cPosition, 56)
    ctx.restore();

    // 绘制历史时间
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(wStart, 16);
    ctx.lineTo(hPosition, 16);
    ctx.lineWidth = 12;
    ctx.strokeStyle = 'blue';
    ctx.lineCap = "round";
    ctx.stroke();
    ctx.beginPath();
    ctx.restore();
    ctx.save();
    ctx.arc(hPosition, 16, 10, 0, 2 * Math.PI);
    ctx.strokeStyle = "red";
    ctx.stroke();
    ctx.textAlign = "center";
    ctx.fillText(hTime, hPosition, 46)
    ctx.restore();
}

const draw = () => {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    drawBg();
    drawCurrentTime();
    drawBeforeTime();
    drawTime();
    window.cancelAnimationFrame(animateId);
    animateId = window.requestAnimationFrame(draw);
};

const update = () => {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    drawBg();
    drawCurrentTime();
    drawBeforeTime();
    drawTime();
}

canvas.onmousedown = (e) => {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left * (canvas.width / rect.width);
    const y = e.clientY - rect.top * (canvas.height / rect.height);
    if (Math.abs(x - hPosition) < 10 && Math.abs(y - 16) < 10) {
        mouseDown = true;
        window.cancelAnimationFrame(animateId);
        animateId = null;
    }
}

canvas.onmousemove = (e) => {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left * (canvas.width / rect.width);
    const y = e.clientY - rect.top * (canvas.height / rect.height);
    if (mouseDown) {
        if (x >= wStart && x <= wEnd) {
            hPosition = x;
        } else if (x < wStart) {
            hPosition = wStart;
        } else {
            hPosition = wEnd;
        }
        beforeSelectTime = totalSeconds * (hPosition - wStart) / (wEnd - wStart) * 1000 + moment().startOf("day");
        update();
    }
}

canvas.onmouseup = (e) => {
    if (mouseDown) {
        mouseDown = false;
        draw();
    }
}

canvas.onmouseleave = (e) => {
    if (mouseDown) {
        mouseDown = false;
        draw();
    }
}

draw();
<div class="container">
        <div class="placeholder"></div>
    <canvas class="canvas" id="canvas"></canvas>
    <div class="select"></div>
</div>
.container{
    width: 700px;
    height: 110px;
    display: flex;
    flex-direction: column;
}


.placeholder{
    height: 30px;
}
.canvas{
    height: 80px;
    flex: 1;
    background: #e3e3e3;
}

本项目引用的自定义外部资源