逃亡 part2
<style>@import 'https://638183.freep.cn/638183/web/css/tz01.css';
#pa { --offsetX: 64px; --bg: #ccc url('https://638183.freep.cn/638183/t24/w6/tcwh.webp') no-repeat center/cover; }
#progress { position: absolute; width: 15vw; height: 15vw; right: 20px; bottom: 20px; }
#prog, #track { fill: none; stroke: lightblue; stroke-width: 16; stroke-opacity: .5; stroke-linecap: round; stroke-linejoin: round; transition: .15s; cursor: pointer; }
#prog { stroke-opacity: 1; }
#player { transform-box: fill-box; transform-origin: center; cursor: pointer; fill: transparent; animation: rotate 8s linear infinite var(--state); }
#btnFs { left: 20px; bottom: 20px; color: silver; border-color: currentColor!important; }
</style>
<div id="pa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1371760675" autoplay loop></audio>
<video class="qk-vid" src="https://bpic.588ku.com/video_listen/588ku_video/24/12/30/16/16/24/video677256d89bac1.mp4" autoplay loop muted></video>
<svg id="progress" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<g id="player" class="sepia"><title>ALT+X</title></g>
<g id="pg"><title>调节进度</title></g>
</svg>
</div>
<script type="module">
import { FS } from 'https://638183.freep.cn/638183/web/js/pathprog.js';
import Dr from 'https://638183.freep.cn/638183/web/mod/svgdr.mod.js';
var dr = Dr.dr(progress);
var ranColor = () => `hsla(${Math.random() * 360}, 100%, 50%, .9)`;
var ar1 = dr.circlePoints(20, 200, 180), ar2 = dr.circlePoints(3, 200, 120, 15);
ar1.forEach(b => dr.circle(b, b, 20, ranColor()).addTo('player'));
dr.circle(200,200,200).addTo('player');
dr.polygon(ar2.join(',')).id('track').addTo('pg');
dr.polygon(ar2.join(',')).id('prog').addTo('pg');
FS(pa, player);
</script> <div class="codebox">
<style>
@import 'https://638183.freep.cn/638183/web/css/tz01.css';
#pa { --offsetX: 64px; --bg: #ccc url('https://638183.freep.cn/638183/t24/w6/tcwh.webp') no-repeat center/cover; }
#progress { position: absolute; width: 15vw; height: 15vw; right: 20px; bottom: 20px; }
#prog, #track { fill: none; stroke: lightblue; stroke-width: 16; stroke-opacity: .5; stroke-linecap: round; stroke-linejoin: round; transition: .15s; cursor: pointer; }
#prog { stroke-opacity: 1; }
#player { transform-box: fill-box; transform-origin: center; cursor: pointer; fill: transparent; animation: rotate 8s linear infinite var(--state); }
#btnFs { left: 20px; bottom: 20px; color: silver; border-color: currentColor!important; }
</style>
<div id="pa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1371760675" autoplay loop></audio>
<video class="qk-vid" src="https://bpic.588ku.com/video_listen/588ku_video/24/12/30/16/16/24/video677256d89bac1.mp4" autoplay loop muted></video>
<svg id="progress" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<g id="player" class="sepia"><title>ALT+X</title></g>
<g id="pg"><title>调节进度</title></g>
</svg>
</div>
<script type="module">
import { FS } from 'https://638183.freep.cn/638183/web/js/pathprog.js';
import Dr from 'https://638183.freep.cn/638183/web/mod/svgdr.mod.js';
var dr = Dr.dr(progress);
var ranColor = () => `hsla(${Math.random() * 360}, 100%, 50%, .9)`;
var ar1 = dr.circlePoints(20, 200, 180), ar2 = dr.circlePoints(3, 200, 120, 15);
ar1.forEach(b => dr.circle(b, b, 20, ranColor()).addTo('player'));
dr.circle(200,200,200).addTo('player');
dr.polygon(ar2.join(',')).id('track').addTo('pg');
dr.polygon(ar2.join(',')).id('prog').addTo('pg');
FS(pa, player);
</script>
</div>
<script type="module">
import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js';
linenumber();
</script> 本帖最后由 马黑黑 于 2025-9-16 13:04 编辑
SVG小播构图
(一)按钮部分 <g id="player">。。。</g> 分组
此分组下有现成的 <title> 标签,提示语用;有一个大圆和若干个小圆,使用 svgdr 绘制,其中大圆透明填充,作为接收点击操作的主要媒介,小圆绕城一圈,填充色使用随机 hsla 色彩,主要是装饰角色。
(二)进度部分 <g id="pg">。。。</g> 分组
此分组也内置了 <title> 标签,然后使用 svgdr 绘制两个三角形用做进度指示器+控制器。
关于 circlePoints 指令
昨天谈到该指令有三个(必选)参数:顶点数、范围半径、顶点外切圆半径,其实它还有一个(可选)参数,角偏移量(offsetAngle),缺省值是0,如果传递了非0数值,指令函数会减去该偏移角度值以确定第一个顶点的位置。帖子代码中的第 26 行第 2 个变量 ar2,使用了 15 做偏移角度稍微调整一下三角形的朝向。
该角度偏移量在实际应用中会非常有用,用不上的时候可以不理睬它。这是函数可选参数的便利体现。
关于 hsla 颜色空间
hsl 颜色体系使用 ① 色相(H), ② 饱和度(S), ③ 亮度(L)来表达颜色,色相取值 0~360,饱和度取值 0%~100%,正常颜色选取 100%,亮度取值 0~100%,正常颜色取值 50%,外加 Alpha 通道 A 设置透明度,CSS 函数写成 hsla(h, s, l, a) ,不需要设置透明度的写成 hsl(h, s, l)。该颜色体系和十六进制(#rrggbb)、 rgb(r,g,b) 等体系一样被广泛应用于Web中。
第 25 行代码是一个函数,生成随机 hsla 颜色,函数仅改变色相 hue,饱和度、亮度、透明度固定不变。函数写成传统JS函数是这样:
function ranColor() {
return `hsla(${Math.random() * 360}, 100%, 50%, .9)`;
} ar2的说得很清楚,ar1的不是很懂,这个是不连而是画圆吧 ar1.forEach(b => dr.circle(b, b, 20, ranColor()).addTo('player')); 其中b, b就是二维数组对应的圆心位置吧。{:4_204:} 昨天讲解 circlePoints 指令,今天就有实例呢,而且还增加了一个参数,这真好{:4_199:} 小播又变了,黑黑老师辛苦了。{:4_187:} 很漂亮,有part2还有part1 吧,先去看看效果 漂亮!谢谢马老师精彩讲授与示范{:4_191:} 杨帆 发表于 2025-9-16 16:48
漂亮!谢谢马老师精彩讲授与示范
{:4_190:} 小辣椒 发表于 2025-9-16 16:02
很漂亮,有part2还有part1 吧,先去看看效果
我倒着听 梦江南 发表于 2025-9-16 15:15
小播又变了,黑黑老师辛苦了。
{:4_190:} 红影 发表于 2025-9-16 13:39
昨天讲解 circlePoints 指令,今天就有实例呢,而且还增加了一个参数,这真好
那个可选参数非常有用 红影 发表于 2025-9-16 13:38
ar2的说得很清楚,ar1的不是很懂,这个是不连而是画圆吧 ar1.forEach(b => dr.circle(b, b, 20, ranC ...
ar1 和 ar2 是两个变量,它们通过 circlePoints() 指令获取到二维数组,每一个数组元素都有一对数据,用于表示一个点的坐标值,结构是这样,,例如:
['400','200']
其中,x 指点坐标的 x 值,y 指点坐标的 y 值。在 ar1 数组中,每一个子数组恰好对应圆心 cx、cy,我们知道,画圆需要圆心 cx和 cy 属性值,还需要半径 r ,填充、描边可以交给CSS设置,也可以再绘制的时候使用对应的 fill、stroke 操作。 ar1 = dr.circlePoints(20, 200, 180), ar2 = dr.circlePoints(3, 200, 120, 15);
根据昨天教程里新指令的参数对照,
ar1是绘了20个顶点,圆心位置200,内径180。
ar2绘制了3个顶点,圆心位置不变,内径只有120,这次还给了个角度15度,这样三角形就可以位置转动了。
ar1.forEach(b => dr.circle(b, b, 20, ranColor()).addTo('player'));
把ar1加入到小播中,就是那20个顶点的事儿,
dr.circle看出来是在画圆;改变20的大小圆的大小也会变化,那么这里的20是半径; ranColor()是圆的颜色,随机色的。。。
前面的b, b是什么东东,按道理是圆心,但这么多圆怎么定的。。{:4_173:} dr.circle(200,200,200).addTo('player');这个圆画得意外。。。
无色无味透明看不到。。它有啥作用啊。 dr.polygon(ar2.join(',')).id('track').addTo('pg');
ar2画成多边形,这个是里头的三角形,它只有三个顶点的多边形。。
可以设四个五个顶点。。也可以画成椭圆啥的。。。
这两个跟之前差不多。。。 歌名描绘的场面宏大,也没听过,最近的歌都有点偏冷门,
不过还好不用自己听歌词。。{:4_173:} 花飞飞 发表于 2025-9-16 19:51
歌名描绘的场面宏大,也没听过,最近的歌都有点偏冷门,
不过还好不用自己听歌词。。
这是新歌 花飞飞 发表于 2025-9-16 19:50
dr.polygon(ar2.join(',')).id('track').addTo('pg');
ar2画成多边形,这个是里头的三角形,它只有三个顶 ...
很灵活的