- 随机发射的方块组建成圆
- linear()表达式
- if……else……表达式
一、随机发射组成圆
1、新建方块形状层
为了和前面的动画无缝连接,新建一个位置同梯形切割后的方形相同位置相同大小的方形。
2、缩小的动画
这里需要方块以自己为中心缩小,而不是以锚点为中心缩小,所以要更改图形对象的缩放,也就是Contents - Shape 1 - Transform:Shape 1下面的Scale,而不是形状层的scale。
为了方便后期控制,新建一个null,更名为“control”,将方块图形的scale链接到null的scale,key上动画。
这里key了一个100%到15%的动画,F9平滑关键帧,曲线面板调整。
3、旋转的动画
这里为了让方块最后组成的圆能夠旋转,选择的方法是更改Anchor Point,使得图形位置偏移,但形状层的锚点位置不变,方便图形能够围绕锚点旋转。
同样为了方便控制,将形状层Rotation和“control”的Rotation建立父子链接,然后在表达式后面增加一个基于index的增量:
thisComp.layer("control").transform.rotation + (index-2)*6
这里每层增加6度,也就是一共复制60层,就刚好60个小方块旋转一周组成一个完整的圆。
command/ctrl + D复制的动作留到后面,这里还有其他事情要做。
4、发射的动画
让方块从中心点发射到四周,给Anchor Point添加linear()就可以很好的实现,但是这个动画是先发射到一个较大的半径,然后回来组成一个相对半径较小的圆,并且发射出去的时间是有随机延迟的。
先给名为“control”的null添加两个slider control,分别命名为“minRadius”和“maxRadius”。
给方块的Anchor Point添加表达式:
seedRandom(index, true); strtTime = random(.3); endTime = strtTime + .5; decay = .5; minRadius = thisComp.layer("control").effect("minRadius")("Slider"); maxRadius = thisComp.layer("control").effect("maxRadius")("Slider"); if(time >= strtTime){ y = value[1]; if(time < endTime){ x = value[0] + linear(time, strtTime, endTime, 0, maxRadius);} else if(time >= endTime){ x = value[0] + maxRadius - easeOut(time, endTime, endTime + decay, 0, maxRadius - minRadius);} }else{ x = value[0]; y = value[1]; } [x,y]
这个表达式很好理解,利用if……else if将时间分成三段:
1、利用seedRandom()得到一个随机的时间值(这里是在0 ~ 0.3之间取随机值),这也是每个方块发射的随机延迟值;
2、从strtTime(start是js语言,所以命名使用的时候一般都会少写一个a)到endTime之间,是方块发射到最大半径的位置;
3、从endTime开始往后的0.5秒,方块从最大半径回到最小半径的位置。
5、透明值改进
完成上述步骤后,会发现在所有方块未发射出去以前,全部都挤在一起,很不美观,所以我们需要一个基于位置变化而改变的透明值变化。
也就是,方块在中心点的时候,透明值为0,发射后透明值变到100。给Opacity添加表达式:
scr = transform.anchorPoint[0]; n = 30; m = 80; if(scr <= n){ transform.opacity = 0; }else{ transform.opacity = ease(scr, n, m, 0 ,100);}
这个表达式是让方块离锚点30像素距离以内透明质为0%,在30像素到80像素之间透明度线性变化到100%,80距离以外透明度都是100%。
6、运动的调试和改进
更进一步增加运动的丰富性,以及让运动和声音结合,改变参数进行调试。
Anchor Point的表达式更改为:
seedRandom(index, true); strtTime = random(1); endTime = strtTime + .5; decay = 1; minRadius = thisComp.layer("control").effect("minRadius")("Slider"); maxRadius = thisComp.layer("control").effect("maxRadius")("Slider"); if(time >= strtTime){ y = value[1]; if(time < endTime){ x = value[0] + linear(time, strtTime, endTime, 0, maxRadius);} else if(time >= endTime){ x = value[0] + maxRadius - easeOut(time, endTime, endTime + decay, 0, maxRadius - minRadius);} }else{ x = value[0]; y = value[1]; } [x,y]
60个方块里随机选择几个(跳跃着在四周选),将Anchor Point的表达式改为:
seedRandom(index, true); strtTime = random(1); endTime = strtTime + 1; minRadius = thisComp.layer("control").effect("minRadius")("Slider"); y = value[1]; if(time > strtTime){ x = value[0] + easeOut(time, strtTime, endTime, 0, minRadius); }else{ x = value[0]; } [x,y]
这个表达式让方块不发射到大的半径再回来,而是直接到最小半径的位置。
再随机选择一些方块,将Anchor Point的表达式里的strtTime后的random的值改为(1,2),让这部分小方块发射时间晚一点:
seedRandom(index, true); strtTime = random(1,2); endTime = strtTime + 1; minRadius = thisComp.layer("control").effect("minRadius")("Slider"); y = value[1]; if(time > strtTime){ x = value[0] + easeOut(time, strtTime, endTime, 0, minRadius); }else{ x = value[0]; } [x,y]
总之,让方块的运动尽量在时间线上平均,让运动更多随机,也就更为丰富。
前面直接将所有直接运动到最小半径(不先到最大半径,没有回返运动)的方块,开始运动的时间用random在(1)或(1,2)取值,而非直接全部写成(2),是为来方便控制。我们在写好表达之后,右键点击相关属性,选择“copy expression only”,然后选择其他图层,command/ctrl + V 就可以直接将表达式粘贴到相关属性之下。
所以,这里我们在粘贴时候是有选择的,在360度各个方向跳跃着随机选择方块,让其开始运动时间在0~1间取随机值。然后再次在360度各个方向随机取方块,让其开始运动时间在1~2秒之间随机取值。
这样,就保证了在各个时间段,各个方向都有方块在运动,不会在某个时间出现一块“空地”。
二、置换的红点
1、准备工作
将所有60个小方块全部复制,打好出点入点。在方块圆针形成的时间点打出入点。
将新的60个方块图层里Anchor Point的表达式替换为:
offset = thisComp.layer("control").effect("minRadius")("Slider"); y = value[1]; x = value[0] + offset; [x,y]
2、小方块的弹性动画
给名为“control”的null添加slider control,命名为offset。给offset打关键帧,偏移50个像素。
间隔地随机选择5个小方块,将五个小方块的Anchor Point的表达式改为:
minRudius = thisComp.layer("control").effect("minRadius")("Slider"); offset = thisComp.layer("control").effect("offset")("Slider"); y = value[1]; x = value[0] + minRudius - offset; [x,y]
或者:
minRudius = thisComp.layer("control").effect("minRadius")("Slider"); offset = thisComp.layer("control").effect("offset")("Slider"); y = value[1]; x = value[0] + minRudius + offset; [x,y]
加上offset是圆圈外偏移50像素,减去offset是往圆圈内偏移50个像素。
这里注意5个方块的往内往外运动间隔一下,一个往内,下一个往外,在下一个往内,以此类推……
给“control”的offset添加弹性表达式:
amp = .2; freq = 5.0; decay = 8.0; n = 0; if (numKeys > 0){ n = nearestKey(time).index; if (key(n).time > time){n--;} } if (n == 0){ t = 0;} else{t = time - key(n).time;} if (n > 0){ v = velocityAtTime(key(n).time - thisComp.frameDuration/10); value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t); } else{value}
调整offset的关键帧,让小方块弹出去再回来。
TIPS:
这里已经有了100多个层,但是这一步骤只用得到这5个层,为了方便操作,可以将暂时用不到的其他层全部隐藏起来。
3、小方块的位移
给选出来的5个小方块添加slider control,修改Rotation的表达式为:
thisComp.layer("control").transform.rotation + (index-2)*6 + effect("Slider Control")("Slider")
给slider打关键帧,给正值就是顺时针旋转,给负值就是逆时针旋转。因为每个小方块相差6度,所以这里slider要给6的整数。
slider的运动区间要在小方块弹出去和弹回来的空隙。
打开曲线面板,调整slider的关键帧运动速度。
给5个小方块都相同操作,可以随机一点交换位置,而不是两两交换。
4、小方块的变色
给名为“control”的null添加两个color control,分别命名为“240color”和“67color”。
打好关键帧,分别是从[240,240,240]变为[238,60,129],以及从[67,67,67]变为[238,60,129]。(这三个颜色都是本项目中仅有的三种颜色,所有颜色要统一起来,不然会花里胡哨)
利用拾取器将color control和五个小方块的stroke的color、以及fill的color有选择的关联起来。就是将其他颜色变成红色,再变回来。
调整关键帧位置,F9平滑关键帧。
4、拖尾效果
用particular制作拖尾效果,因为之前的弹性表达式的关系,方块的运动不是完全的弧线,中间有几个转折,不过一晃而过效果不明显,就不改了。
这里需要给particular的Position XY添加表达式:
thisComp.layer("方块 69").toComp([0,0,0])
利用toComp()得到小方块中心点的位移路径,将其作为粒子发射器的位移路径。
另外就是给粒子发射数量key了关键帧,其他一些参数设置,不细说了。
请登录以参与评论
现在登录