马黑黑 发表于 2022-8-29 12:27

进度可调+透明遮罩的圆环播放器

本帖最后由 马黑黑 于 2022-8-29 12:36 编辑 <br /><br /><style>
#papa { margin: auto; width: 750px; height: 560px; box-shadow: 3px 3px 20px #000; background: lightblue; position: relative; }
#h5player { position: absolute; display: grid; place-items: center; width: 100px; height: 100px; right: 20px; bottom: 20px; background: teal; border-radius: 50%; background: tan conic-gradient(from 0deg, red, green, red 1%, snow 0); mask: radial-gradient(transparent 90%, red 91%, red 0); -webkit-mask: radial-gradient(transparent 60%, red 61%, red 0); cursor: pointer; }
#tmsg { position: absolute; right: 50px; bottom: 50px; font: normal 14px sans-serif; }
#lrctext { position: absolute; left: 20px; top: 20px; font: bold 24px sans-serif; }
</style>

<div id="papa">
        <span id="tmsg">00:00<br>00:00</span>
        <span id="h5player"></span>
        <span id="lrctext">lrc歌词</span>
</div>

<script>
let aud = new Audio();
let lrcAr = [ ['0.00','耶利亚女郎 - 歌词省略'],['240.00','谢谢支持'] ]
aud.src = 'https://music.163.com/song/media/outer/url?id=150852.mp3';
aud.autoplay = true;
aud.loop = true;

h5player.onclick = (e) => {
        if (isHover(e.offsetX, e.offsetY)) { //轨道
                let deg = Math.atan2(e.offsetY - 50, e.offsetX - 50) * 180 / Math.PI;
                deg += (e.offsetX < 50 && e.offsetY < 50) ?450 : 90;
                aud.currentTime = aud.duration * deg / 360;
        } else { //内区域
                aud.paused ? aud.play() : aud.pause();
        }
}

aud.addEventListener('timeupdate', () => {
        tmsg.innerHTML = toMin(aud.duration) + '<br>' + toMin(aud.currentTime);
        h5player.style.background = 'conic-gradient(from 0deg, red, green, red ' + aud.currentTime / aud.duration * 100 + '%, snow 0)';
        for(j = 0; j < lrcAr.length;j ++) {
                if(aud.currentTime >= lrcAr) lrctext.innerHTML = lrcAr;
        }
});

let isHover = (x,y) => Math.pow(x - 50, 2) + Math.pow(y - 50, 2) >= Math.pow(40, 2);

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

马黑黑 发表于 2022-8-29 12:29

本帖最后由 马黑黑 于 2022-8-29 12:35 编辑

源码:
<style>
#papa { margin: auto; width: 750px; height: 560px; box-shadow: 3px 3px 20px #000; background: lightblue; position: relative; }
#h5player { position: absolute; display: grid; place-items: center; width: 100px; height: 100px; right: 20px; bottom: 20px; background: teal; border-radius: 50%; background: tan conic-gradient(from 0deg, red, green, red 1%, snow 0); mask: radial-gradient(transparent 90%, red 91%, red 0); -webkit-mask: radial-gradient(transparent 60%, red 61%, red 0); cursor: pointer; }
#tmsg { position: absolute; right: 50px; bottom: 50px; font: normal 14px sans-serif; }
#lrctext { position: absolute; left: 20px; top: 20px; font: bold 24px sans-serif; }
</style>

<div id="papa">
      <span id="tmsg">00:00<br>00:00</span>
      <span id="h5player"></span>
      <span id="lrctext">lrc歌词</span>
</div>

<script>
let aud = new Audio();
let lrcAr = [ ['0.00','耶利亚女郎 - 歌词省略'],['240.00','谢谢支持'] ]
aud.src = 'https://music.163.com/song/media/outer/url?id=150852.mp3';
aud.autoplay = true;
aud.loop = true;

h5player.onclick = (e) => {
      if (isHover(e.offsetX, e.offsetY)) { //轨道
                let deg = Math.atan2(e.offsetY - 50, e.offsetX - 50) * 180 / Math.PI;
                deg += (e.offsetX < 50 && e.offsetY < 50) ?450 : 90;
                aud.currentTime = aud.duration * deg / 360;
      } else { //内区域
                aud.paused ? aud.play() : aud.pause();
      }
}

