【AE表达式】基于时间随机的溶解转场
这篇文章里面讲的内容非常简单,又比较实用,而且很常用,它是一种可以自由设置的转场,基于表达式和形状图层,而不是效果,因此你可以用它来制作很多比较平凡又不那么平凡的转场,不管是在 AE 中还是 PR 中,甚至任何软件里面都可以使用,下面的视频仅枚举了最简单的设置。
除了实用性,本篇文章也将带你学习表达式在处理空间和时间上的一些基本用法,都是非常简单的,数学知识不超过小学二年级范围,学习时间大概半个小时。另外想起来,我前两天翻出来我那台十年前的 Thinkpad W520,因为配置很老,只能运行 AE 2018 版本,然后发现在旧版本上并不支持新的 JavaScript 引擎,但是我现在这个专栏中的所有表达式都是基于 JavaScript ES6 标准的,如果你还在用旧版本,建议升级到 2021 或最新版本。
一个 Comp 或者一个 Layer 之所以被我称为控件,就是因为它是参数控制的,通过参数控制或者一些简单的复制、删除等操作就可以自动生成出同类但不相同的效果,控件的好处就在于复用性,特别像转场这种东西,你可能需要不断的调用它,但是又不像总是重复相同的效果,所以使用控件或者可以自定义的转场效果都是不错的选择,相对于转场的效果或插件,使用控件主要是可以避开前者的一些限制,而且通过 Alpha 遮罩控制的转场也可以更灵活。如果你做出一批画质很好,尺寸很大的预设转场,使用时直接调用渲染好的视频,也可以缓解软件的运行压力。
先说一下这个控件的产生背景是一位粉丝私信我关于随机控制时间节点的问题,他的代码思路基本上没错,只是在命令上多打了一个字母,所以报错了。我从他的这个事情上获得一些灵感,就做了这个控件以备后用。这个控件的核心是被分割的画面进行透明度过渡,但是它们执行的时间是随机的,这是让转场效果看起来不那么呆板的核心。
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
三次转场只是分割的块不同,当你把它看作一个网格,然后只考虑存在几行几列就很容易理解了。直接看工程中的结构。
![](/assets/blank.gif)
这是对应最上面那个竖条转场的,所以它有 1 行,行中存在 6 个块,按表格方式理解的话即 1 行 6 列,行列都是按照合成宽高平均分布的。我们需要实现计算的主要是行和块的大小和位置。
![](/assets/blank.gif)
为了可以让每一个块都可以单独控制透明度,必须把块的路径和填充放在组中包裹起来,现在来看一下表达式所在属性的层级索引:
![](/assets/blank.gif)
计算列数即查找 [4] 内容 中的数量,计算行数则查找 [6] 内容 中的数量。这部分还不知道的请继续复习 propertyGroup() 部分的知识。
getCellSize: () => {let w = thisComp.width / thisProperty.propertyGroup(4).numProperties;let h = thisComp.height / thisProperty.propertyGroup(6).numProperties;return [Math.ceil(w), Math.ceil(h)]},
块的宽度即列宽,等于合成宽度除以列数;块的高度即行高,等于合成高度除以行数。为了避免不能整除得到的画面出现缝隙,我们都用 ceil() 方法对结果进行上舍。下面再来计算一下每一个块(单元格)在行中的位置:
![](/assets/blank.gif)
这里再一次用到了属性层级索引:
![](/assets/blank.gif)
// 获取列的位置函数getCellPosition: () => {// 指定当前的位置,就是第几列let current = thisProperty.propertyGroup(2);// 统计出一共有多少列let cells = current.propertyGroup(1).numProperties;// 求出列宽,注意这里的列宽是没有进行上舍的// 因此也不能引用矩形路径大小,不然就不能填补缝隙了let w = thisComp.width / cells;// 按照位置索引进行偏移计算// 每一个偏移的倍数都比自身的索引少 1 倍列宽let x = w * (current.propertyIndex - 1)// 整体向左偏移// 也可以写成下面的等效公式// x -= h * (cells - 1) * .5;x -= (thisComp.width - w) * .5;return [x, 0]},
看图分解:
![](/assets/blank.gif)
在没有整体向左移动的时候,需要移动的量就是用红色矩形标记的部分,只要第一个块的位置没有变,那么跑到合成外面的部分永远都等于列数减 1 的总宽度的一半,就是被我注释掉的那行,也可以理解为用合成宽度减掉一个列宽再除以 2,在计算行定位的时候是完全相同的算法。
// 获取行的位置getRowPosition: () => {let current = thisProperty.propertyGroup(2);let rows = current.propertyGroup(1).numProperties;let h = thisComp.height / rows;let y = h * (current.propertyIndex - 1);y -= (thisComp.height - h) * .5;return [0, y]},
至此我们要简化代码的话,可以把相同的算法写成一个函数再调用:
// 获取列的位置函数getCellPosition: () => {let x = myClass.getOffset(thisComp.width)return [x, 0]},// 获取行的位置getRowPosition: () => {let y = myClass.getOffset(thisComp.height)return [0, y]},// 计算偏移getOffset: (total) => {let current = thisProperty.propertyGroup(2);let quantity = current.propertyGroup(1).numProperties;let ave = total / quantity;offset = ave * (current.propertyIndex - 1);offset -= (total - ave) * .5;return offset},
然后是随机时间的不透明渐变,意思就是每一个块进行渐变的开始时间,结束时间,持续时间都是随机的,但是又保证了它们在某一个相同的时间点完全不透明,这个点就是剪辑时两个画面衔接的剪辑点,我已经使用了一个 marker 作为时间标记:
![](/assets/blank.gif)
// 随机时间的不透明度渐变getRndOpacity: (start, end, range, smooth = true) => {seedRandom(index, smooth);value = ease(time, start - random(0, range), start + random(0, range), 0, value);value = ease(time, end - random(0, range), end + random(0, range), value, 0);return value},
原理非常简单,range 用来控制随机范围,这样可以保证每个时间点偏移在可控范围内,start、end 则用来控制动画开始和结束的基础时间点。
![](/assets/blank.gif)
eval(footage("myClass.jsx").sourceText)
myClass.getRndOpacity(thisComp.marker.key(1).time-framesToTime(effect("时间随机程度")(1)),
thisComp.marker.key(1).time+framesToTime(effect("时间随机程度")(1)),
framesToTime(effect("时间随机程度")(1)),
effect("平滑过渡")(1))
实际调用的时候并没有让过渡完成的部分保持一段时间,而只是选取了一个点,这样可以节约比较多的资源,使用转场的时候配合时间重映射就可以了。
myClass = {// 获取单元格尺寸getCellSize: () => {let w = thisComp.width / thisProperty.propertyGroup(4).numProperties;let h = thisComp.height / thisProperty.propertyGroup(6).numProperties;return [Math.ceil(w), Math.ceil(h)]},// 获取列的位置函数getCellPosition: () => {let x = myClass.getOffset(thisComp.width)return [x, 0]},// 获取行的位置getRowPosition: () => {let y = myClass.getOffset(thisComp.height)return [0, y]},// 计算偏移getOffset: (total) => {let current = thisProperty.propertyGroup(2);let quantity = current.propertyGroup(1).numProperties;let ave = total / quantity;offset = ave * (current.propertyIndex - 1);offset -= (total - ave) * .5;return offset},// 随机时间的不透明度渐变getRndOpacity: (start, end, range, smooth = true) => {seedRandom(index, smooth);value = ease(time, start - random(0, range), start + random(0, range), 0, value);value = ease(time, end - random(0, range), end + random(0, range), value, 0);return value},// 生成随机颜色getRndColor: () => {seedRandom(index, true);return random([0, 0, 0, 1], [1, 1, 1, 1]);}
}
完整代码贴到一个文本文档里面,可以直接导入到 AE 中,然后使用 eval() 方法运行。
【AE表达式】基于时间随机的溶解转场相关推荐
- 【AE表达式】300多个人名正从宇宙中飞来……
问题 数量级的问题: 昨天我朋友问:要做三百多个人名(文本)从宇宙深处飞出来的效果,怎么处理? 对于这样的需求,做 AE 包装的小伙伴们都不陌生,就是 3D文本层摆位置,打个相机穿梭一下.没错,对于几 ...
- ae制作的mg如何用到html,【教程】AE表达式常用的函数-制作MG动画必备
我一开始接触AE是简单的套模板,后来慢慢学会自己调关键帧动画.感觉应用比较多的同样也让我很头疼的是运动.所以对表达式控制做了初步的学习.下面是一些常用的AE表达式 1.time time随着时间线的变 ...
- 如何学好 AE 表达式?
--你知道世界上最难的问题是什么吗? --就是这道题. 上面的只是一个梗,不过面对知乎里或者朋友的这种发问,我真的不知道怎么回答,从上个礼拜,我就开始琢磨这个事儿:如何讲明白如何学好 AE 表达式.问 ...
- 【转载】AE 表达式精通大法
本文是转自 设计树 的一篇文章,我对文章进行了重新排版,并标注了重点 原文地址 -- AE表达式精通大法 以下是正文部分: AE 表达式一直是大家学习 AE 过程中的一道坎,涉及代码网上教程资源又不多 ...
- ae绘图未指定错误怎么办_【教程】最全的ae表达式教学分享(实用!)表达式其实很简单...
大部分人对ae表达式是望而却之,感觉很难,无从下手,网上的教程也是层次不齐,很难找到好的教程跟着学.于是呢,搜罗全网,整理了一份最全的最实用的ae表达式教学.也算是一个对自己的总结. 下面解决几个问题 ...
- 基于时间卷积神经网络的概率预测
https://www.toutiao.com/a6715386490647478797/ 基于时间卷积神经网络的概率预测 题目: Probabilistic Forecasting with Tem ...
- mysql基于时间盲注_MYSQL基于时间的盲注详解
MYSQL基于时间的盲注 联合查询,报错注入,以及布尔盲注,都是基于攻击网站会回显消息,或者将错误信息返回在前端,或者会返回web页面的正确或错误 但是有时候网站关闭了错误回显或过滤了某些关键字,网页 ...
- uuid表示时间的部分_基于时间UUID的妙用
1.jar包获取 https://github.com/cowtowncoder/java-uuid-generator/ com.fasterxml.uuid java-uuid-generator ...
- 微信后台基于时间序的海量数据冷热分级架构设计实践
写在前面 微信的后台数据存储随着微信产品特性的演进,经历了数次的架构改造,才形成如今成熟的大规模分布式存储系统,有条不紊的管理着由数千台异构机型组成的机器集群,得以支撑每天千万亿级的访问.键值以及 P ...
最新文章
- static interface method calls are not supported at language level 1.6
- javascript高级程序设计之BOM
- 【深度学习】CV语义分割实践指南!
- c#下各种数据库操作的封装!(支持ACCESS,SQLSERVER,DB2,ORACLE,MYSQL)(二)
- java自增自减很难理解_关于java中自增,自减,和拓展运算符的小讨论
- Qt Designer的UI文件格式
- linux中的memory management和page mapping
- Facebook在欧洲推出网络极端内容与仇恨言论打压行动
- java自带的jvm在哪里看_使用jdk工具查看jvm笔记
- nginx 配置https_nginx 配置https
- 11月22日云栖精选夜读:双11享Go了吗?2017阿里双11在线峰会续写科技盛宴!
- Demo 示例:如何原生的在 K8s 上运行 Flink?
- Matlab简单教程:函数
- 百度问答怎么引流,百度知道引流技巧
- python--超市水果销售系统2.0
- mysql属于dbms还是dbs_DB、DBMS和DBS三者之间有什么关系_数据库
- C语言-qsort函数详解及使用例
- 软件评测师 各章节考点汇总(基础知识部分)
- 如何设置和取消PPT文件的打开密码
- 如何下载 qq群课堂 回放视频