几何与高阶用法 | HQ VISU Designer

几何行为不是动画特效面板,而是把输入值映射成位置、角度和尺寸变化的规则系统。先理解“输入范围 -> 百分比 -> 几何结果”这个核心思路,参数含义会更容易判断。

Move / Rotate / Scale高阶配置含两身位示例
几何

使用前说明

几何行为不是动画特效面板,而是把输入值映射成位置、角度和尺寸变化的规则系统。先理解“输入范围 -> 百分比 -> 几何结果”这个核心思路,参数含义会更容易判断。

几何 最重要的心智模型

几何行为最简单的理解方式是:先把输入值归一化成一个百分比,再把这个百分比映射成位移、角度或缩放比例。因此应重点确认输入范围和输出范围。

几何 先分清哪三类动作

Move 负责沿单一轴向移动;Rotate 负责按角度旋转;Scale 负责按比例改尺寸。如果需求本质上是位移,就不要勉强用缩放表达;如果本质上是旋转,就不要靠很多后置脚本去模拟。

几何 阅读重点

位移配置优先阅读 Move 部分;旋转中心优先阅读 Rotate 部分;固定边和增长方向优先阅读 Scale 部分。

Move

Move:先定输入范围,再定输出位移

Move 最适合做单轴位移,例如滑块、液位块、进度指示块、行程位置和水平或垂直移动对象。

Move 关键字段说明

Input Value 是当前输入;Input Min / Input Max 是原始输入范围;Clamp Min / Clamp Max 是真正用于归一化的有效输入范围;Offset Min / Offset Max 是最终位移距离;Direction 负责决定走水平还是垂直方向。

  • 先确认输入值可能落在哪个区间
  • 再确认 0% 和 100% 分别对应移动距离
  • 最后确定方向是 Horizontal 还是 Vertical
移动一个身位:直接用 shape.width 或 shape.height

如果“一个身位”指对象自身一个宽度或一个高度,最直接的写法就是把 Offset Max 写成 shape.width 或 shape.height。这样即使对象尺寸后来变了,位移规则仍然跟着对象自身尺寸走。

  • 水平一个身位:shape.width
  • 垂直一个身位:shape.height
  • 向左或向上移动时加负号
Offset Min = 0
Offset Max = shape.width
Direction = Horizontal
移动两个身位:直接写 shape.width * 2

如果要让对象最多移动两个自身宽度,可将 Offset Max 设置为 shape.width * 2。向左两个身位使用 -shape.width * 2;垂直两个身位对应 shape.height * 2。这种写法能随对象尺寸变化保持一致,维护成本较低。

  • 向右两个身位:shape.width * 2
  • 向左两个身位:-shape.width * 2
  • 向下两个身位:shape.height * 2
  • 向上两个身位:-shape.height * 2
Offset Min = 0
Offset Max = shape.width * 2
Direction = Horizontal
负方向移动和半身位移动

Move 不只支持整身位。可使用 -shape.width、shape.width * 0.5、shape.height * 1.5 这类表达式。一身位、两身位、半身位、反向两身位,本质上都属于表达式配置问题。

模板变量参与表达式的判断规则

Move、Rotate、Scale 这类几何字段按 JavaScript 表达式规则填写。模板变量用于字符串时必须加引号;用于数值、布尔或计算表达式时,替换后的内容也必须符合该字段的结果类型。未加引号的 `<变量>` 不作为正式写法。

  • 字符串值:'<TITLE>' 或 "<TITLE>"
  • 数值表达式:120、shape.width * 2
  • 布尔表达式:running === true
  • 不要把字符串模板变量填入需要数值结果的字段
超限时要不要隐藏

如果输入值超出有效范围后,这个对象应该直接消失,就打开 Hide if value exceeds limits;如果超限后对象仍应停在边界位置,只是描边提示异常,则不要简单隐藏,而是更适合结合 Quality Border 或后置脚本提示。

Move 几何行为
Move 行为

Move 的核心是把输入区间映射成位移区间,而不是手写一个固定像素偏移。

Rotate

Rotate:真正关键的是旋转中心和最大角度

Rotate 适合指针、阀门、风机、方向件等本质上要按角度表达的对象。多数 Rotate 配不好,问题都不是角度本身,而是 pivot 选错了。

Current Angle 和 Max Rotation 配置

Current Angle 决定当前实际角度,Max Rotation 决定允许的最大旋转范围。推荐先确认源数据已经是角度值,还是需要换算后再使用。如果源数据本身就是角度值,不应再重复乘以角度系数。

Pivot 选错,旋转看起来就会飘

