马黑黑 发表于 2024-3-31 12:47

canvas画布圆形进度条播放器

本帖最后由 马黑黑 于 2024-3-31 13:44 编辑 <br /><br /><style>
#canv { display: block; margin: 20px auto; transform: scale(0.8); }
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>
<p>效果:</p>
<canvas id="canv" width="200" height="200" style=""></canvas>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=2040200174" autoplay loop></audio>
<p>代码:</p>
<div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">style</span>&gt;</cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; #canv { <span class="tBlue">display:</span> block; <span class="tBlue">margin:</span> 20px auto; <span class="tBlue">transform:</span> scale(0.75); }</cl-cd>
<cl-cd data-idx="3">&lt;<span class="tDarkRed">/style</span>&gt;</cl-cd>
<cl-cd data-idx="4">&nbsp;</cl-cd>
<cl-cd data-idx="5">&lt;<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"canv"</span> width=<span class="tMagenta">"200"</span> height=<span class="tMagenta">"200"</span> style=<span class="tMagenta">""</span>&gt;&lt;<span class="tDarkRed">/canvas</span>&gt;</cl-cd>
<cl-cd data-idx="6">&lt;<span class="tDarkRed">audio</span> <span class="tRed">id</span>=<span class="tMagenta">"aud"</span> src=<span class="tMagenta">"https://music.163.com/song/media/outer/url?<span class="tRed">id</span>=2040200174"</span> autoplay loop&gt;&lt;<span class="tDarkRed">/audio</span>&gt;</cl-cd>
<cl-cd data-idx="7">&nbsp;</cl-cd>
<cl-cd data-idx="8">&lt;<span class="tDarkRed">script</span>&gt;</cl-cd>
<cl-cd data-idx="9">(<span class="tBlue">function</span>() {</cl-cd>
<cl-cd data-idx="10">&nbsp; &nbsp; <span class="tBlue">let</span> rotDeg = 0, prgDeg = 0, raf;</cl-cd>
<cl-cd data-idx="11">&nbsp; &nbsp; <span class="tBlue">let</span> ctx = canv.getContext(<span class="tMagenta">'2d'</span>);</cl-cd>
<cl-cd data-idx="12">&nbsp; &nbsp; ctx.lineWidth = 10;</cl-cd>
<cl-cd data-idx="13">&nbsp; &nbsp; ctx.lineCap = <span class="tMagenta">'round'</span>;</cl-cd>
<cl-cd data-idx="14">&nbsp;</cl-cd>
<cl-cd data-idx="15">&nbsp; &nbsp; <span class="tBlue">let</span> gradient = ctx.createLinearGradient(0, 0, 200, 200);</cl-cd>
<cl-cd data-idx="16">&nbsp; &nbsp; gradient.addColorStop(0, <span class="tMagenta">'red'</span>);</cl-cd>
<cl-cd data-idx="17">&nbsp; &nbsp; gradient.addColorStop(.5, <span class="tMagenta">'orange'</span>);</cl-cd>
<cl-cd data-idx="18">&nbsp; &nbsp; gradient.addColorStop(1, <span class="tMagenta">'green'</span>);</cl-cd>
<cl-cd data-idx="19">&nbsp;</cl-cd>
<cl-cd data-idx="20">&nbsp; &nbsp; <span class="tBlue">let</span> img = <span class="tBlue">new</span> Image();</cl-cd>
<cl-cd data-idx="21">&nbsp; &nbsp; img.onload = () =&gt; mkProg();</cl-cd>
<cl-cd data-idx="22">&nbsp; &nbsp; img.src = <span class="tMagenta">'https://638183.freep.cn/638183/web/svg/3star-01.svg'</span>;</cl-cd>
<cl-cd data-idx="23">&nbsp;</cl-cd>
<cl-cd data-idx="24">&nbsp; &nbsp; <span class="tBlue">let</span> mkProg = () =&gt; {</cl-cd>
<cl-cd data-idx="25">&nbsp; &nbsp; &nbsp; &nbsp; ctx.clearRect(0, 0, 200, 200);</cl-cd>
<cl-cd data-idx="26">&nbsp; &nbsp; &nbsp; &nbsp; ctx.clearRect(0, 0, 200, 200);</cl-cd>
<cl-cd data-idx="27">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tGreen">//底轨圆</span></cl-cd>
<cl-cd data-idx="28">&nbsp; &nbsp; &nbsp; &nbsp; ctx.strokeStyle = <span class="tMagenta">'#ccc'</span>;</cl-cd>
<cl-cd data-idx="29">&nbsp; &nbsp; &nbsp; &nbsp; ctx.fillStyle = <span class="tMagenta">'#eee'</span>;</cl-cd>
<cl-cd data-idx="30">&nbsp; &nbsp; &nbsp; &nbsp; ctx.beginPath();</cl-cd>
<cl-cd data-idx="31">&nbsp; &nbsp; &nbsp; &nbsp; ctx.arc(100, 100, 90, 0, 360 * <span class="tRed">Math</span>.PI/180);</cl-cd>
<cl-cd data-idx="32">&nbsp; &nbsp; &nbsp; &nbsp; ctx.stroke();</cl-cd>
<cl-cd data-idx="33">&nbsp; &nbsp; &nbsp; &nbsp; ctx.fill();</cl-cd>
<cl-cd data-idx="34">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tGreen">//进度圆</span></cl-cd>
<cl-cd data-idx="35">&nbsp; &nbsp; &nbsp; &nbsp; ctx.save();</cl-cd>
<cl-cd data-idx="36">&nbsp; &nbsp; &nbsp; &nbsp; ctx.strokeStyle = gradient;</cl-cd>
<cl-cd data-idx="37">&nbsp; &nbsp; &nbsp; &nbsp; ctx.beginPath();</cl-cd>
<cl-cd data-idx="38">&nbsp; &nbsp; &nbsp; &nbsp; ctx.arc(100, 100, 92, 0, prgDeg * <span class="tRed">Math</span>.PI/180);</cl-cd>
<cl-cd data-idx="39">&nbsp; &nbsp; &nbsp; &nbsp; ctx.stroke();</cl-cd>
<cl-cd data-idx="40">&nbsp; &nbsp; &nbsp; &nbsp; ctx.restore();</cl-cd>
<cl-cd data-idx="41">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tGreen">//旋转图片</span></cl-cd>
<cl-cd data-idx="42">&nbsp; &nbsp; &nbsp; &nbsp; ctx.save();</cl-cd>
<cl-cd data-idx="43">&nbsp; &nbsp; &nbsp; &nbsp; ctx.globalCompositeOperation = <span class="tMagenta">'xor'</span>;</cl-cd>
<cl-cd data-idx="44">&nbsp; &nbsp; &nbsp; &nbsp; ctx.translate(100, 100);</cl-cd>
<cl-cd data-idx="45">&nbsp; &nbsp; &nbsp; &nbsp; ctx.rotate(rotDeg * <span class="tRed">Math</span>.PI/180);</cl-cd>
<cl-cd data-idx="46">&nbsp; &nbsp; &nbsp; &nbsp; ctx.translate(-100, -100);</cl-cd>
<cl-cd data-idx="47">&nbsp; &nbsp; &nbsp; &nbsp; ctx.drawImage(img, 20, 20, 160, 160);</cl-cd>
<cl-cd data-idx="48">&nbsp; &nbsp; &nbsp; &nbsp; ctx.restore();</cl-cd>
<cl-cd data-idx="49">&nbsp; &nbsp; &nbsp; &nbsp; rotDeg = (rotDeg + 1) % 360;</cl-cd>
<cl-cd data-idx="50">&nbsp; &nbsp; &nbsp; &nbsp; raf = aud.paused ? cancelAnimationFrame(raf) : requestAnimationFrame(mkProg);</cl-cd>
<cl-cd data-idx="51">&nbsp; &nbsp; };</cl-cd>
<cl-cd data-idx="52">&nbsp;</cl-cd>
<cl-cd data-idx="53">&nbsp; &nbsp; aud.onpause = aud.onplaying = () =&gt; mkProg();</cl-cd>
<cl-cd data-idx="54">&nbsp; &nbsp; aud.onseeking = () =&gt; raf = cancelAnimationFrame(raf);</cl-cd>
<cl-cd data-idx="55">&nbsp; &nbsp; aud.ontimeupdate = () =&gt; prgDeg = aud.currentTime * 360 / aud.duration;</cl-cd>
<cl-cd data-idx="56">&nbsp;</cl-cd>
<cl-cd data-idx="57">&nbsp; &nbsp; canv.onclick = () =&gt; aud.paused ? aud.play() : aud.pause();</cl-cd>
<cl-cd data-idx="58">})();</cl-cd>
<cl-cd data-idx="59">&lt;<span class="tDarkRed">/script</span>&gt;</cl-cd>
</div>

