需求背景

之前为目前所在动效组开发了一个AE的效率小插件。事情是起因是组内为了动效规范化,做了很多规范去约束动效,组内另外一位同事对于UI动效时间提了一个很好的方案。简单来说就是定义了一套规则,让动画时间随着位移的变化而变化。具体规则细节不在这儿赘述。

这个规则很好,唯一的难点在于规则不够直接,在实际操作过程存在一个计算的过程,导致该规则迟迟不能在组内推广,于是我打算搞一个小脚本来完成这个计算。
下面是该脚本的演示:

根据距离修改关键帧.mp4 (1.43MB)

AE的脚本开发是基于JavaScript的。AE提供了一系列的api去操作图层、属性和帧。开发者只需要查阅开发者文档即可。但是不得不说adobe年久失修的开发者文档及其难用,在http://aenhancers.com/ 论坛上可以看到其他开发者的一些经验。

实现思路

总的来说 脚本的初衷是操作关键帧 通过读取物体位移的大小 来动态更改关键帧的距离来实现修改物体运动实现的功能

操作也很简单 用户在选择要修改的关键帧后 执行脚本 脚本去操作关键帧的位置 移动到目标时间。

先通过props= selectedLayers[x].selectedProperties; 将选中的属性存入props中。
再遍历props。判断属性是一维还是二维(单独的x y轴坐标/合在一起的position属性)
通过一定规则计算出关键帧要修改的间隔时间后 通过addKey()在目标时间添加关键帧 并通过setValueAtKey()给关键帧添加变量
最后利用removeKey统一删除多余的关键帧

操作看似麻烦。实则是因为具体编写中踩到了一些坑
一开始我removeKey是写在对props的遍历中的。但是我发现 一旦执行了removeKey() 对属性层的选择就会取消。然后过程会被中断 导致只能操作一个属性层,最后无果只能单独把removeKey()拎出来 并用了一个数组去记录props 事后单独对这个数组遍历去删除多余的点

核心代码

  1. for(var x=0; x<=(selectedLayers.length-1);x++){
  2. props= selectedLayers[x].selectedProperties;
  3. for(var y=0; y<=(props.length-1);y++){
  4. p=props[y];
  5. positionStart = p.keyValue(p.selectedKeys[0]);
  6. positionEnd = p.keyValue(p.selectedKeys[1]);
  7. startTime = p.keyTime(p.selectedKeys[0]);
  8. //alert(positionEnd instanceof Array); 需要判断value是否为数组(position)
  9. if(positionEnd instanceof Array &&positionStart instanceof Array){
  10. //求两点距离 二维坐标
  11. distance=Math.sqrt(Math.pow((Math.abs(positionEnd[0])-Math.abs(positionStart[0])),2)+Math.pow((Math.abs(positionEnd[1])-Math.abs(positionStart[1])),2));
  12. //alert(distance);
  13. }else{
  14. distance=Math.abs(Math.abs(positionEnd)-Math.abs(positionStart));
  15. }
  16. changeTime=(Math.ceil(distance/180)-1)*20+300;
  17. //位移-时间 规则
  18. //p.setValueAtTime(startTime+changeTime/1000, positionEnd);
  19. //旧的方案
  20. //alert(startTime+changeTime/1000);
  21. addKeyIndex[propsNum]=p.addKey(startTime+changeTime/1000);//判断选择的属性是否为位置
  22. propsNum++;
  23. //用了这种方法后 好像就不能多选了
  24. //alert(addKeyIndex[y]);
  25. p.setValueAtKey(addKeyIndex[y],positionEnd);
  26. selectedArray.push(p);
  27. //alert(y);
  28. }
  29. }
  30. for (var i = 0; i <= (selectedArray.length-1); i++) {
  31. //需要在操作前遍历一下选择的点相对所有点的位置 然后再删除点
  32. selectedArray[i].removeKey((addKeyIndex[i]+1));
  33. //下一个迭代:判断是+1还是减1
  34. if(i==(selectedArray.length-1)){
  35. selectedArray.length==0;
  36. }
  37. }


未来迭代方向

脚本当前还有一些问题有待迭代 按照未来迭代计划 在维修bug的同时准备加入预设曲线的功能 达成一站式参数修改
image.png