马黑黑 发表于 2025-9-1 20:36

白色戏法(测试自适应svg路径动画)

本帖最后由 马黑黑 于 2025-9-1 20:59 编辑 <br /><br /><div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/css/tz01.css';
        #pa { --offsetX: 0px; --bg: url('https://638183.freep.cn/638183/t24/w5/ground.webp') no-repeat center/cover; --ma-size: 20%; }
        #ma { background: url('https://638183.freep.cn/638183/web/svg/sunfl-2.svg') no-repeat center/cover; }
        #btnFs { right: 30px; bottom: 30px; color: lightblue; border-color: currentColor!important; }
        #svg use { opacity: 1; animation: flash linear 1s var(--delay) infinite alternate var(--state); }
        @keyframes flash { to { opacity: 0.5; } }
&lt;/style&gt;

&lt;div id="pa"&gt;
        &lt;audio id="aud" src="https://music.163.com/song/media/outer/url?id=33469659" autoplay loop&gt;&lt;/audio&gt;
        &lt;video class="pd-vid" src="https://img.tukuppt.com/video_show/2629112/00/02/03/5b4f3c0b41744.mp4" autoplay loop muted&gt;&lt;/video&gt;
        &lt;div id="ma" class="brightness"&gt;&lt;/div&gt;
        &lt;svg id="svg" width="100%" height="100%" viewBox="0 00 1600 900"&gt;
                &lt;defs&gt;
                        &lt;g id="svgShape" fill="white"&gt;
                                &lt;circle cx="0" cy="0" r="10" stroke-width="0" /&gt;
                                &lt;path d="M0 0 H0 20" stroke-width="3" /&gt;
                        &lt;/g&gt;
                        &lt;path id="motionPath" d="M0 900 Q1500 640,1600 0" /&gt;
                &lt;/defs&gt;
        &lt;/svg&gt;
&lt;/div&gt;

&lt;script type="module"&gt;
        import { FS } from 'https://638183.freep.cn/638183/web/js/fullscreen.js';
        FS(pa,ma);

        const createSvgElement = (element, attributes) =&gt; {
                const elm = document.createElementNS('http://www.w3.org/2000/svg', element);
                attributes.forEach(item =&gt; elm.setAttribute(item,item));
                return elm;
        };

        const total = 20, fragment = document.createDocumentFragment();
        Array.from({length: total}).forEach((_,key) =&gt; {
                const size = (Math.random() + 0.8).toFixed(2);
                const color = '#' + Math.random().toString(16).substring(2,8);

                const use = createSvgElement('use', [
                        ['href', '#svgShape'],
                        ['x', 0],
                        ['y', Math.random() * 200 - 150],
                        ['style', `--delay: ${Math.random() * -4}s; transform: scale(${size}); fill: ${color}; stroke: ${color};`]
                ]);

                const motion = createSvgElement('animateMotion', [
                        ['dur', Math.random() * 10 + 10],
                        ['begin', Math.random() - 20],
                        ['repeatCount', 'indefinite'],
                        ['rotate', 'auto']
                ]);

                const mpath = createSvgElement('mpath',[
                        ['href', '#motionPath']
                ]);

                motion.appendChild(mpath);
                use.appendChild(motion);
                fragment.appendChild(use);
        });
        svg.appendChild(fragment);

        aud.onplaying = aud.onpause = () =&gt; aud.paused ? svg.pauseAnimations() : svg.unpauseAnimations();
&lt;/script&gt;
</div>

<script type="module">
import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js';
linenumber();
</script>

花飞飞 发表于 2025-9-1 20:41

这是满天飞舞的棒棒糖么。{:4_173:}好久没来,四处逛逛先。。一会来看代码

马黑黑 发表于 2025-9-1 20:52

svg路径动画即为 animateMotion 动画。此动画需要一个路径,其实就是后来CSS3接纳的 offset-path + offset-diatance 动画。

在 CSS3 的 offset-path 属性中,如果所使用的路径函数不支持百分比,那意味着路径是绝对路径,运动路径不能适配帖子容器的尺寸(包含动态变化的尺寸),这时候就需要 svg 的 animateMotion 来满足自适应帖子容器尺寸的需要。

本帖的设计:

(一)需要创建一个SVG标签,该标签作为帖子容器的子元素存在,宽高均设为帖子容器的 100%,且,非常重要的,应设置一个 viewBox 属性,该属性的值取决于帖子容器的宽高比例,例如上例的16比9的规格;

(二)SVG标签的子元素全部置于 defs 标签内,共两个内容:其一,用 <g> 分组标签创建运动粒子的形状,可以简单可以复杂;其二,创建一个运动路径标签 <path>,基于svg标签的 viewBox 所规定的宽高范围进行设计。注意 g 和 path 标签都有 id,便于 JS 的处理;

(三)如果希望自定义粒子的颜色,可以给 <g> 标签或 <g> 标签内的元素加上 fill 和 stroke 颜色属性,否则,JS会给它们一个随机颜色(事实上JS都给它们随机颜色,但事先设置了 fill 和 stroke 的话JS通过 style 属性为 use 引用所设置的颜色无效);

(四)JS代码中,基于 svg 的处理主要是按照 animateMotion 动画规范设计动画,通过实例化(use)标签加以实现。

马黑黑 发表于 2025-9-1 20:54

本测试还给 use 标签设计了一个 CSS 动画,它不再 JS 的主要处理范畴,但JS给它提供一个 --delay 变量值

花飞飞 发表于 2025-9-1 21:17

粒子是个圆和小线段一起组成而成的。。。
随机出现,从左下角到右上角,
大小随机,位置随机。。
还设置了闪呀闪的效果,
这么多效果集合在一起,感觉这算力大大超出了凡人认知范围。。{:4_173:}

