JavaScript Layers
JavaScript 可用于多种 Layers,包括 JavaScript Utility、JavaScript Shape、JavaScript Deformer、JavaScript Emitter、JavaScript Modifier 和 JavaScript Emitter,以在 Cavalry 中设置多种 Attribute 类型。
可以通过表达式写入的主要数据类型有:
| 名称 | attrType | 描述 |
|---|---|---|
| Double | double | 带有小数位的数字。例如 4.153。 |
| Double2 | double2 | 一组两个 double。例如 Position 103.453, 487.543。 |
| Double3 | double3 | 一组三个 double。例如 Position (2.5D) 103.453, 487.543, 50.730。 |
| Int | int | 不带小数点的整数。例如 4。 |
| Int2 | int2 | 一组两个整数。例如 Composition Resolution 1920, 1080。 |
| Bool | bool | 具有两种状态的复选框——1 或 0(开/关)。 |
| String | string | 可包含字母数字字符和符号。 |
| Color | color | 包含 R、G、B 和 A 值的 Attribute。 |
| Point Data | pointData | 由 Distributions 生成的点。参见 Using Point data。 |
| Asset | assetId | 接受 .json、.txt 或 .csv Asset。参见 Using Assets。 |
| Layer | layerId | 接受任何 Layer。参见 Using Layer data。 |
这意味着支持 JavaScript 的 Layers 可以连接到 Cavalry 中的上述任何数据类型。
连接两个不兼容的数据类型(例如表达式返回 int,但 JavaScript 连接到 string),将触发尝试自动转换数据类型,但强烈建议正确匹配输出类型,以便更好地控制浮点精度等因素。
以上所有类型也可作为输入,并可通过脚本中的 Attribute 名称引用。要添加另一个 Attribute 作为变量,请点击 UI 底部的 + 按钮并选择相关数据类型。然后可以从具有匹配数据类型的另一个 Attribute 建立输入连接。默认情况下,变量名是字母 n 后跟数字,例如 n0、n1。但是,可以通过右键点击 Attribute 并选择 Rename 来重命名。
变量名区分大小写,不能包含空格。
JavaScript 导入一个 Context Module,其中包含几个与 Duplicator 配合使用的有用成员。
ctx.index- Duplicator 的 Index。ctx.count- Duplicator 的 Count。ctx.positionX/ctx.positionY- Duplicator 点的位置。ctx.layerId- 请求 JavaScript Layer 进行计算的 Layer 的 id。ctx.attributeId- 请求 JavaScript Layer 进行计算的 Attribute 的 id。
有关使用这些值的示例,请参阅 Create > Demo Scenes > JavaScript > Position to Color 预设。
复杂数据类型(color、int2、double2)是遵循以下模式的简单 JavaScript 对象:
let color = { r: 200, g: 100, b: 50, a: 255};let someDouble2 = { x: 200.4, y: 55.6};为简单起见,可以修改或返回输入值。
使用此 Layer 编写 JavaScript 表达式的主要规则是必须返回一个值。例如,以下表达式调用一个函数,该函数返回一个值:
function toCelsius(fahrenheit) { return (5/9) * (fahrenheit-32);}toCelsius(n0);在全局级别设置变量时,请使用 var 而非 let/const。因为 JavaScript Layers 每帧运行,使用 let/const 全局声明将在表达式第二次运行时失败,因为变量已存在且无法重新赋值。
Using Assets
标题为“Using Assets”的章节JavaScript 可以利用 JSON/Text/CSV Assets(CSV Asset 包括 Google Sheets 和 Microsoft Excel)。要与 JavaScript Layers 一起使用这些 Asset 类型,请点击 + 按钮并选择 Add Text/JSON/CSV Asset。这将创建一个新的 Attribute,它可以接收受支持的 Asset 作为输入。
- Text Assets 将作为字符串加载。
- JSON Assets 将作为 JSON 对象字面量加载。
- CSV Assets 将作为 JSON 对象字面量加载。
- 顶层 Object 属性都将与列名匹配。
- 每列包含:
rows- 行数据数组(数字或字符串)。min- 列中的最小数值(如果列为数字)。max- 列中的最大数值(如果列为数字)。
// 打印连接到 Attribute 'n1' 的 CSV 的所有列名。var columns = Object.keys(n1);for (var columnName of columns) { console.log(columnName);}// 返回连接到 Attribute 'n1' 的 CSV/Google Sheet 中标题为 'Cavalry' 的列的最大值。n1.Cavalry.max;// 如果列标题包含空格,例如 'Cavalry Users'。n1["Cavalry Users"].min;// 返回连接到 Attribute 'n1' 的 CSV/Google Sheet 中标题为 'Cavalry Users' 的列的所有值的总和。function setSum() { let total = 0; for (let row of n1["Cavalry Users"].rows) { total += Number(row) } return total;}setSum();// 给定一个连接到 Attribute 'n1' 的 JSON asset,输出 "title" 键的值。// 将 JavaScript Utility 连接到 Text Shape 的 String。/* example.json 的内容{ "data": { "title": "My Title", "body": "This is some body text." }}*/n1.data.title请注意,作为 Asset 使用时,仅支持 Excel 文件的第一个标签页。
Using Point data
标题为“Using Point data”的章节- 创建一个 JavaScript Deformer。
- 点击其 Attribute Editor UI 底部的
+按钮,添加选择 ‘Add Point Data’ 以添加新的 Dynamic Attribute。 - 创建一个 Duplicator。
- 右键点击 Distribution Attribute 并选择
Reveal Generator。 - 删除 Duplicator(保留 Grid Distribution)。
- 连接 gridDistribution.id→javaScriptDeformer.n1(这是在步骤 2 中添加的新 Point Data Attribute)。
- 将 JavaScript 输入中的代码替换为以下之一:
console.log(n1.points[0].position.x);或;console.log(n1.points.length);
- 创建一个 Shape。
- 连接 javaScriptDeformer.id→shape.deformers。这是 JavaScript Deformer 进行计算所必需的。
将播放头步进到下一帧以将值打印到 JavaScript Console。第一个示例将输出第一个 pointId 的 position.x(更改 [0] 中的值以返回其他 pointId),而第二个示例将返回 Distribution 中的点数(默认 3x3 网格为 9 个)。
Using Layer data
标题为“Using Layer data”的章节连接的 Layer 的类型决定了可用的对象:
- Drawable(例如 Null、Falloff)- 将提供一个 layer 对象,包含以下 2D World Space Transform 变量:
- position(例如
n1.layer.position、n1.layer.position.x) - rotation(例如
n1.layer.rotation、n1.layer.rotation.z) - scale(例如
n1.layer.scale、n1.layer.scale.x)
- position(例如
- Shape(例如 Rectangle、Duplicator)- 将提供一个
mesh属性(例如n1.mesh),表示 local space 中的 mesh 层级。mesh属性是来自 Cavalry Module 的 Mesh class 的实例。
使用 Layer 动态输入时,使用 hasInput 来确定是否连接了 Layer。例如,这可用于防止尝试读取不存在的 mesh 数据。
// 假设 'n1' 是一个 Layer 动态输入。console.log(n1.hasInput);// 如果 Layer 连接到 'n1',则返回 true。JavaScript 不区分 2D 和 2.5D Layers,因此对 2D Layers 使用 rotation.z。
// Closest Point on Path 示例。// 将其粘贴到 JavaScript Editor 中,然后点击 'Run Script'。// 创建一个 Null 和两个 Shapesconst nullId = api.create("null", "Move Me!!");const ellipse1Id = api.primitive("ellipse", "Ellipse");const ellipse2Id = api.primitive("ellipse", "Path");api.setFill(ellipse2Id, false);api.setStroke(ellipse2Id, true);api.set(ellipse2Id, {"generator.radius": [350,350]});// 创建一个 JavaScript Utility。const jsUtil = api.create("javaScript");// 添加动态 Attributes 和表达式。api.addDynamic(jsUtil, "array", "layerId");api.addDynamic(jsUtil, "array", "layerId");const expression = 'function getPoint() {\n\xa0\xa0\xa0\xa0let toPt = n2.layer.position;\n\xa0\xa0\xa0\xa0let closestPoint = n1.path.findClosestPoint(toPt.x, toPt.y);\n\xa0\xa0\xa0\xa0return closestPoint.position;\n};\ngetPoint();'api.set(jsUtil, {"expression": expression});// 建立连接。api.connect(ellipse2Id, "id", jsUtil, "array.1");api.connect(nullId, "id", jsUtil, "array.2");api.connect(jsUtil, "id", ellipse1Id, "position");Output dependent calculations
标题为“Output dependent calculations”的章节JavaScript Layers 是 Cavalry 中唯一知道具体是哪个 Layer 和 Attribute 触发计算的地方。此信息可用于根据正在计算哪个连接来输出不同的值。使用 ctx.layerId 和 ctx.attributeId 属性来访问此信息。
// 在此示例中,假设一个 JSON Asset 连接到 JavaScript Layer 的 n1 Attribute。function getText() { if (ctx.layerId == "textShape#1") { // 如果 textShape#1 向 JavaScript 请求值,返回给定的 JSON 值 return n1["colors"]["Green"]; } else if (ctx.layerId == "textShape#2") { // 如果 textShape#2 向 JavaScript 请求值,返回不同的 JSON 值 return n1["colors"]["Yellow"]; } return "None";}getText();表达式的错误将打印到 JavaScript Console。
通过 Cmd/Ctrl + Return 运行表达式时,需要输出连接才能使表达式运行。