马黑黑 发表于 2022-8-23 08:49

用canvas画布做圆环音乐播放器

本帖最后由 马黑黑 于 2022-8-23 10:42 编辑

在画布上画圆,用 arc 方法,它至少需要 5 个参数,下面给出完整参数:

    context.arc(①圆心X坐标, ②圆心Y坐标, ③半径, ④开始角度, ⑤结束角度, ⑥方向);

①②③参数赋值容易理解,不多说;④开始角度默认是 0,位于圆的最右边的坐标处;⑤结束角度,画圆的话是360°,与开始角度(0°)重合;⑥方向取值是 true 或 false,布尔值,用以规定画圆的走向,缺省时是顺时针方向(本例适用缺省设置)。

画圆是做圆环进度的基础,这里再重点说说参数 ④ 开始角度 和 参数 ⑤ 结束角度。圆的角度需要用的圆周率PI,在JS中表达为 Math.PI。比如,我们从 0 开始画圆,参数 ④ 就用 0 表示,它的完整算式是 0 * Math.PI / 180,参数 ⑤ 即结束角度就是360°,算式为2 * Math.PI 。圆环进度条习惯上不从圆的最右边开始,而是从顶部开始的,也就是回退了 90°,所以,圆环进度条的参数 ④ 算式为 -90 * Math.PI / 180,参数 ⑤ 即结束角度将表示当前进度,假设是 angle 度,则它的算式要相应变成 (angle - 90) * Math.PI / 180,以对应已经不是 0° 的开始点。

以上是用画布做圆环进度条的基础。记住:它是针对画布的 arc() 画弧法,角度计算除了 0 以外,必须用 PI 算式而不是直接给出角度值。下面开始编写一个画进度条的函数:

function drawCircle() {
      ctx.clearRect(0, 0, w, h); //每次重新绘制前清空画布
      ctx.beginPath(); //路径开启,用于绘制轨迹圆环
      ctx.strokeStyle = '#eee'; //画布颜色
      ctx.lineWidth = 8; //圆环的厚度
      ctx.arc(w/2, h/2, w/2 - 4, 0, 2 * Math.PI); //绘制轨迹圆环,w、h是画布宽高
      ctx.stroke(); //给上述虚拟圆环着色(用 fill() 方法画的是实现圆)
      ctx.beginPath(); //开始新路径 :用于绘制进度圆环
      ctx.strokeStyle = '#EA0001'; //画布颜色
      ctx.arc(w/2, h/2, w/2 - 4, -90 * Math.PI / 180, (angle - 90) * Math.PI / 180); //画圆环(angle变量实现已声明)
      ctx.stroke(); //上色
      ctx.fillStyle = '#eee'; //改变画笔颜色 :用于绘制文本
      ctx.font = '14px sans-serif'; //字体设置
      ctx.textAlign = 'center'; //文本水平对齐(center 时,以圆心X坐标为基准)
      ctx.textBaseline = 'middle'; //文本垂直对齐(middle 时,以圆心X坐标为基准)
      ctx.fillText(prog, w/2, h/2); //绘制文本,prog 是实现声明的字串变量,文本绘制在圆心处
}


这个函数初始时要运行一次,以便对不自动播放媒体的浏览器友好一些,否则播放器界面出不来。然后,一切交给 audio 的播放情况决定,即,我们在监听 audio 播放器的 timeupdate 事件时改变 angle 和 prog 变量值并调用上述函数以驱使进度条的更新。

为了便于理解,附上《花心》帖子的全部代码:
<style>
#papa { margin: auto; width: 1024px; height: 640px; background: #ccc url('https://638183.freep.cn/638183/t22/51/hx.webp') no-repeat center/cover; box-shadow: 3px 3px 20px #000; position: relative; }
#player { position: absolute; left: 458px; top: 78px; cursor: pointer; }
#hx { position: absolute;left : calc(50% - 180px); top: 10px; }
</style>

<div id="papa">
      <img id="hx" src="https://638183.freep.cn/638183/t22/51/hx.png" alt="" />
      <canvas id="player"></canvas>
</div>

<script>
let ctx = player.getContext('2d'),
      w = h = player.width = player.height = 120,
      prog = '点这播放',
      angle = 0,
      aud = new Audio();

ctx.arc(50,50,40,0, 2*Math.PI);
ctx.stroke();

aud.src = 'https://music.163.com/song/media/outer/url?id=5035947.mp3';
aud.loop = true;
aud.autoplay = true;

drawCircle();

player.onclick = () => aud.paused ? aud.play() : aud.pause();

aud.addEventListener('timeupdate', () => {
      angle = 360 * aud.currentTime / aud.duration;
      prog = toMin(aud.currentTime) + ' | ' + toMin(aud.duration);
      drawCircle();
});

