Truck
<style>#pa { margin: 30px 0 30px calc(50% - 593px); width: 1024px; height: 640px; background: url('https://638183.freep.cn/638183/t24/webp2/truck.webp') no-repeat center/cover; box-shadow: 2px 2px 6px rgba(0,0,0,.6); z-index: 1; position: relative; }
.myball { offset-path: path('M 765 75 Q 950 400,590 526 T 0 0'); offset-distance: 0%; animation: move 10s var(--delay) linear infinite var(--state); }
#player { cursor: pointer; transform-box: fill-box; transform-origin: center; animation:rot 10s linear infinite var(--state) }
@keyframes move { to { offset-distance: 100%; } }
@keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="pa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=33682225" autoplay loop></audio>
<svg id="msvg" width="100%" height="100%"></svg>
</div>
<script>
var sc = document.createElement('script');
sc.src = 'https://638183.freep.cn/638183/web/js2024/svgdr_trial.js';
document.body.appendChild(sc);
sc.onload = () => {
var dr = _dr(msvg);
dr.defs('defs'); //创建defs标签
//小球
dr.g('g1').addTo('defs');
dr.circle(0,0,6,'#fff').addTo('g1');
for(i = 0; i < 20; i ++) {
let delay = -0.5 * i + 's';
dr.use('#g1').set('class', 'myball').style(`--delay: ${delay}`);
}
//渐变
var stop = `
<stop offset="0%" stop-color="darkred"/>
<stop offset="50%" stop-color="green"/>
<stop offset="100" stop-color="red"/>
`;
var attr = {id: 'lgd', x1: 1, x2: 0, y1: 1, y2: 1};
dr.gradient('linearGradient', attr, stop);
//小播 : path 添加到 player
dr.g('player').addTo('defs');
for(var i = 0, tt = 10; i < tt; i++) {
dr.path('M80 80 Q-120 90, 50 10', 'transparent', 'url(#lgd)', 8, 'round').transform(`rotate(${360/tt*i} 80 80)`).addTo('player');
}
dr.use('#player', 450, 300); //实例化小播
aud.onplaying = aud.onpause = () => mState();
player.onclick = () => aud.paused ? aud.play() : aud.pause();
mState = () => {
pa.style.setProperty('--state', aud.paused ? 'paused' : 'running');
};
};
</script>
帖子代码:
<style>
#pa { margin: 30px 0 30px calc(50% - 593px); width: 1024px; height: 640px; background: url('https://638183.freep.cn/638183/t24/webp2/truck.webp') no-repeat center/cover; box-shadow: 2px 2px 6px rgba(0,0,0,.6); z-index: 1; position: relative; }
.myball { offset-path: path('M 765 75 Q 950 400,590 526 T 0 0'); offset-distance: 0%; animation: move 10s var(--delay) linear infinite var(--state); }
#player { cursor: pointer; transform-box: fill-box; transform-origin: center; animation:rot 10s linear infinite var(--state) }
@keyframes move { to { offset-distance: 100%; } }
@keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="pa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=33682225" autoplay loop></audio>
<svg id="msvg" width="100%" height="100%"></svg>
</div>
<script>
var sc = document.createElement('script');
sc.src = 'https://638183.freep.cn/638183/web/js2024/svgdr_trial.js';
document.body.appendChild(sc);
sc.onload = () => {
var dr = _dr(msvg);
dr.defs('defs'); //创建defs标签
//小球
dr.g('g1').addTo('defs');
dr.circle(0,0,6,'#fff').addTo('g1');
for(i = 0; i < 20; i ++) {
let delay = -0.5 * i + 's';
dr.use('#g1').set('class', 'myball').style(`--delay: ${delay}`);
}
//渐变
var stop = `
<stop offset="0%" stop-color="darkred"/>
<stop offset="50%" stop-color="green"/>
<stop offset="100" stop-color="red"/>
`;
var attr = {id: 'lgd', x1: 1, x2: 0, y1: 1, y2: 1};
dr.gradient('linearGradient', attr, stop);
//小播 : path 添加到 player
dr.g('player').addTo('defs');
for(var i = 0, tt = 10; i < tt; i++) {
dr.path('M80 80 Q-120 90, 50 10', 'transparent', 'url(#lgd)', 8, 'round').transform(`rotate(${360/tt*i} 80 80)`).addTo('player');
}
dr.use('#player', 450, 300); //实例化小播
aud.onplaying = aud.onpause = () => mState();
player.onclick = () => aud.paused ? aud.play() : aud.pause();
mState = () => {
pa.style.setProperty('--state', aud.paused ? 'paused' : 'running');
};
};
</script> 帖子思路:
(一)帖子容器是一个div标签,加载了背景图片;
(二)帖子容器下装载音频标签和 svg 标签,其中,svg 标签内容为空,它将由 JS 完成动态效果的绘制;
(三)JS绘制动态效果:
使用还在开发中的 svgdr 插件绘制svg所有内容。先加载插件(14-17行),然后在资源的 onload 事件中封装JS要完成的工作,这样可以不必使用 Promise 机制。
绘制流程简述如下:
① 声明svg画笔(20行),参数 msvg 必须和HTML代码中的 svg id 相一致;
② 创建defs标签用来装载分组、渐变等代码,参数是defs的 id,后续将元素加载到defs标签的依据(21行);
③ 绘制小球(23-28行):小球放入分组 g1,g1 放进 defs;
④ 创建一个渐变效果(小播用),渐变也加入到 defs标签中(30-36行);
⑤ 绘制小播(37-42):小播使用路径绘制,它的 fill 属性使用了前面创建的渐变效果。用for语句绘制多条路经,放入id="player" 的g分组,g分组放入defs标签中,然后通过 use 实例化该分组;
⑥ 其他,如监听音频状况、音频联动动画、小播点击事件等 帖子的实现可以不使用 svgdr,可以考虑将相同的效果写成或通过svgdr生成 XML代码,然后将这些代码放在svg标签内,这样JS部分就会非常简洁 很欣赏 跟着黑黑老师学代码。辛苦了!{:4_190:} 令人赞叹的设计,先说背景图片色彩和空间感都令人震憾。。天空之上的感觉,美。。搭上这样的音乐,更有神秘之感。。 小播设计颜值很高,红绿这么难驾驭的色彩,硬是让白老师一次一次用出这么高级的感觉。不愧是天选之色。。
小播乍一看以为是径向渐变,仔细看完代码才发现是线性渐变。。。应该每个线条单独来看,10片这样的线条组合起来,成花儿一样的效果,这个构思绝了。。
单个线条路径设计也是神来之笔。。单看很不起眼也很普通,组合在一起就是惊艳。。 小球路径设计很难的吧,要从月亮边上小白点出发,再到左上角结束,又是一个根据背景图片微调位置的贴子,要细心和耐心,花大量的时间。。(或者老师不用,眼睛就是尺{:4_199:})
小球数量小于20个,半径为6,每个小球出现时间比上一个延迟0.5,形成这样运动轨迹。
小球做为对象添加到到g1分组里面的。。 马黑黑 发表于 2024-10-24 12:13
帖子思路:
(一)帖子容器是一个div标签,加载了背景图片;
这个解释超级详细,层次分明。。
神奇的是 <svg id="msvg" width="100%" height="100%"></svg>这个空标签横空出世,划一块地儿给JS描绘。。{:4_170:}
这些设计都令人拍案叫绝。。
原来可以这样纸处理。。 马黑黑 发表于 2024-10-24 12:15
帖子的实现可以不使用 svgdr,可以考虑将相同的效果写成或通过svgdr生成 XML代码,然后将这些代码放在svg标 ...
相同的效果通过svgdr生成 XML代码,这得有深厚的功底才能做到的节奏{:4_173:} 小球的路径是css路设置的二次贝塞尔曲线,JS里给它形状和个数。
小播是在JS里画的二次赛贝尔曲线,而且设置了渐变,这个曲线设置得好,10条正好能连上,看起来像内部呈圆环了。
黑黑把这些效果用得挥洒自如{:4_199:} dr.path('M80 80 Q-120 90, 50 10', 'transparent', 'url(#lgd)', 8, 'round').transform(`rotate(${360/tt*i} 80 80)`).addTo('player');
是因为M80 80的缘故么,咋感觉应该是反向移动,去试了,不行的{:4_173:} var attr = {id: 'lgd', x1: 1, x2: 0, y1: 1, y2: 1};这个是从右到左吧,不是45度了。如果x1: 0, x2: 1,深红和红就换了。
<stop offset="0%" stop-color="darkred"/>
<stop offset="50%" stop-color="green"/>
<stop offset="100" stop-color="red"/>这个100这里不用加 %?0那里也不用的吧。 很奇妙的场景和音乐,很奇妙的svg效果。{:4_199:} 小文 发表于 2024-10-24 12:30
很欣赏
晚上好 梦江南 发表于 2024-10-24 14:03
跟着黑黑老师学代码。辛苦了!
{:4_190:} 醉美水芙蓉 发表于 2024-10-24 16:49
欣赏老师带来的精彩!
{:4_190:} 花飞飞 发表于 2024-10-24 17:47
令人赞叹的设计,先说背景图片色彩和空间感都令人震憾。。天空之上的感觉,美。。搭上这样的音乐,更有神秘 ...
{:4_205:}