本讲主要讨论使用tzMaker制作自定义的粒子,涉及到的主要指令有 ringPos() 和 ranPos(),ring 代表圆环、ran表示随机,pos是 position 的缩写、意为位置。先从 ringPos() 指令开始,它返回一个数组,形式为 [x, y],即圆弧顶点的坐标数据。看示例:
<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');
// 取15个点坐标,X、Y偏移量为粒子宽高各一半
const ps = tz.ringPos(15, { offsetX: 20, offsetY: 20 });
// 遍历 ps 数组(注意 style 内的注释不能简单用 // 表示)
ps.forEach( (p, k) => {
tz.add('div', '', 'lz', {style: `
left: ${p[0]}px; /* 左定位 */
top: ${p[1]}px; /* 上定位 */
--deg: ${tz.getRanInt(0, 360)}deg; /* 渐变角度随机 */
`});
tz.son.textContent = k + 1;
});
</script>
ringPos() 指令需要两个参数,第一个参数是数值参数,取多少个外切圆弧上的点,第二个参数是一组配置,约定有圆弧覆盖角度 a(默认360),取点起始角度 startA(默认0),圆心坐标 cx、cy(默认为帖子容器宽高的一半),长、短半径 r1、r2(默认为帖子容器宽高的一半再减去100),点的 X、Y 偏移量 offsetX 和 offsetY(默认都是0),键值对顺序不论,要求名称对上、键值合法。上例的配置,获取15个圆弧上的点坐标,配置参数仅 offsetX 和 offsetY 偏移量,其余配置均取默认值。可以做更多更详尽的配置以便生成预设的粒子效果,看下例:
<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, // 覆盖角度,改为 -180 粒子整体将是另一个朝向
startA: -90, // 起点角度,改为 -90 粒子排序将是另一个方向
offsetX: 20,
offsetY: 20
});
ps.forEach( (p, k) => {
tz.add('div', '', 'lz', {style: `
left: ${p[0]}px;
top: ${p[1]}px;
--deg: ${tz.getRanInt(0, 360)}deg;
`});
tz.son.textContent = k + 1;
});
</script>
角度,包含覆盖角度、起始角度,均支持正、负数值。圆的角度为360度,圆周的起点是三点钟方向、走向顺时针,可以再配置中改变覆盖角度和起点角度,并通过二者的正、负数值的合理配套来改变粒子整体的朝向和粒子个体的排列顺序方向。
如果希望生成在正圆轨道上排列粒子,则需要配置 r1、r2 参数为相等的数值,另外,可以改变外切圆的圆心以布置粒子的整体位置,下面的配置代码生成的粒子绕成一个正圆,正圆轨道在帖子容器的(400,300)坐标处:
const ps = tz.ringPos(15, {
cx: 400,
cy: 300,
r1: 120,
r2: 120,
a: 360,
startA: -90, // 起点在十二点钟即0点钟方向
offsetX: 20,
offsetY: 20
});
接着谈谈 ranPos() 指令。该指令返回指定数值内的随机数值,注意返回值并不是完整的点坐标XY值而只是其中之一。指令总共需要两个参数,都是数值参数,第一个参数必选,可以视为距离数值,指令将在这个距离范围内生成一个随机点的坐标值之一;第二个参数为偏移值,可选,默认值为0,这是基于粒子的宽高而做的考虑,为的是用指令返回值定位元素时元素不至于超越容器边界。下面的例子将通过 ranPos() 指令制定50个粒子的各自随机位置:
<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');
// 取50个点,依据帖子容器宽高减去偏移量生成坐标值作为粒子的定位数据
Array.from({length: 50}).forEach( (_, key) => {
const x = tz.ranPos(pa.offsetWidth, 40); /* x坐标依据帖子容器宽 */
const y = tz.ranPos(pa.offsetHeight, 40); /* y坐标依据帖子容器高 */
tz.add('div', '', 'lz', {style: `
left: ${x}px;
top: ${y}px;
--deg: ${tz.getRanInt(0, 360)}deg;
`});
tz.son.textContent = key + 1;
});
</script>
不一定同时获取两个随机数,一切看需要而定,例如,希望粒子从上往下掉落,或从右向左飞行,则可以固定 top 或 left,此时只需获取 y 或 x 的配套随机值即可。无需考虑偏移量时,偏移量参数可以缺省。
生成了粒子,动画层面只需要在CSS中设计,自定义的动态粒子系统即刻实现。不过动画的实现这里不再重复讨论,本讲的重点在于对两个指令 ringPos() 和 ranPos() 的介绍,使用它们生成了自定义的粒子,任务就已完成。
ringPos() 和 ranPos() 指令并非完全为粒子而设计,它们除了可以用来辅助生成粒子(本质是给粒子定位),还能做更多,一切仅局限于设计和实现能力。