”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 效果:Modulo操作员(%)

效果:Modulo操作员(%)

发布于2025-02-25
浏览:522

深入浅出After Effects表达式中的取模运算符(%)

取模运算符(%),也称为余数运算符,是表达式构建中一个非常有用的工具,但初学者可能不太容易理解。本文将解释其功能和用途。

% 用于计算一个等式的余数。例如:

10 % 3

此表达式返回 1,因为 10 除以 3 商为 3,余数为 1。

在处理时间变量时,这对于创建循环非常有用。

循环表达式

大多数刚接触 After Effects 表达式的设计师都熟悉 loopOut() 表达式。它允许我们使用 "cycle"(从开始循环到结束)、"pingpong"(从开始到结束再反向回到开始)、"offset"(重复关键帧但每次偏移值以构建动画)或 "continue"(使用最后一个关键帧的速度来继续运动)来循环关键帧属性。这非常全面,涵盖了关键帧动画所需的一切。

但是,如果要循环一个表达式,loopOut 就不是一个可行的解决方案。可能有很多原因不想使用关键帧,但主要原因是如果一个值需要动态更新,并且不断更新。更新附加到滑块的表达式比更新一组关键帧要容易得多。

如果运动是连续的,那么 Linear 或 Ease 就足够了。但对于需要循环的复杂动画,我们可以使用时间对取模运算符来实现该循环。

要了解其工作原理,请将以下表达式复制并粘贴到文本图层的“源文本”属性中:

Math.floor(time % 5)

您将看到图层每秒计数从 0 到 4,每隔 5 秒循环回 0。这是因为随着时间的推移,表达式的余数会每秒改变:

随时间变化的余数
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0
Math.floor 函数将参数舍入为整数。

After Effects: The Modulo Operator (%)

由此,很容易看出如何在需要在特定参数之间设置动画数字时使用它。

示例:数字时钟

让我们使用 % 来制作一个数字时钟。

秒数需要在 0 到 60 之间计数,而分钟需要在每 60 个间隔递增。让我们再次将此粘贴到文本图层的“源文本”属性中:

sec = Math.floor(time % 60);
minute = Math.floor(time / 60);

if (sec 

分解表达式,我们的 sec 变量将从 0 到 60 计数,而 minute 变量将在每 60 的倍数时递增(同样,我们使用 Math.floor 来舍入数字)。其后的 if 语句在 sec 变量小于 10 时在其前面添加一个 0,确保我们的秒变量始终具有两位数字(如果需要,也可以对分钟重复此操作)。然后,只需使用时间分隔符将其组合在一起即可。

After Effects: The Modulo Operator (%)

如果您需要计数器独立于时间工作,可以通过将时间替换为滑块并设置其值来实现相同的效果。

您还可以使用取模运算符和 After Effects 文本表达式选择器使时间分隔符闪烁。

转到文本图层,并向文本图层添加不透明度动画选项(如果您不确定如何操作,可以查看本文中关于此的所有内容)。然后添加表达式选择器,并删除范围选择器。

After Effects: The Modulo Operator (%)

将动画器中的不透明度设置为 0,然后将此表达式添加到“数量”属性:

//数字时钟分隔符闪烁 //添加到表达式选择器

minute = Math.floor(time / 60);

minute = 10 && textIndex == 3 ? Math.floor(time2 % 1.5) 100 : 0;

我编写了一个条件语句,基于分钟变量中的位数不固定。首先,我从源文本属性复制分钟变量。然后,我用它来计算时间分隔符的 textIndex 值。当分钟显示中只有一位数字时,它将等于 2。当分钟显示超过 10 时,它将为 3。条件语句也可以写成 if 语句,如下所示,以进一步解释它在做什么:

if (minute = 10 && textIndex == 3) Math.floor(time2 % 1.5) 100 else 0

如果分钟小于 10 且 textIndex 等于 2,则 Math.floor(time2 % 1.5) 100 会影响文本图层中的第二个字符。这将使字母闪烁(开/关比例为 2:1),这要归功于取模运算符。Math.floor 函数舍入数字,而整个表达式最后乘以 100 以在 0 和 100 之间切换,这是表达式选择器的范围。

但是,如果分钟等于或大于 10 且 textIndex 等于 3,则该效果将应用于文本图层中的第三个字符。这解释了分钟显示中的额外数字。如果您的分钟显示需要超过 99,则需要添加另一个参数来影响时间分隔符在第四个位置时的显示。

但是,如果您的分钟显示设置为恒定的位数,则该语句将变得简单得多:

dividerIndex = 3; textIndex == dividerIndex ? Math.floor(time2 % 1.5) 100 : 0

After Effects: The Modulo Operator (%)

就这样,你得到了一个数字时钟!

在显示取模运算符如何帮助创建循环之后,我们现在可以考虑如何将其应用于其他属性。

示例:模拟时钟

现在让我们制作一个模拟时钟。当指针滴答作响时,它通常不是一个连续的运动,而是一个突然停止和启动的运动。这就是取模运算符可以帮助解决的循环类型。

让我们来看一下可以粘贴到时钟指针图层旋转属性中的以下表达式:

//秒针旋转 frames = thisComp.frameDuration;

loopTime = 1; dur = frames * 6; strength = 6;

counter = Math.floor(time/loopTime); t = time % loopTime;

ease(t, 0, dur, strength counter, strength (counter 1))

首先,我们设置一些变量。frames 是合成中一帧的持续时间,使其能够跨多个帧速率工作。

将 loopTime 设置为您想要循环的时间。我希望循环持续一秒钟,所以我将其设置为 1。dur 是循环内动画的持续时间,所以我将其设置为 frames * 6,使其持续 6 帧。strength 是动画值的改变,因为我正在设置时钟指针动画,所以我将其设置为 6,因此时钟指针将在 60 次滴答声中完成一次旋转。

接下来,我创建一个 counter 变量,它将帮助偏移我的值。我使用 Math.floor(time/loopTime) 创建它,使用 Math.floor 舍入数字并将计数器的速度设置为与循环匹配。最后,t 是我们可以用来为表达式驱动的动画计时的一个变量。这是 time % loopTime,因此当时间达到 loopTime 中存储的数字时,时间就会循环。

之后,我们可以制作动画。在此示例中,我使用 ease 表达式。通过将第一个参数设置为 t,我们将旋转值重新映射到我们的循环时间变量。接下来的两个参数是 0 和 dur,即动画的起点和终点。最后两个参数是 strength counter 和 strength (counter 1),即旋转属性的值。通过将 strength 乘以 counter,我们可以偏移每个循环的值,在 strength * (counter 1) 结束,准备下一个循环。

After Effects: The Modulo Operator (%)

在这种情况下,通过表达式而不是关键帧来驱动运动的优点是,如果您需要为不断变化的时间构建时钟模板。表达式的静态值可以连接到滑块,从而更容易不断更新。

您可以使用更高级的表达式或构建自己的函数来制作更定制的动画:

//秒针旋转 frames = thisComp.frameDuration;

loopTime = 1; dur = frames * 6; change = 6;

counter = Math.floor(time/loopTime); t = time % loopTime;

function easeInOutBack (t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t/=d/2) (tt(((s=(1.525)) 1)t - s)) b; return c/2((t-=2)t(((s=(1.525)) 1)t s) 2) b; }

