自用AE表达式
个人之前写的After Effects表达式
自用AE表达式
表达式学习相关链接:
Con幺幺的AE学习笔记
月离AE表达式文档
鹤梦表达式增强库
标记字幕表达式
基于标记生成字幕
支持混合使用普通标记和有持续时间的标记,将表达式添加到带有标记的文本层使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
m = thisLayer.marker.nearestKey(time);
//寻找最近的标记
function ifZero(){
if(m.index-1==0){
return ""
}else{
return ifDuration(m.index-1)
}
}
//判断是否为零,如果零输出空值
function ifDuration(a){
var kayA=thisLayer.marker.key(a);
if(kayA.duration==0){
return thisLayer.marker.key(a).comment
}else{
if(time <= kayA.time+kayA.duration){
return thisLayer.marker.key(a).comment
}else{
return ""
}
}
}
//判断标记是否有持续时间,如果有,判断当前时间是否在持续时间内
if(m.time <= time){
ifDuration(m.index)
}else{
ifZero()
}
基于图层标记时间映射动画
同上,支持混合使用普通标记和有持续时间的标记,示例表达式可用于图层透明度属性。
将表达式添加到带有标记的文本层,或者添加到其他图层将layer1修改为文本层使用。
建议学习:AE文本动画文档
配合使用可以做出许多有趣的效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//V1.02 by Con11
//数组需要按照例如[100,100]的格式输入数值
inValue=0;//进入数值
stayValue=100;//一般数值
outValue=0;//退出数值
aniTime=0.5;//动画时间
aniDely=0;//动画延迟
linearTrue=false;//是否线性,true为线性,false为缓动
layer1=thisLayer;//图层
m = layer1.marker.nearestKey(time);
//寻找最近的标记
function ifZero(){
if(m.index-1==0){
return ""
}else{
return ifDuration(m.index-1)
}
}
//判断是否为零,如果零输出空值
function ifDuration(a){
var kayA=layer1.marker.key(a);
if(kayA.duration==0){
return layer1.marker.key(a).index
}else{
if(time <= kayA.time+kayA.duration){
return layer1.marker.key(a).index
}else{
return ""
}
}
}
//判断标记是否有持续时间,如果有,判断当前时间是否在持续时间内
if(m.time <= time){
nowMark=ifDuration(m.index);
}else{
nowMark=ifZero();
}
function linearIn(a){
return linear(time,a,a+aniTime,inValue,stayValue)
}
function linearOut(a,b,c){
if(layer1.marker.key(nowMark).duration==0){
return linear(time,c-aniTime,c,stayValue,outValue)
}else{
return linear(time,a+b-aniTime,a+b,stayValue,outValue)
}
}
//线性出入
function toEaseIn(a){
return ease(time-aniDely,a,a+aniTime,inValue,stayValue)
}
function toEaseOut(a,b,c){
if(layer1.marker.key(nowMark).duration==0){
return ease(time-aniDely,c-aniTime,c,stayValue,outValue)
}else{
return ease(time-aniDely,a+b-aniTime,a+b,stayValue,outValue)
}
}
//缓动出入
if(nowMark==""){
inValue
//如果索引是空返回进入值
}else{
markTime=layer1.marker.key(nowMark).time;
if(layer1.marker.nearestKey(outPoint).index==nowMark){//判断是否为最后一个标记
markTime1=outPoint
}else{
markTime1=layer1.marker.key(nowMark+1).time;
}
markDuration=layer1.marker.key(nowMark).duration;
if(linearTrue==true){//判断是否为线性
if(time <= markTime+aniTime){
linearIn(markTime)
}else{
linearOut(markTime,markDuration,markTime1)
}
}else{
if(time <= markTime+aniTime){
toEaseIn(markTime)
}else{
toEaseOut(markTime,markDuration,markTime1)
}
}
}
路径跟踪
获取修剪路径上的点坐标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
thePath = ;//路径
startEndValue = ;//开始点/结束点
offSetValue = ;//偏移量
var getTrimPathPoint = function(thePath,startEndValue,offSetValue) {
//获取图层
var i = 1,j = 0, theLayer = "";
do {
try {
theLayer = thePath.propertyGroup(i);
i = i + 1;
} catch (err) {
j = 1;
}
} while (j == 0)
//获取结束点位置+偏移值
var x=startEndValue/100 + offSetValue/360;
var y=x-Math.floor(x);
return thePath.pointOnPath(y) + theLayer.toComp(transform.anchorPoint);//输出当前点位置 + 合成空间位置
}
getTrimPathPoint(thePath,startEndValue,offSetValue);
获取修剪路径上的点切线方向
1
2
3
4
5
6
7
8
9
10
11
thePath = ;//路径
startEndValue = ;//开始点/结束点
offSetValue = ;//偏移量
var getTrimPathRotion = function(thePath,startEndValue,offSetValue) {
//获取结束点位置+偏移值
var x=startEndValue/100 + offSetValue/360;
var y=x-Math.floor(x);
var tangent=thePath.tangentOnPath(y)//获取路径点tan值
return 90 + value - radiansToDegrees(Math.atan2(tangent[0],tangent[1]));//转换tan到角度,输出当前角度值-路径角度值
}
getTrimPathRotion(thePath,startEndValue,offSetValue);
数组取整
数组四舍五入取整
1
2
3
4
5
6
7
8
9
10
value = ;//此处输入数组
var arrayRound = function(value) {
var arrayLength = value.length;
var outputValue = value;
for (i=0; i < arrayLength; i++){
outputValue[i]=(Math.round(value[i]));
}
return outputValue;
}
arrayRound(value);
数组去除小数
1
2
3
4
5
6
7
8
9
10
value = ;//此处输入数组
var arrayTrunc = function(value) {
var arrayLength = value.length;
var outputValue = value;
for (i=0; i < arrayLength; i++){
outputValue[i]=(Math.trunc(value[i]));
}
return outputValue;
}
arrayTrunc(value)
数组向上取整
1
2
3
4
5
6
7
8
9
10
value = ;//此处输入数组
var arrayCeil = function(value) {
var arrayLength = value.length;
var outputValue = value;
for (i=0; i < arrayLength; i++){
outputValue[i]=(Math.ceil(value[i]));
}
return outputValue;
}
arrayCeil(value)
数组向下取整
1
2
3
4
5
6
7
8
9
10
value = ;//此处输入数组
var arrayFloor = function(value) {
var arrayLength = value.length;
var outputValue = value;
for (i=0; i < arrayLength; i++){
outputValue[i]=(Math.floor(value[i]));
}
return outputValue;
}
arrayFloor(value);
获取图层变换
获取真实位置
1
2
3
targetLayer = ;//输入图层
targetLayer.toWorld([0,0,0]);
获取真实旋转方向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
targetLayer = ;//输入图层
function getXRotion(){
zVec = normalize(targetLayer.toWorldVec([0,0,1]));
return radiansToDegrees(Math.atan2(-zVec[1], zVec[2]));
}
function getYRotion(){
zVec = normalize(targetLayer.toWorldVec([0,0,1]));
return radiansToDegrees(Math.asin(zVec[0]));
}
function getZRotion(){
xVec = normalize(targetLayer.toWorldVec([1,0,0]));
yVec = normalize(targetLayer.toWorldVec([0,1,0]));
return radiansToDegrees(Math.atan2(-yVec[0], xVec[0]));
}
[getXRotion(),getYRotion(),getZRotion()];
计算两个物体在摄像机屏幕坐标系下的z轴距离
计算两个物体的前后距离,同时可用于判断物体前后关系
New Bing AI写的表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var A = ;//图层A
var B = ;//图层B
// 获取两个物体的世界坐标
var A_world = A.toWorld(A.anchorPoint);
var B_world = B.toWorld(B.anchorPoint);
// 获取摄像机的世界坐标和方向
var cam = thisComp.activeCamera;
var cam_world = cam.toWorld([0,0,0]);
var cam_dir = cam.toWorldVec([0,0,-1]);
// 计算两个物体在摄像机方向上的投影长度
var A_proj = dot(A_world - cam_world, cam_dir);
var B_proj = dot(B_world - cam_world, cam_dir);
//输出
var z_dist = A_proj - B_proj;
z_dist;
其他
在关键帧前随机颜色
用于颜色属性
1
2
3
4
5
6
7
if (time < nearestKey(time).time){
posterizeTime(4);//设置帧数
seedRandom(index,timeless=false)
random([0,0,0,1],[1,1,1,1]);
}else{
nearestKey(time).value;
}
本文由作者按照 CC BY 4.0 进行授权