Pivot 决定对象绕哪个点转。中心旋转最适合风机、马达类;顶部或底部旋转更适合指针、杆件;左侧或右侧旋转更适合铰接对象。看起来“旋转轨迹不对”的问题,往往优先不是角度错,而是 pivot 选错。

Top / Bottom / Left / Right 的配置场景

当真实机械中心不在对象几何中心时,就不要默认 Centre。比如指针底部固定、末端摆动,就更适合 Bottom;门板左侧铰接,就更适合 Left。

旋转超限处理

如果超出 Max Rotation 后就不应该再显示,可以打开 Hide if value exceeds limits;如果超限后仍想保留对象,但用边框提示异常,就更适合打开 Quality Border 并配好好坏颜色。

Rotate 几何行为
Rotate 行为

Rotate 里最值得仔细思考的通常不是角度本身,而是 Pivot。

Scale

Scale:决定从哪一边长出来,比决定放大多少更重要

Scale 最适合液位、进度条、增长条、充满效果和强调类大小变化。它不是简单把对象放大,而是有一个固定边和一个变化边。

Scale Min / Scale Max 说明

Scale Min / Scale Max 决定对象在输入最小值和最大值时的缩放系数。例如 0.5 表示缩到原来的一半,1.0 表示原样,1.5 表示放大到 1.5 倍。它不是像 Move 那样直接填距离,而是填比例。

Anchor Edge 决定哪一边固定

如果 Anchor Edge = Right,表示右边固定、对象朝左边或远离右边的方向变化;如果 Anchor Edge = Bottom,表示底边固定、对象朝上或远离底边方向变化。这个思路特别适合液位条和增长条。

  • Left:左边固定
  • Right:右边固定
  • Top:顶边固定
  • Bottom:底边固定
Scale 与 Move 的选择边界

表达“长度变长或变短”时,优先用 Scale;表达“整个对象在页面上平移”时,优先用 Move。很多页面表达不清,是因为本应缩放的对象被配置成平移,或本应平移的对象被配置成缩放。

Scale 的高阶写法

当对象尺寸本身也要被脚本感知时,Scale 很适合配合 Post Operations 使用。运行时会暴露 scaleFactor、width、height 等后置变量,用于在缩放之后做轻量样式跟进。

Scale 几何行为
Scale 行为

Scale 的关键不是“变大变小”,而是“哪一边固定、哪一边变化”。

高级

Post Operations:能做轻量跟进,但不要拿它重写主逻辑

Post Operations 是几何行为执行后的后置脚本区。它好用,但有边界。用好了是增强,用不好会把几何规则变得很乱。

适合做什么

适合做轻量跟进,例如根据最终位置改变一个颜色、记录一次当前缩放值、根据当前角度切换一个状态类名。这类逻辑属于“几何完成后再补一点点”。

不适合做什么

不适合在 Post Operations 里再手工做第二次 Move、Rotate 或 Scale。也不适合把主要业务计算都塞到这里。它应该是后置补充,不应该取代主几何规则。

后置脚本里常见可用变量

当前运行时会给后置脚本准备一些别名,例如 pivotX、pivotY、scaleFactor、offsetX、offsetY、currentAngle、maxAngle。后置脚本可以拿到本次几何行为已经算出的关键结果。

推荐实践

主逻辑尽量写在几何行为主字段中,后置脚本只做补充。这样后续维护人员可以先从主字段理解位移、旋转或缩放的来源。

脚本

脚本方式改布局:直接调用 qtedit.setComponentLayout()

如果目标位置或目标尺寸已经明确,且这种变化难以通过固定几何行为表达,可以使用脚本直接调整布局。

脚本布局的优先场景

当布局变化依赖多个输入、多个模板值或复杂条件组合时,脚本通常比堆叠大量几何参数更清晰。联动多个对象一起变化时,qtedit.setComponentLayout() 会更直接。

适合什么高阶场景

拖动结果回写、对象成组平移、根据用户输入重新布置面板、根据模板值动态调整弹窗位置,这些都适合脚本方式。

最简单的脚本布局例子

先取当前组件数据,再按业务规则计算新位置,最后回写需要调整的字段。这样脚本逻辑更容易理解。

var data = qtedit.getComponentData("Rectangle 1");
if (data) {
  qtedit.setComponentLayout("Rectangle 1", {
    x: data.x + data.width * 2,
    y: data.y,
    angle: data.rotation || 0
  });
}
范围动画与几何映射
范围映射

输入范围映射到几何范围时,先把逻辑想清楚,再决定用几何行为还是脚本布局。