如何在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
}
我正在尝试构建自定义音频播放器。为此,我正在使用 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
}