Starry Night 表达式动画...

  • 经验类型经验/观点
  • 经验属性原创文章
  • 经验版权署名-非商业性使用
2931 0 4 2018-02-26

手写动画了解一下?

Starry night


设计场景

无缝衔接演化的星空


目标

1. 定义全局参数接口,快速调整。只用一个图层
2. 让参数驱动场景和随机动画的生成
3. 粒子自然随机地分布于界定范围
4. 实现周期随机,并且,达到无缝连接
5. 可按需调整形态


一、星星单体定义

1. 随机纵深

添加一个圆形基本形状,在形状的「路径/大小」属性上定义:

id = thisProperty.propertyGroup(2).propertyIndex;
seedRandom(id,true);
x = random(.001,4);//随机尺寸
y = x;//等宽高
[x,y]

解决思路:

random( ); 可实现数值上的随机,但会导致需要复制多个图层,不够灵活。
祭出进阶随机表达式,用形状层的独立索引 id 来产生随机种子,由一个图层管理:

id = thisProperty.propertyGroup(2).propertyIndex;//2代表返回第二级父级属性索引,此处为形状本身。
seedRandom(id,true);//true 使随机值固定,不随时间跳跃。
random( );

每复制一个星星(形状 Star),它的独立 id 就会产生差异化。

纵深用尺寸差异来体现,定义 [a,b] 限定合适范围即可。
惯用套路,使用一个小数值让最小的粒子都有存在感,范围限制在 (.001,4)。
同样的方法,我们可以添加一个匹配尺寸的随机「模糊」属性,让表现更加真实。

对象大小是一个包含宽、高的二维属性,随机必然产生偏差。
定义其中一个属性(宽度 x),再把其赋值给另一个属性( 高度 y)即可解决:

x = a;
y = x;
[x,y];

2. 角度偏移

形状的「变换/旋转」属性上,定义:

id = thisProperty.propertyGroup(2).propertyIndex;
value + 360*noise(id);//临近角度随机偏移

解决思路:

生成 360° 的临近随机偏移。
noise(id); 生成 [0,1] 的临近偏移量,再乘与 360。
value 为初始角度 0 ,加上偏移量 [0,360]:
value + 360*noise(id);

3. 随机分布

形状的「变换/位置」属性上,定义:

id = thisProperty.propertyGroup(2).propertyIndex;
seedRandom(id,true);
a = width/2;
b = height/2;
gaussRandom([-a,-b],[a,b]);//在画布区域高斯分布,10%在画布外

只用 random( ); 也是可以实现的,不过高斯(正态)分布更加自然,试试无妨。
画布中心是锚点是 [0,0],换算后星空的范围落于 [[-width/2,-height/2],[width/2,height/2]]
如果用于不同图层,只需要换成:

a = width;
b = height;
gaussRandom([0,0],[a,b]);

4. 无缝连接的周期随机亮度

形状的「变换/不透明度」属性上,定义:

freq = .2;//频率,每 0.2s 一次不透明度变化
amp = 100;//不透明度的偏移幅度
loopTime = 4;//定义周期
t = time % loopTime;//取余,周期重置
wiggle1 = wiggle(freq, amp, 1, .5, t);//抖动
wiggle2 = wiggle(freq, amp, 1, .5, t - loopTime);//反向偏移
value - linear(t, 0, loopTime, wiggle1, wiggle2);//首尾相接

学习了 Dan Ebberts 的 Looping Wiggle 方法,思路:


定义两个随机抖动 wiggle1,wiggle2。利用 linear 表达式将其首尾的随机数值连接,实现循环。
loopTime 和 t,则利用「取余」方法定义了动画周期,此处随着时间 (time) 的变化,每隔 4 秒一个周期。

其中,freq, amp 以及 loopTime 是三个核心参数,按需调整即可改变设计。

5. 形态

对形状层添加一个全局的「收缩与膨胀」效果
在「数量」上添加表达式:

a = 1.8 * layerStyle.outerGlow.opacity;//光芒长度和闪烁亮度关联
clamp(a,0,100);//限制范围

思路:

用「表达式关联器」,将星星尖角的数值 a 关联到下文添加的「外发光」属性上,达到亮度和发光度的正确匹配。
星星越亮,突出的尖角就会越大。
clamp( ); 把最大值限制到 100,可按需调整。

6. 无缝连接的周期闪烁

对父级图层 Starry 添加「外发光」样式,定义如下:

freq = .8;//频率,每 0.8s 一次不透明度变化
amp =30;//发光闪烁幅度
loopTime = 4;//定义周期
t = time % loopTime;//取余,周期重置
wiggle1 = wiggle(freq, amp, 1, .5, t);//抖动
wiggle2 = wiggle(freq, amp, 1, .5, t - loopTime);//反向偏移
linear(t, 0, loopTime, wiggle1, wiggle2);//首尾相接

思路:

同 4,应用 looping wiggle 方法。
初始外发光不透明度数值设为 50%,这个场景中,我不希望动画太过跳跃,幅度只用了 ±30%。
每个完整的 4s 周期里面,会有 5 次 每隔 0.8s ,从 20% 到 80% 的外发光闪烁。

调整核心参数 freq, amp 以及 loopTime,即可改变设计。


二、场景生成

单颗星星的定义完成,接下来就要实现设计师的终极愿望了:
一 劳 永 逸!

完整的星空图层结构如下图:

图层结构


两个全局控制参数决定星星的形态和整体的循环闪烁表现。分别是「收缩和膨胀」效果、「外发光」样式。
每颗星星 (Star) 的 id 会对自身的各子级属性产生不同的随机量。


按住 CMD+D 复制 Star!一片完全由参数驱动的星空扑面而来。
大繁归简,神奇的复制操作~~~
( •̀∀•́ )」✧ ヽ(•̀ω•́ )ゝ


三、小结


StarryNight 动画是对 近期所学 random 系列表达式的一个应用总结。案例中剥离了核心参数和全局控制来提升调整的灵活度和效率。完全可以傻瓜式地,直接使用「复制」快捷键来创造完整的场景。


整个场景的设计都是从本质规律出发的,这么一来就可以根据不同的需求逐步拆解,写出想象中的动画拉~


星空实际上是一种基础的粒子形态。同样的方法还可以生成「云团」、「烟花」、「撒花」、「爆破」等等常见的动态元素或场景。各位可以在此基础上举一反三。


用一根直线路径生成烟花:


烟花


星轨

Image title


至于研发实现环节,目前业界的 Lottie 方案对移动端的表达式解析还很不完善,对此我还是保留一点期待的。
当前可以使用视频和 apng 等特定的格式来做快速的设计验证。
掌握了核心参数法,视觉和开发 GG 的沟通也会更加的顺滑。
毕竟,他们也是用算法来写的,万变不离其宗——规律。


aep 源文件见文末附件。


附、应用的表达式


noise();//临近随机

random();//随机

id = thisProperty.propertyGroup(2).propertyIndex;//读取第二级父级索引
seedRandom(id,true);//生成随机量,使用 true 让随机值固定,不随时间变化
random();//输出

gaussRandom();//正态分布,10% 随机落于区域外

time*a;//随时间变化,月亮内部加了个湍流置换,效果随时间演化

wiggle(freq,amp);//抖动

clamp(a,aMin,Max);//限制参数a的范围

linear(x, xMin, xMax, output1, output2);//关联线性变化


全部评论:0

更多作品

发表评论

取消

点击右上角
分享给朋友吧

分享到

取消

每人每天仅限5票,快给你心仪的作品鼓励的一票。

投票