<script>
(function() {
    let rotDeg = 0, prgDeg = 0, raf;
    let ctx = canv.getContext('2d');
    ctx.lineWidth = 10;
    ctx.lineCap = 'round';

    let gradient = ctx.createLinearGradient(0, 0, 200, 200);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(.5, 'orange');
    gradient.addColorStop(1, 'green');

    let img = new Image();
    img.onload = () => mkProg();
    img.src = 'https://638183.freep.cn/638183/web/svg/3star-01.svg';

    let mkProg = () => {
      ctx.clearRect(0, 0, 200, 200);
      ctx.clearRect(0, 0, 200, 200);
      //底轨圆
      ctx.strokeStyle = '#ccc';
      ctx.fillStyle = '#eee';
      ctx.beginPath();
      ctx.arc(100, 100, 90, 0, 360 * Math.PI/180);
      ctx.stroke();
      ctx.fill();
      //进度圆
      ctx.save();
      ctx.strokeStyle = gradient;
      ctx.beginPath();
      ctx.arc(100, 100, 92, 0, prgDeg * Math.PI/180);
      ctx.stroke();
      ctx.restore();
      //旋转图片
      ctx.save();
      ctx.globalCompositeOperation = 'xor';
      ctx.translate(100, 100);
      ctx.rotate(rotDeg * Math.PI/180);
      ctx.translate(-100, -100);
      ctx.drawImage(img, 20, 20, 160, 160);
      ctx.restore();
      rotDeg = (rotDeg + 1) % 360;
      raf = aud.paused ? cancelAnimationFrame(raf) : requestAnimationFrame(mkProg);
    };

    aud.onpause = aud.onplaying = () => mkProg();
    aud.onseeking = () => raf = cancelAnimationFrame(raf);
    aud.ontimeupdate = () => prgDeg = aud.currentTime * 360 / aud.duration;

    canv.onclick = () => aud.paused ? aud.play() : aud.pause();
})();
</script>

