如何在Javascript中使用Canvas绘制垂直线作为音乐曲目进度条

How to draw vertical lines as a music track progressbar using Canvas in Javascript

我正在尝试构建自定义音频播放器。为此,我正在使用 HtmlAudioElement。我已经设法播放、暂停、显示持续时间等等,但我在播放曲目时卡在了需要显示进度条的地方。我有每毫秒更新一次的百分比值(已经播放了多少首歌曲)。我想知道使用那个百分比值我可以使用 canvas 并随着百分比增加绘制垂直线吗?

这就是进度条应该如何随着百分比的增加而改变颜色。我不知道从哪里开始。我对 Canvas 很陌生。任何帮助?

到目前为止我已经试过了。 (这不是我想要的)。

const canvas = document.getElementById('progress');
canvas.width = 1920;
canvas.height = 100;
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'grey';

for(let i = 0; i < 1000; i+=10){
    console.log(i);
    ctx.fillRect(i,0,5,100);
}

let count = 0;
let percent = 0;
ctx.fillStyle = 'orange';

function draw(){
    console.log('Hello')
    ctx.fillRect(count,0,5,100);
    count+=10;
    if(count > 100/1){
        return;
    }
    window.requestAnimationFrame(draw);
}

draw();

这就是现在的样子。

我想随着播放百分比的变化,我需要将该值挂接到 Canvas 中的某处,以便我可以画出这些线。

提前致谢:)

您可以直接从保存它的媒体对象中读取值(完成百分比)。

我无法解决您遇到的问题。你提到颜色下面是一个简单的变色条。

基本进度条

定义进度条的一些常量

const width = 500;
const height = 20;
const startColor = {r: 255, g: 128, b: 0}; // unsigned byte values 0 - 255
const endColor = {r: 255, g: 128, b: 0};

插值颜色

function progressColor(start, end, progress) {
    const r = (end.r - start.r) * progress + start.r;
    const g = (end.g - start.g) * progress + start.g;
    const b = (end.b - start.b) * progress + start.b;
    return `rgb(${r | 0},${g |0 }, ${b | 0})`;
}

绘制条形图

function progressBar(progress) {
    ctx.fillStyle =  progressColor(startColor, endColor, progress);
    // whatever design you want the example is just a simple bar

    ctx.fillRect(0,0, width * progress, height);
}

主循环

  • 每60秒主循环一次。

  • 如果音频暂停,它就会停止。

  • 启动动画循环时必须注意不要多次启动它

  • 注意在渲染最后一个动画帧之前,音频会停止大约 1/60 秒。

主动画循环...

var progressAnimating = false;  // this is to avoid more that one mainLoop playing
function mainLoop() {
    ctx.clearRect(0,0,width,height);

    // draw backing bar here

    const fractionDone = audio.time / audio.duration;
    progressBar(fractionDone);

    // only while not paused
    if (!audio.paused) {
        requestAnimationFrame(mainLoop);
    } else {
        progressAnimating = false;  // flag that the animation has stopped
    }
}

使用音频事件启动动画

  • 使用音频播放事件启动动画。

  • 检查以确保在请求第一帧之前动画没有播放。

  • 如果动画仍处于活动状态,则它将自行继续

.

audio.addEventListener("play",() => {
    if (!progressAnimating) {
        requestAnimationFrame(mainLoop);
        progressAnimating = true;
    }
});

设置进度条的样式

下一个函数替换上面的实心条。 它使用剪辑区域来限制宽度,因此您不需要 fiddle 小数条。

const barWidth = 4; // in px
const barSpacing = 8; // distance from left edge to next left edge in px

function progressBar(progress) {
    ctx.save(); // save the unclipped state

    ctx.beginPath(); // create the clip path
    ctx.rect(0,0, width * progress, height);
    ctx.clip();

    ctx.fillStyle =  progressColor(startColor, endColor, progress);

    ctx.beginPath(); // draw all bars as one
    var x = 0;
    while (x < width * progress) {
        ctx.rect(x, 0, barWidth, height);
        x += barSpacing;
    }
    ctx.fill(); // draw that bars

    ctx.restore(); // restore unclipped state
}