马黑黑 发表于 2025-11-12 13:14

tzMaker中级教程三

<style>
        .artBox { font-size: 18px; margin: 20px auto; max-width: 1200px; }
        .artBox > p { margin: 10px 0; line-height: 30px; }
        .artBox mark { padding: 4px 6px; background: lightblue; }
</style>

<div class="artBox">
        <p>本讲主要探讨如何通过tzMaker创建帖子的粒子动画。tz模块没有封装粒子动画相关指令,不过如你在前面相关章节所看到的,tz具备绘制粒子的能力,换言之,它可以创建静态的粒子,包括绕圆弧布局的粒子、随机分散布局的粒子、原地旋转构图的粒子等等。以随机分散粒子为例,我们可以使用 lzRan() 指令实现,给粒子指定一个class,在CSS对应class选择器中设置粒子的相关属性,特别地,不能缺少关键帧动画,这样,tz所创建的粒子就会鲜活起来。来看看闪烁的星空案例:</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
        .pa { background: #000; }
        .lz {
                width: 4px;
                height: 4px;
                background: lightblue;
                animation: flash 1s infinite alternate;
        }
        @keyframes flash {
                from { opacity: 1; transform: rotate(15deg); }
                to { opacity: 0; transform: rotate(45deg); }
        }
&lt;/style&gt;

&lt;div class="pa"&gt;&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v1';
        const tz = TZ.TZ('pa');
       
        tz.lzRan(200, 'pa', {
                className: 'lz', <txt-green>// 粒子使用 .lz 选择器的样式</txt-green>
                delay: -2 <txt-green>// 提前运行动画时间区间 -2~0 秒</txt-green>
        });
&lt;/script&gt;
        </div>
        <p>两百个 id="lz" 的 div 标签做成的粒子,随机分布在帖子容器里面,它们通过CSS 选择器 .lz 制定了样式和动画,指令配置代码中还特意加入约定属性 delay,让粒子随机在 -2~0 秒之间提前运行动画,避免动画同质化,并借此营造更为自然的动画效果。除了 delay 动画运行延时属性, tz还有一个约定动画周期时长属性 duration,> 0 的整数,对应CSS的 animation-duration 属性,必要的时候可以让它参与到配置中来。</p>
        <p>粒子不一定要布满帖子容器,一切可以定制,例如星斗粒子,完全可以给它设置一个容器,安排好粒子容器的尺寸和在帖子容器中的位置,然后在 lzRan() 指令的第二个参数 'pa' 改为其 id 标识,就可以把粒子控制在特定的范围里。还可以给粒子制定动画路线,这样不论粒子是随机分布的还是预设了固定位置的,运行时粒子都会出现在动画的路线上。下面的例子,粒子沿着椭圆圆环路线运行,运行动画前它们都是随机摆放在帖子容器中:</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
        .pa { background: linear-gradient(black, tan); }
        lz {
                width: 30px;
                height: 20px;
                offset-path: ellipse(40% 30%);
                animation: move 18s linear infinite;
        }
        @keyframes move {
                from { offset-distance: 0%; }
                to { offset-distance: 100%; }
        }
&lt;/style&gt;

&lt;div class="pa"&gt;&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v1';
        const tz = TZ.TZ('pa');
       
        tz.lzRan(30, 'pa', {
                className: 'lz',
                duration: 18, <txt-green>// 动画周期时长区间 0~18 秒</txt-green>
                delay: -18
        });
&lt;/script&gt;
        </div>
        <p>上例的花括号 {} 配置中 className 属性指明粒子使用CSS .lz 选择器定义的样式。粒子在 .lz 样式和JS的 {} 配置都没有设置背景色,模块将随机赋予它们十六进制的背景颜色值;如果需要,可以在CSS代码或JS {} 配置中定义粒子的背景,图片、渐变(含随机渐变)、颜色值都可以。CSS动画设置了一个相抵路径(offset-path)的椭圆形路线,并在关键帧动画选择器 @keyframes 中设置从 0% 到 100% 的运行机制,配合JS {} 配置的 duration 和 delay 两个动画相关的属性,粒子的运行就有快有慢、有前有后,大抵会均匀分布在预设路线中。</p>
        <p>以上两个示例,使用的指令都是 lzRan(),它生成的粒子可以自由分布,也可以设定 top 和(或)left 以定位或半定位,然后设计好CSS关键帧动画,粒子就可以动起来。lzRan() 指令最适合创建“全局”动画,可以满帖子范围内跑,如果愿意还可以让它们跑出帖子之外。而另外两个粒子相关指令,lzRing() 和 lzRot(),它们更喜欢呆在小范围内且相对而言其位置是固定的,不过它们也可以在“原地”运行自己的动画,下例使用 lzRing() 指令做绕圈圈布局的粒子,它们整体随父元素做旋转动画(公转),各自也另外运行相同(可以不相同)的旋转动画(自转):</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
        .pa { background: white; }
        .ma { border: 4px double purple; }
        .lz {
                width: 30px;
                height: 30px;
                animation: rotate 2s linear infinite var(--state);
        }
&lt;/style&gt;

&lt;div class="pa"&gt;&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v1.0';
        const tz = TZ.TZ('pa');
       
       <txt-green>// 加入音频以便动画可以进行交互</txt-green>
        tz.add('audio', '', '', { src: 'https://music.163.com/song/media/outer/url?id=551842545' });
        tz.add('div', 'lzpa', 'ma').playmp3();
        tz.lzRing(8, 'lzpa', {
                className: 'lz',
                duration: 2,
                delay: -2
        });
&lt;/script&gt;
        </div>
        <p>lzRot() 生成的“粒子”本质上应是大个头,多个单体旋转后构成复合图案,彼此间可能有交叉或接触,复合组图后具备更强的整体性,单体个性化动画可操作空间很小。但事在人为,设计得好,依然可以有限地给单体设置动画,下例,使用粒子的伪元素实现闪烁关键帧动画:</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
        .pa { background: beige; }
        .ma { display: grid; place-items: center; }
        .lz {
                position: absolute;
                width: 2px;
                height: 100%;
                display: grid; <txt-green>/* grid布局便于安排伪元素位置 */</txt-green>
                place-items: center;
        }
        .lz::before, .lz::after {
                position: absolute;
                content: '';
                top: -40px;
                width: 40px;
                height: 40px;
                background: linear-gradient(black, var(--cc)); <txt-green>/* 渐变背景 */</txt-green>
                border-radius: 50%;
                animation: flash .2s infinite alternate var(--state);
                animation-delay: inherit; /* 继承父元素动画延时属性 */</txt-green>
        }
        .lz::after { top: 100%; }
        @keyframes flash { to { opacity: .5; } }
&lt;/style&gt;

&lt;div class="pa"&gt;&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v1.0';
        const tz = TZ.TZ('pa');

        tz.add('audio', '', '', { src: 'https://music.163.com/song/media/outer/url?id=37778306' });
        tz.add('div', 'lzpa', 'ma').playmp3();
        tz.lzRot(6, 'lzpa', {
                className: 'lz',
                cc: true, <txt-green>// 使用 --cc 随机颜色</text-green>
                angle: 180, <txt-green>// 粒子贯穿容器,角度不应是360</text-green>
                delay: -1<txt-green>// 粒子主元素没有动画,但伪元素可以继承 animation-delay 属性值</text-green>
        });
&lt;/script&gt;
        </div>
        <p>最后这个示例很有意思:tz模块没有操作伪元素的能力,{}配置里的 delay 属性基于粒子而非粒子的伪元素,伪元素在CSS里设置了继承父元素的 animation-delay 属性,故而 delay 属性的配置能作用于伪元素,伪元素运行动画的起步时间差异因此可以实现,避免了同步运行;粒子伪元素所用到的 --cc 变量也是通过继承得来:{}配置里的 cc 属性在模块中生成的 --cc 变量作用于粒子自身,然后粒子再将变量值传递给伪元素。</p>
        <p>本讲主要讨论使用 lzRan()、lzRing() 和 lzRot() 三个指令实现粒子动画,内容难度中上,需要花点心思体会。下一部分的粒子动画探讨可能更为抽象难懂,敬请期待。</p>
</div>

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

梦江南 发表于 2025-11-12 13:22

这粒子第一像星星一样,很赞。黑黑老师辛苦了!

霜染枫丹 发表于 2025-11-12 18:23

感谢分享,收藏好贴,好好学习。恭祝安好!

红影 发表于 2025-11-12 18:49

tzMaker中的粒子的三个指令,每一个都那么出彩,各自可以弄出奇妙的效果,而且代码极简,太赞了{:4_199:}

红影 发表于 2025-11-12 19:03

最后那个演示的效果最漂亮,渐变做的闪烁弄得小球像是在发光了{:4_187:}

马黑黑 发表于 2025-11-12 19:22

红影 发表于 2025-11-12 19:03
最后那个演示的效果最漂亮,渐变做的闪烁弄得小球像是在发光了

本质上它们也是发光。

光的原理大概是明暗的差异,我们可以从明度、透明度等角度入手加以实现

马黑黑 发表于 2025-11-12 19:23

红影 发表于 2025-11-12 18:49
tzMaker中的粒子的三个指令,每一个都那么出彩,各自可以弄出奇妙的效果,而且代码极简,太赞了

三个指令共性不少,但各有专业,擅长点不一样

马黑黑 发表于 2025-11-12 19:23

霜染枫丹 发表于 2025-11-12 18:23
感谢分享,收藏好贴,好好学习。恭祝安好!

{:4_191:}

马黑黑 发表于 2025-11-12 19:24

梦江南 发表于 2025-11-12 13:22
这粒子第一像星星一样,很赞。黑黑老师辛苦了!

{:4_190:}

杨帆 发表于 2025-11-12 20:48

谢谢马老师集中讲解如何使用 lzRan()、lzRing() 和 lzRot() 三个指令实现粒子动画{:4_191:}

马黑黑 发表于 2025-11-12 21:35

杨帆 发表于 2025-11-12 20:48
谢谢马老师集中讲解如何使用 lzRan()、lzRing() 和 lzRot() 三个指令实现粒子动画

{:4_190:}

杨帆 发表于 2025-11-12 22:03

马老师讲授下一部分粒子动画一定会更精彩,期待中……

在tzMaker举例时,可否也能同步有svgdr的示例?{:4_180:}

马黑黑 发表于 2025-11-12 22:10

杨帆 发表于 2025-11-12 22:03
马老师讲授下一部分粒子动画一定会更精彩,期待中……

在tzMaker举例时,可否也能同步有svgdr的示例?{: ...

svgdr主要是作图,过去有过很多示例

杨帆 发表于 2025-11-12 22:13

马黑黑 发表于 2025-11-12 22:10
svgdr主要是作图,过去有过很多示例

好的,知道了,谢谢老师{:4_190:}

红影 发表于 2025-11-12 23:04

马黑黑 发表于 2025-11-12 19:22
本质上它们也是发光。

光的原理大概是明暗的差异,我们可以从明度、透明度等角度入手加以实现

这个和直射的光还不一样,是小球上流转的光,特别神奇{:4_187:}

马黑黑 发表于 2025-11-12 23:05

红影 发表于 2025-11-12 23:04
这个和直射的光还不一样,是小球上流转的光,特别神奇

它们不是光照效果,是自发光

红影 发表于 2025-11-12 23:06

马黑黑 发表于 2025-11-12 19:23
三个指令共性不少,但各有专业,擅长点不一样

是的,用它们可以得到不同的效果展现,当然也可以两个都用,前面我就把第一个效果和最后一个效果合一起去了,也挺好看{:4_173:}

马黑黑 发表于 2025-11-12 23:13

红影 发表于 2025-11-12 23:06
是的,用它们可以得到不同的效果展现,当然也可以两个都用,前面我就把第一个效果和最后一个效果合一起去 ...

灵活搭配,甚至异用,都可以达到神奇的效果

红影 发表于 2025-11-14 22:14

马黑黑 发表于 2025-11-12 23:05
它们不是光照效果,是自发光

嗯嗯,知道了,这样流动的光特别漂亮{:4_187:}

红影 发表于 2025-11-14 22:16

马黑黑 发表于 2025-11-12 23:13
灵活搭配,甚至异用,都可以达到神奇的效果

看到黑黑最新的实例也是有星星还有小球呢。
页: [1] 2
查看完整版本: tzMaker中级教程三