Как рисовать вертикальные линии в виде индикатора прогресса трека musi c, используя Canvas в Javascript - PullRequest
1 голос
/ 14 февраля 2020

Я пытаюсь создать собственный аудиоплеер. Я использую HtmlAudioElement для этого. Мне удалось воспроизвести, поставить на паузу, показать длительность и все, но я застрял там, где мне нужно показать индикатор выполнения при воспроизведении трека. У меня есть процентное значение (сколько песен уже сыграно), которое обновляется каждую миллисекунду. Мне было интересно, используя это процентное значение, могу ли я использовать холст и рисовать вертикальные линии при увеличении процента?

enter image description here

Так вот как индикатор выполнения должен менять цвет как процент увеличивается. Я понятия не имею, с чего начать. Я очень плохо знаком с 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();

enter image description here

Так вот как это выглядит прямо сейчас.

Я хочу, чтобы при процентном изменении воспроизведения мне нужно было перехватить это значение где-нибудь в Canvas, чтобы я мог рисовать эти линии.

Заранее спасибо:)

1 Ответ

1 голос
/ 14 февраля 2020

Вы можете прочитать значение (% выполнено) непосредственно из медиа-объекта, который его содержит.

Я не могу тренироваться, с чем у тебя проблемы. Вы упоминаете, что цвет - это простая полоса изменения цвета.

Basi c индикатор выполнения

Некоторые константы для определения индикатора выполнения

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);
}

Основное l oop

  • Основное l oop каждые 60 секунд.

  • Если звук приостановлен, он останавливается.

  • При запуске анимации необходимо соблюдать осторожность l oop Не запускать ее более одного раза

  • Примечание что звук будет остановлен примерно за 1/60 секунды до воспроизведения последнего кадра анимации.

Основная анимация l oop ...

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;
    }
});

Стилизация индикатора выполнения

Следующая функция заменяет строку solid сверху. Он использует область клипа для ограничения ширины, поэтому вам не нужно возиться с дробными полосами.

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
}
...