• AE特效解读


    // 解读:Musicminion 
    // 注释:原始的代码里面有一些冗余代码,我做了一些删除
    
    // 首先要理解这个表达式表达的是什么:这个表达式表示的是动画完成的
    // 以位置参数为例子:
    // 真实的位置参数 = 该图层在变换中的位置 + 偏移量(动画制作/表达式选择器中的位置值) * 表达式选择器里面的数量百分比
    
    
    // 这个数量百分比可以从 0% -> 100%, 也可以从 100% -> 0% 
    // 而我们这个表达式就是为了表示上面所述的 【表达式选择器里面的数量百分比】
    
    
    // 首先获取该合成的设置参数
    freq = effect("frequency")("滑块");		//(频率)
    decay = effect("decay")("滑块");			//(衰退,减缓)
    duration = effect("duration")("滑块");	//(持续时间)
    
    // 计算延迟,也就是每两个字之间延迟多久开始动画
    // 注意:表达式里面的依据是字符,也就说每个字符都是一个独立个体来计算轨迹
    // thisComp.frameDuration 代表合成中1帧的持续时间
    // inPoint的返回类型是数值,返回图层的入点(以秒为单位)。
    retard = textIndex * thisComp.frameDuration * 2;
    
    // t 代表每个字已经开始了多少时间,如果小于0,没开始,大于0就是已经开始
    // 值得注意的是,每个文字的开始时间是不同的!
    t = time - (inPoint + retard);
    startVal = [100,100,100];
    endVal = [0,0,0];
    
    // 判断当前时间线,如果在动画的时间,那么返回一个三维数组(三维数组的值全都是X) X 范围是 0-100,对应最终的百分比
    if (t < duration)
    {
    	// 如果 t < 0 表达式返回 [100,100,100] 如果 t > duration 表达式返回 [0,0,0]
    	// 如果 t = duration / 2 ; 表达式返回 [50,50,50],
    	// 如果 t = duration / 4 ; 表达式返回 [75,75,75],
    	// 总之就是 小学学过的 y = kx + b 的线性函数
    	linear(t,0,duration,startVal,endVal);
    }
    // 如果超出了动画时间,那么就要做一个震动,作为动画的结束,避免突兀
    else
    {
    	// amp 代表振幅
    	amp = (endVal - startVal)/duration;
    	
    	// 这句话就是小学物理,窝米噶 = 2派 除以 T; T = 1/f f 就是频率
    	w = freq*Math.PI*2;
      
      // 返回一个修正后的震动值,这个值我们后续再说:
    	endVal + amp*(Math.sin((t-duration)*w)/Math.exp(decay*(t-duration))/w);
    }
    
    • 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

    linear 函数相当于线性映射的工具,把一个从 [ m i n , m a x ] [min,max] [min,max]区间的数字映射到 [ s t a r t V a l , e n d V a l ] [startVal,endVal] [startVal,endVal]
    l i n e a r ( t , m i n , m a x , s t a r t V a l , e n d V a l ) = { s t a r t V a l , t ≤ 0 e n d V a l − s t a r t V a l m a x − m i n × ( t − m i n ) + s t a r t V a l , m i n < t < m a x e n d V a l , t ≥ m a x linear(t,min,max,startVal,endVal)= \left\{

    startVal,t0endValstartValmaxmin×(tmin)+startVal,min<t<maxendVal,tmax" role="presentation" style="position: relative;">startVal,t0endValstartValmaxmin×(tmin)+startVal,min<t<maxendVal,tmax
    \right. linear(t,min,max,startVal,endVal)= startVal,maxminendValstartVal×(tmin)+startVal,endVal,t0min<t<maxtmax
    如果说,表达式选择器的数量 这个值我们用 H ( t ) H(t) H(t) 表示,那么就是:
    w = 2 π T = 2 π f w=\frac{2\pi}{T}=2\pi f w=T2π=2πf

    如果你不理解表达式选择器的数量含义,请看这里:

    • 这个数量是一个0-1之间的值
    • 这个值用来修正运动
    • 以位置参数为例子:真实的位置参数 = 该图层在变换中的位置 + 偏移量(动画制作/表达式选择器中的位置值) * 表达式选择器里面的数量百分比值
    • 也就是说: x = x 0 + k Δ x ( 0 ≤ k ≤ 100 % ) x = x_0 + k\Delta x (0\leq k \leq 100\%) x=x0+kΔx(0k100%)
    • 在运动中,k可以从0变到1,也可以从1变到0,取决于运动设计者。

    H ( t ) = { 0 , t ≤ t 0 100 − 100 d u r a t i o n × ( t − t 0 ) , t 0 < t < d u r a t i o n − 100 d u r a t i o n × s i n [ w ( t − d u r a t i o n ) ] w × e d e c a y × ( t − d u r a t i o n ) , t ≥ d u r a t i o n H(t)= \left\{

    0,tt0100100duration×(tt0),t0<t<duration100duration×sin[w(tduration)]w×edecay×(tduration),tduration" role="presentation" style="position: relative;">0,tt0100100duration×(tt0),t0<t<duration100duration×sin[w(tduration)]w×edecay×(tduration),tduration
    \right. H(t)= 0,100duration100×(tt0),duration100×w×edecay×(tduration)sin[w(tduration)],tt0t0<t<durationtduration

    翻译成人话就是:

    • 动画还没开始前,这个表达式的值为100%
    • 动画开始,这个表达式的值线性的从 100 % 100\% 100%变化到 0 % 0\% 0%
    • 动画结束,这个表达式的值为【振幅指数级别减小】的正弦函数。

    这个函数巧妙的地方在于,它完美的让二阶导在临界值的时候保证了连续,我们不妨求导一下:

    H ′ ( t ) = { 0 , t ≤ t 0 − 100 d u r a t i o n , t 0 < t < d u r a t i o n − 100 d u r a t i o n × w × w ⋅ c o s [ w ( t − d u r a t i o n ) ] − s i n [ w ( t − d u r a t i o n ) ] d e c a y e d e c a y × ( t − d u r a t i o n ) , t ≥ d u r a t i o n H^{'}(t)= \left\{

    0,tt0100duration,t0<t<duration100duration×w×wcos[w(tduration)]sin[w(tduration)]decayedecay×(tduration),tduration" role="presentation">0,tt0100duration,t0<t<duration100duration×w×wcos[w(tduration)]sin[w(tduration)]decayedecay×(tduration),tduration
    \right. H(t)= 0,duration100,duration×w100×edecay×(tduration)wcos[w(tduration)]sin[w(tduration)]decay,tt0t0<t<durationtduration

    t = d u r a t i o n t=duration t=duration 的时候,你会发现第二行的表达式结果完全等于第三行的结果,也就是保证了运动的速度的连续性变化!

  • 相关阅读:
    算法基础之字符串哈希
    学习笔记 Golang 写入文件(io.WriteString、ioutil.WriteFile、file.Write、write.WriteString)
    链路负载均衡之DNS透明代理
    修改文字对齐方式,居中改为底部对齐
    跨界协作:借助gRPC实现Python数据分析能力的共享
    快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘IQueryable和IEnumerable
    Python百日进阶-WEB开发】Day152 - 前端基础 之 JQuery(一)
    Leetcode.树形DP
    SpringBoot-15-模块开发-页面国际化
    [论文笔记]SiameseNet
  • 原文地址:https://blog.csdn.net/weixin_51394621/article/details/127138381