梦驼铃
<style>#papa { position: relative; left: -202px; display: block; margin: auto; box-shadow: 2px 2px 10px #000; user-select: none; z-index: 1; }
#mama { cursor: pointer; }
#tit { font: bold 3em sans-serif; text-shadow: 4px 4px 0 #000; stroke-width: 0.5px; stroke: snow; fill: none; dominant-baseline: text-before-edge; letter-spacing: 4px; }
#tmsg { fill: transparent; stroke: gray; stroke-width: 1px; font: bold 1em sans-serif; }
#btnplay, #btnpause { fill: #ccc; cursor: pointer; display: block; }
#btnpause { display: none; }
#btnplay:hover, #btnpause:hover { fill: orange; }
</style>
<svg id="papa" width="1000" height="553">
<image xlink:href="/data/attachment/forum/202209/07/090849t9n9xgz2rnlaqgbl.jpg" x="0" y="0" width="100%" height="100%" />
<g id="mama" transform="rotate(-90, 900, 453)">
<circle id="track" cx="900" cy="453" r="50" fill="none" stroke-width="10" stroke="rgba(255,255,255,0.65)" />
<circle id="prog" cx="900" cy="453" r="50" fill="none" stroke-width="6" stroke="rgba(57,54,81,0.85)" />
</g>
<polygon id="btnplay" points="890 443, 890 463, 910 453" />
<g id="btnpause">
<rect x="892" y="443" width="5" height="20" />
<rect x="900" y="443" width="5" height="20" />
</g>
<path id="curPath" d="M 850 463 Q 900 400 950 463" fill="none" stroke="none"/>
<path id="durPath" d="M 850 443 Q 900 500 950 443" fill="none" stroke="none"/>
<g id="tmsg">
<text x="40" y="0"><textPath id="curMsg" xlink:href="#curPath" dominant-baseline="text-after-edge">00:00</textPath></text>
<text x="38" y="0"><textPath id="durMsg" xlink:href="#durPath" dominant-baseline="text-before-edge">00:00</textPath></text>
</g>
<text id="tit" x="20" y="20">梦驼铃</text>
</svg>
<script>
let aud = new Audio();
let cc = {
x: 1*track.getAttribute('cx'),
y: 1*track.getAttribute('cy'),
r: 1*track.getAttribute('r'),
sw: 1*track.getAttribute('stroke-width'),
len: track.getTotalLength(),
};
aud.src = 'https://music.163.com/song/media/outer/url?id=1911002130.mp3';
aud.autoplay = true;
aud.loop = true;
prog.style.strokeDasharray = prog.style.strokeDashoffset =cc.len;
aud.addEventListener('pause', () => btnstate());
aud.addEventListener('play',() => btnstate());
aud.addEventListener('timeupdate', () => {
prog.style.strokeDashoffset = cc.len - cc.len * aud.currentTime / aud.duration;
curMsg.textContent = toMin(aud.currentTime);
durMsg.textContent = toMin(aud.duration);
});
btnplay.onclick = btnpause.onclick = () => aud.paused ? aud.play() : aud.pause();
mama.onclick = (e) => {
let deg = Math.atan2(e.offsetY - cc.y, e.offsetX - cc.x) * 180 / Math.PI;
deg += (e.offsetX < cc.x && e.offsetY < cc.y) ? 450 : 90;
aud.currentTime = aud.duration * deg / 360;
};
let btnstate = () => aud.paused ? (btnplay.style.display = 'block', btnpause.style.display = 'none') : (btnplay.style.display = 'none', btnpause.style.display = 'block');
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>
源码
<style>
#papa { position: relative; left: 202px; display: block; margin: auto; box-shadow: 2px 2px 10px #000; user-select: none; z-index: 1; }
#mama { cursor: pointer; }
#tit { font: bold 3em sans-serif; text-shadow: 4px 4px 0 #000; stroke-width: 0.5px; stroke: snow; fill: none; dominant-baseline: text-before-edge; letter-spacing: 4px; }
#tmsg { fill: transparent; stroke: gray; stroke-width: 1px; font: bold 1em sans-serif; }
#btnplay, #btnpause { fill: #ccc; cursor: pointer; display: block; }
#btnpause { display: none; }
#btnplay:hover, #btnpause:hover { fill: orange; }
</style>
<svg id="papa" width="1000" height="553">
<image xlink:href="/data/attachment/forum/202209/07/090849t9n9xgz2rnlaqgbl.jpg" x="0" y="0" width="100%" height="100%" />
<g id="mama" transform="rotate(-90, 900, 453)">
<circle id="track" cx="900" cy="453" r="50" fill="none" stroke-width="10" stroke="rgba(255,255,255,0.65)" />
<circle id="prog" cx="900" cy="453" r="50" fill="none" stroke-width="6" stroke="rgba(57,54,81,0.85)" />
</g>
<polygon id="btnplay" points="890 443, 890 463, 910 453" />
<g id="btnpause">
<rect x="892" y="443" width="5" height="20" />
<rect x="900" y="443" width="5" height="20" />
</g>
<path id="curPath" d="M 850 463 Q 900 400 950 463" fill="none" stroke="none"/>
<path id="durPath" d="M 850 443 Q 900 500 950 443" fill="none" stroke="none"/>
<g id="tmsg">
<text x="40" y="0"><textPath id="curMsg" xlink:href="#curPath" dominant-baseline="text-after-edge">00:00</textPath></text>
<text x="38" y="0"><textPath id="durMsg" xlink:href="#durPath" dominant-baseline="text-before-edge">00:00</textPath></text>
</g>
<text id="tit" x="20" y="20">梦驼铃</text>
</svg>
<script>
let aud = new Audio();
let cc = {
x: 1*track.getAttribute('cx'),
y: 1*track.getAttribute('cy'),
r: 1*track.getAttribute('r'),
sw: 1*track.getAttribute('stroke-width'),
len: track.getTotalLength(),
};
aud.src = 'https://music.163.com/song/media/outer/url?id=1911002130.mp3';
aud.autoplay = true;
aud.loop = true;
prog.style.strokeDasharray = prog.style.strokeDashoffset =cc.len;
aud.addEventListener('pause', () => btnstate());
aud.addEventListener('play',() => btnstate());
aud.addEventListener('timeupdate', () => {
prog.style.strokeDashoffset = cc.len - cc.len * aud.currentTime / aud.duration;
curMsg.textContent = toMin(aud.currentTime);
durMsg.textContent = toMin(aud.duration);
});
btnplay.onclick = btnpause.onclick = () => aud.paused ? aud.play() : aud.pause();
mama.onclick = (e) => {
let deg = Math.atan2(e.offsetY - cc.y, e.offsetX - cc.x) * 180 / Math.PI;
deg += (e.offsetX < cc.x && e.offsetY < cc.y) ? 450 : 90;
aud.currentTime = aud.duration * deg / 360;
};
let btnstate = () => aud.paused ? (btnplay.style.display = 'block', btnpause.style.display = 'none') : (btnplay.style.display = 'none', btnpause.style.display = 'block');
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>
本帖尝试使用纯 svg 做帖子。帖子就是一个 svg 标签,其内有若干 svg 的子标签。
svg 支持 CSS 对它的诸多元素的定义,也以自己的方式接受 JS 的指令,所以,帖子也是用 CSS、JS。
但 svg 并非易于操控,它的开发,初始意图主要不是人工写代码的,所以语法、语句非常繁琐,不宜掌握、控制,本帖仅作为演示,不建议用来做帖子,除非你可以随意摆布本帖 svg 内的元素,例如,把圆环播放器整体挪个位置。
个人觉得帖子这个圆环播放器也挺漂亮,我会在有空的时候单独封装,令其成为一个 HTML 元素,可以随便调整位置。 好漂亮的制作。学习学习!老黑辛苦了!{:4_190:}
我这强迫症……{:5_103:}{:5_117:}
黑黑把这5小只加进去,<br><br><br><br><br> 让你帅得光芒万丈的头像完整展现在世人面前,亮瞎那谁谁
https://pic.imgdb.cn/item/6317fcf016f2c2beb18645d7.png
欣赏老师的精彩代码,感谢!{:4_204:} 马黑黑 发表于 2022-9-7 09:22
本帖尝试使用纯 svg 做帖子。帖子就是一个 svg 标签,其内有若干 svg 的子标签。
svg 支持 CSS 对它的诸 ...
在路径上,对于curPath 设置了 d="M 850 463 Q 900 400 950 463",对于durPath设置了d="M 850 443 Q 900 500 950 443",这两个一个朝上弯一个朝下弯,护住了播放按钮,倒也好看呢{:4_187:}
马黑黑 发表于 2022-9-7 09:22
本帖尝试使用纯 svg 做帖子。帖子就是一个 svg 标签,其内有若干 svg 的子标签。
svg 支持 CSS 对它的诸 ...
仔细看了看,移动这个圆环要跟着移动的东西不少,只要都考虑倒了,也是能移动的呀{:4_173:} 再来欣赏! 这个帖子厉害了,只有CSS和JS,没HTML什么事啊。
等着看你让这些SVG"令其成为一个 HTML 元素"。猜想是多设一个块,都扔里面? 安宁 发表于 2022-9-7 10:11
我这强迫症……
黑黑把这5小只加进去, 让你帅得光芒万丈的头像完整展现在世 ...
俺习惯不要脸{:4_170:}
其实有更简单的做法:帖子父元素加一个 margin-top: 120px 也是可以的。 醉美水芙蓉 发表于 2022-9-7 11:40
欣赏学习黑黑老师佳作!
感谢支持 梦缘 发表于 2022-9-7 10:13
欣赏老师的精彩代码,感谢!
客气客气 红影 发表于 2022-9-7 11:14
在路径上,对于curPath 设置了 d="M 850 463 Q 900 400 950 463",对于durPath设置了d="M 850 443 Q 900...
路径的设计,我用了二次赛贝尔曲线,M 的数字是曲线起点,Q 的第一组数字是控制点,第二组数字是曲线终点。我想其实可以用弧线 A 代替 Q,可能更好控制。 红影 发表于 2022-9-7 11:20
这个帖子厉害了,只有CSS和JS,没HTML什么事啊。
等着看你让这些SVG"令其成为一个 HTML 元素"。猜想是多设 ...
严格来讲,svg 的这种用法,仍然是HTML,svg是HTML的一个元素,这里只是不需要其他HTML元素而已。
常规封装,svg 将作为父元素的子元素,歌词与按钮或分离或组合,分离的话用到两个svg,组合的话只用一个svg。 红影 发表于 2022-9-7 11:17
仔细看了看,移动这个圆环要跟着移动的东西不少,只要都考虑倒了,也是能移动的呀
对。主要是播放时间信息的路径,需要重新设计。还有就是 <g id="mama" ..>的旋转基点,要改为与两个圆环的圆心一致。 马黑黑 发表于 2022-9-7 12:04
路径的设计,我用了二次赛贝尔曲线,M 的数字是曲线起点,Q 的第一组数字是控制点,第二组数字是曲线终点 ...
弧线A貌似你没讲过,但贝尔曲线你讲解过的,那就贝尔曲线呗{:4_173:} 马黑黑 发表于 2022-9-7 12:08
对。主要是播放时间信息的路径,需要重新设计。还有就是 的旋转基点,要改为与两个圆环的圆心一致。
这个不愁,算了位置都能准确放好的{:4_204:} 黑黑固然一天一个,黑神你太厉害了{:4_178:}