空空如也
<style>#papa { left: -214px; width: 1024px; height: 640px; background: #666 url('/data/attachment/forum/202209/06/074904leqeezdkdihvu6w4.jpg') no-repeat center/cover; display: grid; place-items: center; box-shadow: 3px 3px 20px #000; user-select: none; position: relative; z-index: 1;}
#mplayer { position: absolute;right: 100px; bottom: 20px; width: 120px; height: 120px; border-radius: 50%; overflow: hidden; }
#track { stroke: url(#gradient); }
#lrc { position: absolute; display: block; top: 20px; }
#lrctxt { dominant-baseline: middle; fill: url(#gradient); font: bold 2.2em sans-serif; text-shadow: -2px -2px 0px snow, 2px 2px 3px #000; letter-spacing: 3px; }
</style>
<div id="papa">
<div id="mplayer">
<svg width="100%" height="100%" shape-rendering="geometricPrecision">
<g transform="rotate(-90, 60, 60)">
<circle id="track" cx="60" cy="60" r="55" fill="none" stroke="rgba(255,255,255,.5)" stroke-width="10" stroke-dasharray="2" stroke-opacity="0.35" />
<circle id="prog" cx="60" cy="60" r="55" fill="none" stroke="red" stroke-width="3" stroke-opacity="0.65"/>
</g>
<text fill="orange">
<tspan id="cur" x="40" y="55">00:00</tspan>
<tspan id="dur" x="40" y="75">00:00</tspan>
</text>
</svg>
</div>
<svg id="lrc" width="410" height="150">
<defs><path id="lrcPath" fill="none" stroke="red" d="M 20 20 Q 200 180 400 20" /></defs>
<defs>
<linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="blue"/>
<stop offset="35%" stop-color="orange"/>
<stop offset="65%" stop-color="gray"/>
<stop offset="100%" stop-color="red"/>
</linearGradient>
</defs>
<text x="0" y="20"><textPath id="lrctxt" xlink:href="#lrcPath">任然 - 空空如也</textPath></text>
</svg>
</div>
<script>
let lrcAr = [
['0.00','空空如也 - 任然'],
['14.06','熟悉的 陌生的 这种感觉'],
['17.04','重复的 曾经的 那些情节'],
['20.06','也只是 怀念'],
['26.07','一滴滴 一点点 一页一篇'],
['29.07','分手了 也不过 三百多天'],
['32.05','可我却 害怕遇见'],
['37.04','我懵懵懂懂过了一年'],
['40.04','这一年似乎没有改变'],
['43.05','守着你离开后的世界'],
['45.09','空 空如也'],
['49.06','白天和晚上都是冬夜'],
['52.06','悲伤的到来我从不拒绝'],
['57.03','反正亦是'],
['58.09','空空空空如也'],
['62.00','我懵懵懂懂过了一年'],
['65.01','徘徊在石板路的街边'],
['68.00','曾经笑容灿烂如今却'],
['70.05','空空如也'],
['74.02','一切的星光都已陨灭'],
['77.04','得过且过是我如今速写'],
['81.03','无所谓 让痛重叠'],
['111.05','我懵懵懂懂过了一年'],
['114.02','这一年似乎没有改变'],
['117.03','守着你离开后的世界'],
['119.07','空 空如也'],
['123.05','白天和晚上都是冬夜'],
['126.04','悲伤的到来我从不拒绝'],
['131.02','反正亦是'],
['132.08','空空空空如也'],
['135.09','我懵懵懂懂过了一年'],
['138.09','徘徊在石板路的街边'],
['141.09','曾经笑容灿烂如今却'],
['144.03','空空如也'],
['148.01','一切的星光都已陨灭'],
['151.00','得过且过是我如今速写'],
['155.01','无所谓 让痛重叠'],
['160.03','我懵懵懂懂过了一年'],
['163.05','这一年似乎没有改变'],
['166.07','守着你离开后的世界'],
['169.00','空 空如也'],
['172.08','白天和晚上都是冬夜'],
['175.08','悲伤的到来我从不拒绝'],
['180.04','反正亦是'],
['182.01','空空空空如也'],
['184.09','我懵懵懂懂过了一年'],
['188.01','徘徊在石板路的街边'],
['191.02','曾经笑容灿烂如今却'],
['193.05','空空如也'],
['197.04','一切的星光都已陨灭'],
['200.04','得过且过是我如今速写'],
['204.04','无所谓 让痛重叠']
];
let aud = new Audio();
aud.src = 'https://music.163.com/song/media/outer/url?id=526464293.mp3';
aud.autoplay = true;
aud.loop = true;
let girth = prog.getTotalLength();
prog.style.strokeDasharray = prog.style.strokeDashoffset = girth+ 'px';
mplayer.onmousemove = (e) => {
if (isHover(e.offsetX, e.offsetY))mplayer.style.cursor = 'pointer';
}
mplayer.onclick = (e) => {
if (isHover(e.offsetX, e.offsetY)) {
let deg = Math.atan2(e.offsetY - 60, e.offsetX - 60) * 180 / Math.PI;
deg += (e.offsetX < 60 && e.offsetY < 60) ?450 : 90;
aud.currentTime = aud.duration * deg / 360;
} else {
aud.paused ? aud.play() : aud.pause();
}
}
aud.addEventListener('timeupdate', () => {
prog.style.strokeDashoffset = girth - girth * aud.currentTime / aud.duration + 'px';
cur.textContent = toMin(aud.currentTime);
dur.textContent = toMin(aud.duration);
for(j=0; j<lrcAr.length; j++) {
if(aud.currentTime >= lrcAr) lrctxt.textContent = lrcAr;
}
});
let isHover = (x,y) => Math.pow(x - 60, 2) + Math.pow(y - 60, 2) >= Math.pow(45, 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>
代码:
<style>
#papa { left: -214px; width: 1024px; height: 640px; background: #666 url('/data/attachment/forum/202209/06/074904leqeezdkdihvu6w4.jpg') no-repeat center/cover; display: grid; place-items: center; box-shadow: 3px 3px 20px #000; user-select: none; position: relative; z-index: 1;}
#mplayer { position: absolute;right: 100px; bottom: 20px; width: 120px; height: 120px; border-radius: 50%; overflow: hidden; }
#track { stroke: url(#gradient); }
#lrc { position: absolute; display: block; top: 20px; }
#lrctxt { dominant-baseline: middle; fill: url(#gradient); font: bold 2.2em sans-serif; text-shadow: -2px -2px 0px snow, 2px 2px 3px #000; letter-spacing: 3px; }
</style>
<div id="papa">
<div id="mplayer">
<svg width="100%" height="100%" shape-rendering="geometricPrecision">
<g transform="rotate(-90, 60, 60)">
<circle id="track" cx="60" cy="60" r="55" fill="none" stroke="rgba(255,255,255,.5)" stroke-width="10" stroke-dasharray="2" stroke-opacity="0.35" />
<circle id="prog" cx="60" cy="60" r="55" fill="none" stroke="red" stroke-width="3" stroke-opacity="0.65"/>
</g>
<text fill="orange">
<tspan id="cur" x="40" y="55">00:00</tspan>
<tspan id="dur" x="40" y="75">00:00</tspan>
</text>
</svg>
</div>
<svg id="lrc" width="410" height="150">
<defs><path id="lrcPath" fill="none" stroke="red" d="M 20 20 Q 200 180 400 20" /></defs>
<defs>
<linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="blue"/>
<stop offset="35%" stop-color="orange"/>
<stop offset="65%" stop-color="gray"/>
<stop offset="100%" stop-color="red"/>
</linearGradient>
</defs>
<text x="0" y="20"><textPath id="lrctxt" xlink:href="#lrcPath">任然 - 空空如也</textPath></text>
</svg>
</div>
<script>
let lrcAr = [
['0.00','空空如也 - 任然'],
['14.06','熟悉的 陌生的 这种感觉'],
['17.04','重复的 曾经的 那些情节'],
['20.06','也只是 怀念'],
['26.07','一滴滴 一点点 一页一篇'],
['29.07','分手了 也不过 三百多天'],
['32.05','可我却 害怕遇见'],
['37.04','我懵懵懂懂过了一年'],
['40.04','这一年似乎没有改变'],
['43.05','守着你离开后的世界'],
['45.09','空 空如也'],
['49.06','白天和晚上都是冬夜'],
['52.06','悲伤的到来我从不拒绝'],
['57.03','反正亦是'],
['58.09','空空空空如也'],
['62.00','我懵懵懂懂过了一年'],
['65.01','徘徊在石板路的街边'],
['68.00','曾经笑容灿烂如今却'],
['70.05','空空如也'],
['74.02','一切的星光都已陨灭'],
['77.04','得过且过是我如今速写'],
['81.03','无所谓 让痛重叠'],
['111.05','我懵懵懂懂过了一年'],
['114.02','这一年似乎没有改变'],
['117.03','守着你离开后的世界'],
['119.07','空 空如也'],
['123.05','白天和晚上都是冬夜'],
['126.04','悲伤的到来我从不拒绝'],
['131.02','反正亦是'],
['132.08','空空空空如也'],
['135.09','我懵懵懂懂过了一年'],
['138.09','徘徊在石板路的街边'],
['141.09','曾经笑容灿烂如今却'],
['144.03','空空如也'],
['148.01','一切的星光都已陨灭'],
['151.00','得过且过是我如今速写'],
['155.01','无所谓 让痛重叠'],
['160.03','我懵懵懂懂过了一年'],
['163.05','这一年似乎没有改变'],
['166.07','守着你离开后的世界'],
['169.00','空 空如也'],
['172.08','白天和晚上都是冬夜'],
['175.08','悲伤的到来我从不拒绝'],
['180.04','反正亦是'],
['182.01','空空空空如也'],
['184.09','我懵懵懂懂过了一年'],
['188.01','徘徊在石板路的街边'],
['191.02','曾经笑容灿烂如今却'],
['193.05','空空如也'],
['197.04','一切的星光都已陨灭'],
['200.04','得过且过是我如今速写'],
['204.04','无所谓 让痛重叠']
];
let aud = new Audio();
aud.src = 'https://music.163.com/song/media/outer/url?id=526464293.mp3';
aud.autoplay = true;
aud.loop = true;
let girth = prog.getTotalLength();
prog.style.strokeDasharray = prog.style.strokeDashoffset = girth+ 'px';
mplayer.onmousemove = (e) => {
if (isHover(e.offsetX, e.offsetY))mplayer.style.cursor = 'pointer';
}
mplayer.onclick = (e) => {
if (isHover(e.offsetX, e.offsetY)) {
let deg = Math.atan2(e.offsetY - 60, e.offsetX - 60) * 180 / Math.PI;
deg += (e.offsetX < 60 && e.offsetY < 60) ?450 : 90;
aud.currentTime = aud.duration * deg / 360;
} else {
aud.paused ? aud.play() : aud.pause();
}
}
aud.addEventListener('timeupdate', () => {
prog.style.strokeDashoffset = girth - girth * aud.currentTime / aud.duration + 'px';
cur.textContent = toMin(aud.currentTime);
dur.textContent = toMin(aud.duration);
for(j=0; j<lrcAr.length; j++) {
if(aud.currentTime >= lrcAr) lrctxt.textContent = lrcAr;
}
});
let isHover = (x,y) => Math.pow(x - 60, 2) + Math.pow(y - 60, 2) >= Math.pow(45, 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-9-6 09:53 编辑
圆环播放器在HIGH歌基础上略作调整,将进度圆环的 stroke-width 设置为比轨迹圆环的小一点。
lrc歌词文本使用了路径(帖子中间“空空如也”四个字是图片自身设计的),
<path id="lrcPath" fill="none" stroke="red" d="M 20 20 Q 200 180 400 20" />
路径头尾用 <defs> ... </defs> 标签包裹,意在隐藏路径(路径不显示),也可以设置路径的 fill 和 stroke 为 none。
路径 id 要捆绑在 textPahth 里面。使用文本路径,textPath 是必须的,作为 text 的子标签并和 tspan 一样充当文本显示的角色 空了来学习。 马黑黑 发表于 2022-9-6 08:00
圆环播放器在HIGH歌基础上略作调整,将进度圆环的 stroke-width 设置为比轨迹圆环的小一点。
lrc歌词文 ...
看到你设置成了3,这样那些散热片就能露出来了呢。
还设置了个弯弧标题呢,使用了svg里path路径,不知道这个功能以前讲过没有,即使讲过我也没记住,真正的《空空如也》{:4_173:} 黑黑先生早晨好!你的制作独辟蹊径,出其不虞,很有新意。 d="M 20 20 Q 200 180 400 20" 这里面的数字都代表什么啊,就是这些数字让文字弯曲的吧{:4_173:} 感谢老师的代码分享,欣赏学习,问好!{:4_187:} 醉美水芙蓉 发表于 2022-9-6 11:41
欣赏学习黑黑老师佳作!
{:4_191:} 梦缘 发表于 2022-9-6 11:21
感谢老师的代码分享,欣赏学习,问好!
{:4_191:} 红影 发表于 2022-9-6 09:41
d="M 20 20 Q 200 180 400 20" 这里面的数字都代表什么啊,就是这些数字让文字弯曲的吧
svg路径很强大,用它可以绘制所有图形 梦油 发表于 2022-9-6 09:28
黑黑先生早晨好!你的制作独辟蹊径,出其不虞,很有新意。
{:4_190:} 加林森 发表于 2022-9-6 08:06
空了来学习。
{:4_190:} 红影 发表于 2022-9-6 09:20
看到你设置成了3,这样那些散热片就能露出来了呢。
还设置了个弯弧标题呢,使用了svg里path路径,不知道 ...
路径有讲过的 制作真棒,图片很有感觉,必须学习 {:4_187:}{:4_179:} 大猫咪 发表于 2022-9-6 12:23
制作真棒,图片很有感觉,必须学习
{:4_191:} 马黑黑 发表于 2022-9-6 12:22
谢茶! 加林森 发表于 2022-9-6 12:24
谢茶!
客气了 马黑黑 发表于 2022-9-6 12:24
客气了
嗯嗯。