easeInOutBack(t, 0, change, dur, 1.70158)

After Effects: The Modulo Operator (%)

最后,您可以创建一个变量来设置起始值,并使用 if 语句跳过分针(可能还有时针)动画的第一次迭代:

//分针旋转 frames = thisComp.frameDuration;

loopTime = 60; dur = frames * 6; strength = 6; startValue = 180;

counter = Math.floor(time/loopTime); t = time % loopTime;

function easeInOutBack (t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t/=d/2) (tt(((s=(1.525)) 1)t - s)) b; return c/2((t-=2)t(((s=(1.525)) 1)t s) 2) b; }

if (counter > 0) { easeInOutBack(t, startValue strength * counter, strength, dur, 1.70158) } else { startValue }

After Effects: The Modulo Operator (%)

从这里开始,只需将滑块连接到我们的 startValue 变量即可。这样,您就拥有了一个可以通过简单更改滑块中的值来更新的模拟时钟。

结论

取模运算符对于创建循环以辅助动态表达式非常有用,而其他方法不适合项目的需要。

尝试在您自己的项目中测试它!

有任何意见?有什么不清楚的地方?请在下方留言。

最新教程 更多>
  • 我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    将我的加密库从mcrypt升级到openssl 问题:是否可以将我的加密库从McRypt升级到OpenSSL?如果是这样,如何?答案:是的,可以将您的Encryption库从McRypt升级到OpenSSL。可以使用openssl。附加说明: [openssl_decrypt()函数要求iv参...
    编程 发布于2025-03-03
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-03-03
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    删除匿名事件侦听器将匿名事件侦听器添加到元素中会提供灵活性和简单性,但是当要删除它们时,可以构成挑战,而无需替换元素本身就可以替换一个问题。 element? element.addeventlistener(event,function(){/在这里工作/},false); 要解决此问题,请考虑...
    编程 发布于2025-03-03
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-03-03
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-03-03
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-03-03
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。$("#map").css({ marginT...
    编程 发布于2025-03-03
  • 如何检查对象是否具有Python中的特定属性?
    如何检查对象是否具有Python中的特定属性?
    方法来确定对象属性存在寻求一种方法来验证对象中特定属性的存在。考虑以下示例,其中尝试访问不确定属性会引起错误: >>> a = someClass() >>> A.property Trackback(最近的最新电话): 文件“ ”,第1行, AttributeError: SomeClass...
    编程 发布于2025-03-03
  • 如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    How to Resolve "General error: 2006 MySQL server has gone away" While Inserting RecordsIntroduction:Inserting data into a MySQL database can...
    编程 发布于2025-03-03
  • Java是否允许多种返回类型:仔细研究通用方法?
    Java是否允许多种返回类型:仔细研究通用方法?
    在Java中的多个返回类型:一种误解类型:在Java编程中揭示,在Java编程中,Peculiar方法签名可能会出现,可能会出现,使开发人员陷入困境,使开发人员陷入困境。 getResult(string s); ,其中foo是自定义类。该方法声明似乎拥有两种返回类型:列表和E。但这确实是如此吗...
    编程 发布于2025-03-03
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-03-03
  • \“(1)vs.(;;):编译器优化是否消除了性能差异?\”
    \“(1)vs.(;;):编译器优化是否消除了性能差异?\”
    答案: 在大多数现代编译器中,while(1)和(1)和(;;)之间没有性能差异。编译器: perl: 1 输入 - > 2 2 NextState(Main 2 -E:1)V-> 3 9 Leaveloop VK/2-> A 3 toterloop(next-> 8 last-> 9 ...
    编程 发布于2025-03-03
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    编程 发布于2025-03-03
  • 大批
    大批
    [2 数组是对象,因此它们在JS中也具有方法。 切片(开始):在新数组中提取部分数组,而无需突变原始数组。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    编程 发布于2025-03-03
  • 如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    从python import codecs import codecs import codecs 导入 text = codecs.decode('这狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#带有...
    编程 发布于2025-03-03

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3