tzMaker中级教程四
本帖最后由 马黑黑 于 2025-11-14 12:57 编辑 <br /><br /><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制作自定义的粒子,涉及到的主要指令有 ringPos() 和 ranPos(),ring 代表圆环、ran表示随机,pos是 position 的缩写、意为位置。先从 ringPos() 指令开始,它返回一个数组,形式为 ,即圆弧顶点的坐标数据。看示例:</p>
<div class="codebox" data-prev="1">
<style>
@import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
<txt-green>/* 粒子样式 */</txt-green>
.lz { position: absolute; width: 40px; height: 40px; background: linear-gradient(var(--deg), green, orange); border-radius: 50%; color: #eee; display: grid; place-items: center; }
</style>
<div id="pa" class="pa"></div>
<script type="module">
import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v3';
const tz = TZ.TZ('pa');
<txt-green>// 取15个点坐标,X、Y偏移量为粒子宽高各一半</txt-green>
const ps = tz.ringPos(15, { offsetX: 20, offsetY: 20 });
<txt-green>// 遍历 ps 数组(注意 style 内的注释不能简单用 // 表示)</txt-green>
ps.forEach( (p, k) => {
tz.add('div', '', 'lz', {style: `
left: ${p}px; <txt-green>/* 左定位 */</txt-green>
top: ${p}px; <txt-green>/* 上定位 */</txt-green>
--deg: ${tz.getRanInt(0, 360)}deg; <txt-green>/* 渐变角度随机 */</txt-green>
`});
tz.son.textContent = k + 1;
});
</script>
</div>
<p>ringPos() 指令需要两个参数,第一个参数是数值参数,取多少个外切圆弧上的点,第二个参数是一组配置,约定有圆弧覆盖角度 <txt-red>a</txt-red>(默认360),取点起始角度 <txt-red>startA</txt-red>(默认0),圆心坐标 <txt-red>cx、cy</txt-red>(默认为帖子容器宽高的一半),长、短半径 <txt-red>r1、r2</txt-red>(默认为帖子容器宽高的一半再减去100),点的 <txt-red>X、Y</txt-red> 偏移量 <txt-red>offsetX</txt-red> 和 <txt-red>offsetY</txt-red>(默认都是0),键值对顺序不论,要求名称对上、键值合法。上例的配置,获取15个圆弧上的点坐标,配置参数仅 offsetX 和 offsetY 偏移量,其余配置均取默认值。可以做更多更详尽的配置以便生成预设的粒子效果,看下例:</p>
<div class="codebox" data-prev="1">
<style>
@import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
.lz { position: absolute; width: 40px; height: 40px; background: linear-gradient(var(--deg), green, orange); border-radius: 50%; color: #eee; display: grid; place-items: center; }
</style>
<div id="pa" class="pa"></div>
<script type="module">
import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v3';
const tz = TZ.TZ('pa');
const ps = tz.ringPos(15, {
a: 180, <txt-green>// 覆盖角度,改为 -180 粒子整体将是另一个朝向 </txt-green>
startA: -90, <txt-green>// 起点角度,改为 -90 粒子排序将是另一个方向 </txt-green>
offsetX: 20,
offsetY: 20
});
ps.forEach( (p, k) => {
tz.add('div', '', 'lz', {style: `
left: ${p}px;
top: ${p}px;
--deg: ${tz.getRanInt(0, 360)}deg;
`});
tz.son.textContent = k + 1;
});
</script>
</div>
<p>角度,包含覆盖角度、起始角度,均支持正、负数值。圆的角度为360度,圆周的起点是三点钟方向、走向顺时针,可以再配置中改变覆盖角度和起点角度,并通过二者的正、负数值的<txt-red>合理</txt-red>配套来改变粒子整体的朝向和粒子个体的排列顺序方向。</p>
<p>如果希望生成在正圆轨道上排列粒子,则需要配置 r1、r2 参数为相等的数值,另外,可以改变外切圆的圆心以布置粒子的整体位置,下面的配置代码生成的粒子绕成一个正圆,正圆轨道在帖子容器的(400,300)坐标处:</p>
<div class="codebox">
const ps = tz.ringPos(15, {
cx: 400,
cy: 300,
r1: 120,
r2: 120,
a: 360,
startA: -90, <txt-green>// 起点在十二点钟即0点钟方向</txt-green>
offsetX: 20,
offsetY: 20
});
</div>
<p>接着谈谈 ranPos() 指令。该指令返回指定数值内的随机数值,注意返回值并不是完整的点坐标XY值而只是其中之一。指令总共需要两个参数,都是数值参数,第一个参数必选,可以视为距离数值,指令将在这个距离范围内生成一个随机点的坐标值之一;第二个参数为偏移值,可选,默认值为0,这是基于粒子的宽高而做的考虑,为的是用指令返回值定位元素时元素不至于超越容器边界。下面的例子将通过 ranPos() 指令制定50个粒子的各自随机位置:</p>
<div class="codebox" data-prev="1">
<style>
@import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
/* 粒子样式 */
.lz { position: absolute; width: 40px; height: 40px; background: linear-gradient(var(--deg), green, orange); border-radius: 50%; color: #eee; display: grid; place-items: center; }
</style>
<div id="pa" class="pa"></div>
<script type="module">
import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js?v3';
const tz = TZ.TZ('pa');
<txt-green>// 取50个点,依据帖子容器宽高减去偏移量生成坐标值作为粒子的定位数据</txt-green>
Array.from({length: 50}).forEach( (_, key) => {
const x = tz.ranPos(pa.offsetWidth, 40); <txt-green>/* x坐标依据帖子容器宽 */</txt-green>
const y = tz.ranPos(pa.offsetHeight, 40); <txt-green>/* y坐标依据帖子容器高 */</txt-green>
tz.add('div', '', 'lz', {style: `
left: ${x}px;
top: ${y}px;
--deg: ${tz.getRanInt(0, 360)}deg;
`});
tz.son.textContent = key + 1;
});
</script>
</div>
<p>不一定同时获取两个随机数,一切看需要而定,例如,希望粒子从上往下掉落,或从右向左飞行,则可以固定 top 或 left,此时只需获取 y 或 x 的配套随机值即可。无需考虑偏移量时,偏移量参数可以缺省。</p>
<p>生成了粒子,动画层面只需要在CSS中设计,自定义的动态粒子系统即刻实现。不过动画的实现这里不再重复讨论,本讲的重点在于对两个指令 ringPos() 和 ranPos() 的介绍,使用它们生成了自定义的粒子,任务就已完成。</p>
<p>ringPos() 和 ranPos() 指令并非完全为粒子而设计,它们除了可以用来辅助生成粒子(本质是给粒子定位),还能做更多,一切仅局限于设计和实现能力。</p>
</div>
<script type="module">
import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js';
linenumber();
</script> 学习一下~由衷感谢马老师对ringPos() 和 ranPos() 指令的深入浅出的讲解{:4_180:} 因为有起始角度和覆盖角度的设定,所以ringPos() 指令生成的小球可以按想要的方式排布呢。 这两个定位点都挺重要的,决定了粒子的排布{:4_187:} 红影 发表于 2025-11-14 20:32
这两个定位点都挺重要的,决定了粒子的排布
也可以绕过tz指令,自己设计算法 红影 发表于 2025-11-14 20:27
因为有起始角度和覆盖角度的设定,所以ringPos() 指令生成的小球可以按想要的方式排布呢。
是的 杨帆 发表于 2025-11-14 17:34
学习一下~由衷感谢马老师对ringPos() 和 ranPos() 指令的深入浅出的讲解
有点抽象 马黑黑 发表于 2025-11-14 21:09
有点抽象
抽象点也好,骨感美,特别是老师的讲解还赋予了它冷峻的美呢{:4_180:} 马黑黑 发表于 2025-11-14 21:08
也可以绕过tz指令,自己设计算法
哦,知道了{:4_187:} 马黑黑 发表于 2025-11-14 21:08
是的
还可以通过长短轴的设计,让小球的弯曲量得到控制{:4_204:} 红影 发表于 2025-11-14 23:23
还可以通过长短轴的设计,让小球的弯曲量得到控制
对,配置里的 r1 r2(本来应该命名为 rx、ry,更直观) 红影 发表于 2025-11-14 23:22
哦,知道了
看情况,满意指令提供的返回值就用指令,代码会少很多;不满意的再自己设置,代码量偏大 杨帆 发表于 2025-11-14 23:16
抽象点也好,骨感美,特别是老师的讲解还赋予了它冷峻的美呢
感觉讲解使用的方式没有突破初级教程的风格 马黑黑 发表于 2025-11-15 11:14
感觉讲解使用的方式没有突破初级教程的风格
讲解内容似乎对讲解方式与风格影响不大
讲解方式与习惯有关,重要的是要有自己的风格
老师的讲解方式挺好呀,独具风格——深入浅出,简明扼要,耐人寻味~ 马黑黑 发表于 2025-11-15 11:12
对,配置里的 r1 r2(本来应该命名为 rx、ry,更直观)
知道它表达的含义就好,命名倒是无所谓呢。 马黑黑 发表于 2025-11-15 11:13
看情况,满意指令提供的返回值就用指令,代码会少很多;不满意的再自己设置,代码量偏大
两者都能用,给使用者提供了极大的便利呢。 红影 发表于 2025-11-15 22:59
两者都能用,给使用者提供了极大的便利呢。
应该是这样 红影 发表于 2025-11-15 22:58
知道它表达的含义就好,命名倒是无所谓呢。
命名讲究的:rx 表示水平方向的半径,ry 表示垂直方向的半径。不过也有用R1、R2的惯例 马黑黑 发表于 2025-11-15 23:06
应该是这样
感谢黑黑的设计{:4_187:} 马黑黑 发表于 2025-11-15 23:07
命名讲究的:rx 表示水平方向的半径,ry 表示垂直方向的半径。不过也有用R1、R2的惯例
嗯嗯,也就是我们常说的横轴竖轴的半径吧,用xy的比R1、R2的的确更容易理解。
页:
[1]
2