马黑黑 发表于 2024-3-31 12:49

播放器可以调整大小:

源码第 2 行代码,transform: scale(1.2); 中,1.2 表示放大 1.2 倍。一楼使用的数值是 0.8 ,播放器的原始尺寸为 200 * 200。

马黑黑 发表于 2024-3-31 12:50

这里是放大 1.2 倍的效果:

http://mhh.52qingyin.cn/art/show.php?st=4&sd=4&art=mahei_1711860249

庶民 发表于 2024-3-31 13:08

我就是支持。,

马黑黑 发表于 2024-3-31 13:43

庶民 发表于 2024-3-31 13:08
我就是支持。,

{:4_190:}

南无月 发表于 2024-3-31 17:41

马黑黑 发表于 2024-3-31 12:49
播放器可以调整大小:

源码第 2 行代码,transform: scale(1.2); 中,1.2 表示放大 1.2 倍。一楼使用的 ...

transform: scale(1.2);
一句代码就可以改变大小。。太神了。
那么,同理。。钟表的贴子里加上这句,也可以改变大小 {:4_199:}

马黑黑 发表于 2024-3-31 17:43

南无月 发表于 2024-3-31 17:41
transform: scale(1.2);
一句代码就可以改变大小。。太神了。
那么,同理。。钟表的贴子里加上这句,也 ...