马黑黑 发表于 2025-9-1 21:22

花飞飞 发表于 2025-9-1 21:17
粒子是个圆和小线段一起组成而成的。。。
随机出现,从左下角到右上角,
大小随机,位置随机。。


动画分层面:闪烁是CSS关键帧动画(容易理解),沿路径运动是SVG动画(较难理解)

花飞飞 发表于 2025-9-1 21:22

画面又简洁又清爽,用的是今天实例的背景,
实例是白色小球旋转,这个是粒子周边飞舞
那个实例中间的小播是代码写的图案,这个是SVG图片。。
感觉大不相同啊。。我再去瞅瞅。

马黑黑 发表于 2025-9-1 21:22

花飞飞 发表于 2025-9-1 20:41
这是满天飞舞的棒棒糖么。好久没来,四处逛逛先。。一会来看代码

这是坦克{:4_196:}

马黑黑 发表于 2025-9-1 21:24

花飞飞 发表于 2025-9-1 21:22
画面又简洁又清爽,用的是今天实例的背景,
实例是白色小球旋转,这个是粒子周边飞舞
那个实例中间的小播 ...

两者实现手段不一样

花飞飞 发表于 2025-9-1 21:27

马黑黑 发表于 2025-9-1 21:22
动画分层面:闪烁是CSS关键帧动画(容易理解),沿路径运动是SVG动画(较难理解)

d="M0 900 Q1500 640,1600 0"这个路径起点0 900,左下角,终点是1600 0..中间那个是控制点。。
能让这么多粒子随着这个路径随意出现,这才是计算的厉害之处。


const size = (Math.random() + 0.8).toFixed(2); 这句保证了大小随机。。从取0和1的话,结果就是0.8-1.8的大小

const color = '#' + Math.random().toString(16).substring(2,8);这句颜色随机也比较容易看出来。。

马黑黑 发表于 2025-9-1 21:29

花飞飞 发表于 2025-9-1 21:27
d="M0 900 Q1500 640,1600 0"这个路径起点0 900,左下角,终点是1600 0..中间那个是控制点。。
能让这么 ...

特别需要注意的是svg的 viewBox 设计,路径 d 属性依据它

花飞飞 发表于 2025-9-1 21:30

最难看出来的是位置怎么 设的可以这么满天飞舞。。
20个粒子不是整齐划一的哦,而是出现有延迟,过程有闪烁,
位置也有错落。。
这指挥的粒子简直是太听话了。。没有一个乱跑的。{:4_170:}
我再看看哪句管的

红影 发表于 2025-9-1 21:32

这些粒子是小扇子么,这形状设置得有趣。{:4_173:}

马黑黑 发表于 2025-9-1 21:36

花飞飞 发表于 2025-9-1 21:30
最难看出来的是位置怎么 设的可以这么满天飞舞。。
20个粒子不是整齐划一的哦,而是出现有延迟,过程有闪 ...

综合运作的效果:

(一)animateMotion 的相关属性有 dur(动画时长)、begin(何时开始),它们取值都是随机的,时长关快慢,开始时间管先后(用的是负值,提前运行);

(二)实例化 use 标签为粒子的最终形态,除了大小,还有位置,关位置的是 x、y,x 都设为0,y 则错开一定范围,这样它们在主线上的运动在y方向则是错开那么一点点距离的。

马黑黑 发表于 2025-9-1 21:36

红影 发表于 2025-9-1 21:32
这些粒子是小扇子么,这形状设置得有趣。

这是小坦克,无人坦克

花飞飞 发表于 2025-9-1 21:37

['x', 0],
['y', Math.random() * 200 - 150],这个Y轴的数据随机啊。。就是可以左右乱偏的,取0和1的话,偏移在-150和50之间,那就可以理解为啥可以错落了。。
                       

['style', `--delay: ${Math.random() * -4}s; transform: scale(${size}); fill: ${color}; stroke: ${color};`]
这句好复杂。。延迟4秒,大小取上面的随机值 ,填充和边框也取随机色。。。(不过也有说明这随机色失效了)
五体投地,佩服。。
这么复杂的东东怎么想出来的。。

红影 发表于 2025-9-1 21:38

马黑黑 发表于 2025-9-1 20:54
本测试还给 use 标签设计了一个 CSS 动画,它不再 JS 的主要处理范畴,但JS给它提供一个 --delay 变量值

这个动画是明暗变化的动画吧。
<svg id="svg" width="100%" height="100%" viewBox="0 00 1600 900">这个整个在背景范围里啊。
这个js设计感觉有点复杂,很多看着都觉得似是而非,前面学的又都忘记了{:4_173:}

马黑黑 发表于 2025-9-1 21:39

花飞飞 发表于 2025-9-1 21:37
['x', 0],
['y', Math.random() * 200 - 150],这个Y轴的数据随机啊。。就是可以左右乱偏的,取0和1的话, ...

懂的用材料和工具,产品就可以生产出来

花飞飞 发表于 2025-9-1 21:39

马黑黑 发表于 2025-9-1 21:36
综合运作的效果:

(一)animateMotion 的相关属性有 dur(动画时长)、begin(何时开始),它们取值 ...

给跪了,这神仙算法,感觉我能看出一丢丢,CPU就快烧坏了。。。{:4_170:}

花飞飞 发表于 2025-9-1 21:41

马黑黑 发表于 2025-9-1 21:22
这是坦克

{:4_170:}小猪猪你设计这么可爱的小坦克,没满月就出来营业了,仔细看还真是的。。。吃一个。。
页: [1] 2 3 4 5 6 7
查看完整版本: 白色戏法(测试自适应svg路径动画)