马黑黑 发表于 2025-9-8 13:26

SVG心形路径播放按钮(带进度指示)

<div class="codebox" data-prev="1">
&lt;style&gt;
        #heart { fill: pink; stroke: red; stroke-width: 4; transition: 0.25s; cursor: pointer; }
&lt;/style&gt;

&lt;svg id="msvg" width="200" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="-200 -200 400 400"&gt;
        &lt;path id="heart" d="M0 190 C-200 20,-300 -320,0 -100 C300 -320,200 20,0 190" stroke-dasharray="1227" stroke-dashoffset="1227"&gt;
                &lt;title id="tit"&gt;播放/暂停&lt;/title&gt;
        &lt;/path&gt;
&lt;/svg&gt;
&lt;audio id="aud" src="https://music.163.com/song/media/outer/url?id=555121065" autoplay loop&gt;&lt;/audio&gt;

&lt;script&gt;
        const pathlength = heart.getTotalLength(); // 获取路径长度

        // 音频播放时 : 进度变更+跳动
        aud.ontimeupdate = () =&gt; {
                heart.setAttribute('stroke-dashoffset', pathlength - pathlength * aud.currentTime / aud.duration);
                heart.setAttribute('opacity', Math.random() * 0.5 + 0.5);
        };

        // 点击心形路径 : 播放/暂停
        heart.onclick = () =&gt; aud.paused ? aud.play() : aud.pause();

        // 提示语
        aud.onplaying = aud.onpause = () =&gt; tit.textContent = aud.paused ? '点击播放' : '点击暂停';
&lt;/script&gt;
</div>

<script type="module">
import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js';
linenumber();
</script>

马黑黑 发表于 2025-9-8 13:41

SVG设置有 viewBox 属性,这意味着,不论 SVG 宽高如何设置,绘制于 viewBox 之内的路径长度都是固定的、不因SVG的宽高而改变。因此通过 svg元素.getTotalLength() 函数获得路径长度(这里约等于1227)可以直接用于设置 path 标签的偏移相关属性值,后面的JS重新获取路径长度是为了计算更精准。

如果希望还可以控制音频的播放进度,那情况会复杂得多。我们之前的小播插件中,有用不规则路径做的,其实现原理大约酱紫:

一、采集路径上的点坐标,一般存入数组中;
二、获取鼠标指针在路径上点击的点的坐标数据,并和路径点坐标集合进行比对,确定相符的点坐标数据;
三、根据该点坐标数据,确定该点和路径起点的距离;
四、计算音频应播放到的时间节点。

核心就是确定点击点离路径开始点的距离,处理起来需要相当多的复杂计算,所用到的数学原理和JS内置的操作svg的相关API也会比较多。

花飞飞 发表于 2025-9-8 18:37

这个沿不规则SVG路径做进度条的,比规则的计算复杂的多了吧。。。{:4_199:}今天这是又升级啦

花飞飞 发表于 2025-9-8 18:52

stroke-dasharray="1227" stroke-dashoffset="1227"
看到这两个熟面孔,虚线和偏移量都是1227,这是怎么算出来的呢。

JS里都看不太懂了,只知道这句是透明度随机
heart.setAttribute('opacity', Math.random() * 0.5 + 0.5);{:4_170:}

花飞飞 发表于 2025-9-8 18:55

代码简洁,核心计算强悍。。
之前做过类似的自由路径播放器,效果一样精彩

马黑黑 发表于 2025-9-8 19:06

花飞飞 发表于 2025-9-8 18:55
代码简洁,核心计算强悍。。
之前做过类似的自由路径播放器,效果一样精彩

谢赞

马黑黑 发表于 2025-9-8 19:07

花飞飞 发表于 2025-9-8 18:52
stroke-dasharray="1227" stroke-dashoffset="1227"
看到这两个熟面孔,虚线和偏移量都是1227,这是怎么算 ...

1227在二楼不是讲到了吗?

马黑黑 发表于 2025-9-8 19:08

花飞飞 发表于 2025-9-8 18:37
这个沿不规则SVG路径做进度条的,比规则的计算复杂的多了吧。。。今天这是又升级啦

这个确实复杂,不过以前做过的

杨帆 发表于 2025-9-8 19:13

漂亮!谢谢马老师精彩分享{:4_191:}

马黑黑 发表于 2025-9-8 19:15

杨帆 发表于 2025-9-8 19:13
漂亮!谢谢马老师精彩分享

{:4_190:}

花飞飞 发表于 2025-9-8 20:22

马黑黑 发表于 2025-9-8 19:08
这个确实复杂,不过以前做过的

记得做过,我曾用过杯子,小伞,还可以自己根据形状画的路径。。
那时候觉得换个路径就可以啦{:4_173:}没有认真学原理

花飞飞 发表于 2025-9-8 21:27

马黑黑 发表于 2025-9-8 19:07
1227在二楼不是讲到了吗?

看到了说是它自己计算的{:4_173:}

花飞飞 发表于 2025-9-8 21:28

马黑黑 发表于 2025-9-8 19:06
谢赞

多来几个谢,果子不够了{:4_173:}

红影 发表于 2025-9-8 21:59

这颗粉色的心做过漂亮的虚线偏移,现在又做了带路径的播放按钮,黑黑对它开发运用得真好{:4_187:}

红影 发表于 2025-9-8 22:00

上次的心是大小变化的,这次的是明暗变化,无论怎样,都做成了动态的呢{:4_204:}

马黑黑 发表于 2025-9-9 08:22

红影 发表于 2025-9-8 22:00
上次的心是大小变化的,这次的是明暗变化,无论怎样,都做成了动态的呢

虽然很蹩脚

马黑黑 发表于 2025-9-9 08:22

红影 发表于 2025-9-8 21:59
这颗粉色的心做过漂亮的虚线偏移,现在又做了带路径的播放按钮,黑黑对它开发运用得真好

粗糙的制作

红影 发表于 2025-9-9 22:13

马黑黑 发表于 2025-9-9 08:22
虽然很蹩脚

哪里,都很漂亮呢{:4_187:}

红影 发表于 2025-9-9 22:13

马黑黑 发表于 2025-9-9 08:22
粗糙的制作

咋一下子变这么谦虚了{:4_172:}

马黑黑 发表于 2025-9-9 22:48

红影 发表于 2025-9-9 22:13
咋一下子变这么谦虚了

胡须长了
页: [1] 2
查看完整版本: SVG心形路径播放按钮(带进度指示)