是的

南无月 发表于 2024-3-31 17:43

马黑黑 发表于 2024-3-31 12:50
这里是放大 1.2 倍的效果:

http://mhh.52qingyin.cn/art/show.php?st=4&sd=4&art=mahei_1711860249

试了一下把我《凝望》里面的钟表改变,成功变大或者变小,神奇的代码{:4_199:}

马黑黑 发表于 2024-3-31 17:44

南无月 发表于 2024-3-31 17:43
试了一下把我《凝望》里面的钟表改变,成功变大或者变小,神奇的代码

这是CSS的能耐

南无月 发表于 2024-3-31 17:51

马黑黑 发表于 2024-3-31 17:43
是的

哎。。
这么神奇的利器,转到网站了。{:4_173:}

南无月 发表于 2024-3-31 17:52

马黑黑 发表于 2024-3-31 17:44
这是CSS的能耐

CSS挺神的呀

南无月 发表于 2024-3-31 18:05

另存为PNG图片后发现,里面的SVG图形是中空的。。
ctx.globalCompositeOperation = 'xor';
11. xor : 形状在重叠处变为透明,并在其他地方正常绘制;
是合成模式中这句的实例应用。。
{:4_199:}

马黑黑 发表于 2024-3-31 18:06

南无月 发表于 2024-3-31 17:51
哎。。
这么神奇的利器,转到网站了。

{:4_191:}

马黑黑 发表于 2024-3-31 18:08

南无月 发表于 2024-3-31 17:52
CSS挺神的呀

CSS的 transform 属性是形变或转换属性,它能平移(translate)、旋转(rotate)、扭曲(skew)、缩放(scale)元素

红影 发表于 2024-3-31 19:51

看到了globalCompositeOperation = 'xor',下面的彩色让进度条变得如此绚丽多彩{:4_199:}

红影 发表于 2024-3-31 19:52

里面很是轻柔美妙的粉色,在这个季节看着好美啊{:4_187:}

红影 发表于 2024-3-31 19:54

这个能显示进度,不是手动控制进度的模式。估计使用画布的,倒这个程度就不错了吧{:4_187:}

马黑黑 发表于 2024-3-31 20:10

红影 发表于 2024-3-31 19:54
这个能显示进度,不是手动控制进度的模式。估计使用画布的,倒这个程度就不错了吧

canvas画布不想HTML和svg基于DOM节点,它自己只是一个HTML中的节点,子节点不视为HTML元素,要点击画布里的图像需要额外的计算,目前这个w3c提出了一个API,但能实现的只有Chrome且必须在实验室状态下运行。

但不是不能操作,我们撇开API接口,仅通过算法去实现,也是可行的,问题在于代码量会剧增。所以我这个设计,基本上,内圆很靠近画布边缘,这是为了将来如果有余力解决问题时做个铺垫。

马黑黑 发表于 2024-3-31 20:11

红影 发表于 2024-3-31 19:52
里面很是轻柔美妙的粉色,在这个季节看着好美啊
感谢支持

马黑黑 发表于 2024-3-31 20:13

本帖最后由 马黑黑 于 2024-3-31 20:16 编辑

红影 发表于 2024-3-31 19:51
看到了globalCompositeOperation = 'xor',下面的彩色让进度条变得如此绚丽多彩
{:4_190:}
页: [1] 2 3 4 5
查看完整版本: canvas画布圆形进度条播放器