aud.addEventListener('timeupdate', () => {
      tmsg.innerHTML = toMin(aud.duration) + '\n' + toMin(aud.currentTime);
      h5player.style.background = 'conic-gradient(from 0deg, red, green, red ' + aud.currentTime / aud.duration * 100 + '%, snow 0)';
      for(j = 0; j < lrcAr.length;j ++) {
                if(aud.currentTime >= lrcAr) lrctext.innerHTML = lrcAr;
      }
});

let isHover = (x,y) => Math.pow(x - 50, 2) + Math.pow(y - 50, 2) >= Math.pow(40, 2);

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

马黑黑 发表于 2022-8-29 12:39

与使用伪元素遮罩相比,mask透明遮罩能令圆环内区域与帖子背景融为一体,这是它的优点。

缺点也有:

① 锯齿;
② 播放时间信息与播放器没有隶属关系,需要额外定位。

梦油 发表于 2022-8-29 14:48

黑黑朋友下午好!我很久没有听《耶利亚女郎》了。谢谢你。

马黑黑 发表于 2022-8-29 18:15

梦油 发表于 2022-8-29 14:48
黑黑朋友下午好!我很久没有听《耶利亚女郎》了。谢谢你。

{:4_190:}

加林森 发表于 2022-8-29 19:36

有看没有懂。伪元素遮罩到底是什么?

马黑黑 发表于 2022-8-29 19:57

加林森 发表于 2022-8-29 19:36
有看没有懂。伪元素遮罩到底是什么?

你都用了咋没看懂呢

加林森 发表于 2022-8-29 20:14

马黑黑 发表于 2022-8-29 19:57
你都用了咋没看懂呢

我是摸索出来的,用对了啊。{:4_205:}

马黑黑 发表于 2022-8-29 20:47

加林森 发表于 2022-8-29 20:14
我是摸索出来的,用对了啊。

那挺好的

加林森 发表于 2022-8-29 20:48

马黑黑 发表于 2022-8-29 20:47
那挺好的

谢谢你耐心地教我啊。{:4_191:}

马黑黑 发表于 2022-8-29 20:48

加林森 发表于 2022-8-29 20:48
谢谢你耐心地教我啊。

不是教,是讨论

加林森 发表于 2022-8-29 20:51

马黑黑 发表于 2022-8-29 20:48
不是教,是讨论

好的好的。

红影 发表于 2022-8-29 21:04

马黑黑 发表于 2022-8-29 12:39
与使用伪元素遮罩相比,mask透明遮罩能令圆环内区域与帖子背景融为一体,这是它的优点。

缺点也有:


透明遮罩好,省得还得去调圆环里的颜色了{:4_173:}

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

黑黑厉害,这么快又写出圆环播放器可调进度的代码了{:4_199:}

小辣椒 发表于 2022-8-29 21:53

马黑黑 发表于 2022-8-29 12:39
与使用伪元素遮罩相比,mask透明遮罩能令圆环内区域与帖子背景融为一体,这是它的优点。

缺点也有:


这个可以啊,也是一样漂亮的

马黑黑 发表于 2022-8-29 21:53

红影 发表于 2022-8-29 21:05
黑黑厉害,这么快又写出圆环播放器可调进度的代码了

而且还不复杂,就是知识点要点烧脑,多数人会觉得很难理解

马黑黑 发表于 2022-8-29 21:54

小辣椒 发表于 2022-8-29 21:53
这个可以啊,也是一样漂亮的

就是,如果颜色反差大的话,锯齿会有,不过可以用blur滤镜弄一下

马黑黑 发表于 2022-8-29 21:54

红影 发表于 2022-8-29 21:04
透明遮罩好,省得还得去调圆环里的颜色了

个个都懒哈

小辣椒 发表于 2022-8-29 22:00

黑黑,这个代码我电脑预览小圆里面的时间移动出小圆了,是什么原因啊

马黑黑 发表于 2022-8-29 22:03

小辣椒 发表于 2022-8-29 22:00
黑黑,这个代码我电脑预览小圆里面的时间移动出小圆了,是什么原因啊

不同环境,尺寸会有变化。我再封装一个不会移出的,你等一下下
页: [1] 2 3
查看完整版本: 进度可调+透明遮罩的圆环播放器