function drawCircle() {
      ctx.clearRect(0, 0, w, h);
      ctx.beginPath();
      ctx.strokeStyle = '#eee';
      ctx.lineWidth = 8;
      ctx.arc(w/2, h/2, w/2 - 4, 0, 2 * Math.PI);
      ctx.stroke();
      ctx.beginPath();
      ctx.strokeStyle = '#EA0001';
      ctx.arc(w/2, h/2, w/2 - 4, -90 * Math.PI / 180, (angle - 90) * Math.PI / 180);
      ctx.stroke();
      ctx.fillStyle = '#eee';
      ctx.font = '14px sans-serif';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(prog, w/2, h/2);
}

function toMin(val) {
      if(!val) return '00:00';
      val = Math.floor(val);
      let min = parseInt(val / 60);
      let sec = parseFloat(val % 60);
      if(min < 10) min = '0' + min;
      if(sec < 10) sec = '0' + sec;
      return min + ':' + sec;
}

</script>

红影 发表于 2022-8-23 09:44

原来不但进度圆环是用画布画出来的,连文本也是呢{:4_187:}

红影 发表于 2022-8-23 09:49

监听 audio 播放器的 timeupdate 事件,就是最后那段代码吧?

马黑黑 发表于 2022-8-23 09:58

红影 发表于 2022-8-23 09:49
监听 audio 播放器的 timeupdate 事件,就是最后那段代码吧?

有点英语基础的话,应该看得出来,这个才是监听 timeupdate 事件:

aud.addEventListener('timeupdate', () => {
      angle = 360 * aud.currentTime / aud.duration;
      prog = toMin(aud.currentTime) + ' | ' + toMin(aud.duration);
      drawCircle();
});

马黑黑 发表于 2022-8-23 10:42

红影 发表于 2022-8-23 09:44
原来不但进度圆环是用画布画出来的,连文本也是呢

文本啰嗦而已,容易的

加林森 发表于 2022-8-23 10:45

来学习。

红影 发表于 2022-8-23 16:44

马黑黑 发表于 2022-8-23 09:58
有点英语基础的话,应该看得出来,这个才是监听 timeupdate 事件:

aud.addEventListener('timeupdate ...

呵呵,我的英语很差的{:4_173:}

红影 发表于 2022-8-23 16:44

马黑黑 发表于 2022-8-23 10:42
文本啰嗦而已,容易的

直接输入多好。

马黑黑 发表于 2022-8-23 17:15

红影 发表于 2022-8-23 16:44
直接输入多好。

那你在自己的美图秀秀里直接输入看看

马黑黑 发表于 2022-8-23 17:15

红影 发表于 2022-8-23 16:44
呵呵,我的英语很差的
这会影响对代码的理解

红影 发表于 2022-8-23 20:54

马黑黑 发表于 2022-8-23 17:15
那你在自己的美图秀秀里直接输入看看

图片上家文字就不能改了,代码的能修改啊。我说的是用CSS直接输入,不用画布的方式。

红影 发表于 2022-8-23 20:55

马黑黑 发表于 2022-8-23 17:15
这会影响对代码的理解

那是,不过用于代码的单词毕竟不多,慢慢也就熟悉了,问题也不大。

马黑黑 发表于 2022-8-23 21:12

红影 发表于 2022-8-23 20:55
那是,不过用于代码的单词毕竟不多,慢慢也就熟悉了,问题也不大。

强记总是可以的,毕竟学过,淡忘了一些而已

马黑黑 发表于 2022-8-23 21:13

红影 发表于 2022-8-23 20:54
图片上家文字就不能改了,代码的能修改啊。我说的是用CSS直接输入,不用画布的方式。

用啥都可以

红影 发表于 2022-8-23 21:36

马黑黑 发表于 2022-8-23 21:12
强记总是可以的,毕竟学过,淡忘了一些而已

常用的总是会知道的,就像一些设备是外文说明书,有些人说难,我就这样说的。

红影 发表于 2022-8-23 21:36

马黑黑 发表于 2022-8-23 21:13
用啥都可以

嗯嗯,知道了。

马黑黑 发表于 2022-8-23 21:50

红影 发表于 2022-8-23 21:36
嗯嗯,知道了。

{:4_180:}

马黑黑 发表于 2022-8-23 21:50

红影 发表于 2022-8-23 21:36
常用的总是会知道的,就像一些设备是外文说明书,有些人说难,我就这样说的。

接触多了就会记住的

红影 发表于 2022-8-24 21:05

马黑黑 发表于 2022-8-23 21:50
接触多了就会记住的

是的,学一种语言难,但只是掌握特定的名称没那么难。

马黑黑 发表于 2022-8-24 22:07

红影 发表于 2022-8-24 21:05
是的,学一种语言难,但只是掌握特定的名称没那么难。

我们一般是这么要求:可以不会说,但有一定的阅读能力
页: [1] 2 3
查看完整版本: 用canvas画布做圆环音乐播放器