动画是状态表达的放大器,不是状态表达本身。先把状态、颜色、文本和交互讲清楚,再决定哪些位置确实需要动态表达。
动画功能详解 | HQ VISU Designer
工业页面中的动画用于强化状态识别、运动方向和异常提示。动画是否需要配置,应根据它能否帮助用户更快理解设备状态、位置变化或风险信息来判断。
Before Use
工业页面中的动画用于强化状态识别、运动方向和异常提示。动画是否需要配置,应根据它能否帮助用户更快理解设备状态、位置变化或风险信息来判断。
运动方向、液位变化、指针变化、设备旋转和报警提醒最适合使用动画。这类信息只靠静态图形时识别效率较低,动态表达可以帮助用户更快理解当前状态。
当动画过多、对象持续变化,或仅为了视觉效果而增加动画时,页面重点会被削弱,用户更难识别关键状态。
动画字段支持哪些写法
动画字段分成数值表达式、布尔表达式、颜色值和模板变量。先分清字段类型,再填写表达式,后面的参数才容易稳定。
Move、Rotate、Scale 的输入值、位移、角度和缩放比例都可以写数值表达式。表达式必须能立即算出数字,不能直接放入异步请求。
- 固定数值:120
- Tag 数值:ReadTagDouble("<device-code>.<tag-code>", 0)
- 对象尺寸:shape.width、shape.height
- 计算表达式:shape.width * 2、shape.height * 0.5
ReadTagDouble("<device-code>.<tag-code>", 0)
shape.width
shape.height * 0.5 Definition 是当前行为的准备区,适合读取 Tag、定义变量、计算中间值和准备函数。真正决定结果的是后面的 Condition、Value、Text、Fill、Stroke、Visibility、Offset、Angle 或 Scale 字段。Definition 中只声明变量但最终字段没有引用时,页面显示不会变化。
- Definition:准备变量和函数
- Condition / Enabled:返回布尔值
- Text / Fill / Stroke:返回字符串
- Input Value / Angle / Offset / Scale:返回数字
- Visibility:返回布尔值
// Definition
var running = ReadTagBoolean("<device-code>.<run-tag>", false);
var color = running ? "#22C55E" : "#64748B";
// Fill
color Blink、Active、Enabled 和超限控制类字段通常需要布尔结果。建议写明确比较,不要只写一个含义不清的变量。
- 二值 Tag:ReadTagBoolean("<device-code>.<tag-code>", false)
- 状态码比较:state === 1
- 组合条件:running === true && alarm === false
var running = ReadTagBoolean("<device-code>.<run-tag>", false);
var alarm = ReadTagBoolean("<device-code>.<alarm-tag>", false);
running === true && alarm === false 颜色字段使用十六进制颜色值。普通颜色行为通常通过颜色选择器维护;Script Color 的 Fill 和 Stroke 可以返回颜色字符串。
- 固定颜色:"#22C55E"
- 脚本颜色:state === 1 ? "#22C55E" : "#EF4444"
- 模板颜色:"<FILL_COLOR>"
var state = ReadTagInteger("<device-code>.<state-tag>", 0);
state === 1 ? "#22C55E" : "#EF4444" 填写动画字段前,应先确认该字段需要的结果类型。Condition、Enabled、Active 和 Visibility 返回布尔值;Input Value、Offset、Angle、Scale、Limit、Clamp 返回数字;Fill、Stroke、Text 返回字符串;模板变量参与表达式时,应按字符串处理。字段类型明确后,后续排查会更直接。
- 布尔值:Condition、Enabled、Active、Visibility
- 数字:Input Value、Offset、Angle、Scale、Limit、Clamp
- 字符串:Fill、Stroke、Text
- 模板变量:在表达式中作为字符串使用
// Active
ReadTagBoolean("<PLC>.<RUN_TAG>", false)
// Offset Max
shape.width * 2
// Fill
ReadTagBoolean("<PLC>.<ALARM_TAG>", false) ? "#dc2626" : "#16a34a" 模板变量格式为 <NAME>,变量名以字母或下划线开头。模板变量放入脚本表达式时,应写在字符串里。
- Tag 字符串:"<PLC>.<RUN_TAG>"
- 颜色字符串:"<FILL_COLOR>"
- 模板变量参与 JavaScript 表达式时应放入字符串
ReadTagBoolean("<PLC>.<RUN_TAG>", false) 多个页面都要使用的换算函数、格式化函数、颜色规则和项目级常量,可以放在 Global Script。当前页面独有的 Tag 名称、表格数据、弹窗范围和运行时状态仍应放在 Page Script,避免跨页面内容相互依赖。
- 项目级换算:formatPressure(value)
- 项目级颜色:getStateColor(state)
- 项目级常量:const QUALITY_BAD_COLOR = "#EF4444"
- 页面独有内容仍放 Page Script
当前页 Page Script 顶层声明的 var、let、const 和 function 可以被当前页动画字段引用。适合把量程、偏移量、Tag 名称和换算函数放在这里,再让 Move、Rotate、Scale、Script Color、Condition 等字段直接引用。
- 顶层变量:const levelMax = 100
- 顶层 Tag 名称:var levelTag = "<device-code>.<level-tag>"
- 顶层函数:function readLevel() { ... }
- 动画字段:readLevel() 或 levelMax
const levelMax = 100;
var levelTag = "<device-code>.<level-tag>";
function readLevel() {
return ReadTagDouble(levelTag, 0);
}
// Scale / Input Value
readLevel()
// Scale / Input Max
levelMax window.qteditPageReady 会在页面运行时准备完成后执行,适合做组件初始化、文本设置、显示控制和运行后刷新。用于初始动画计算的值,应优先放在 Page Script 或 Global Script 顶层。
- 初始动画值优先引用顶层变量或函数
- ready 回调适合调用 qtedit.setComponentText 等运行时方法
- 回调内更新状态后需要驱动行为时,可写入运行时变量并刷新视图
var pumpVisible = true;
window.qteditPageReady = function() {
qtedit.writeVariable("pumpVisible", pumpVisible);
qtedit.refreshView();
}; 读取整数 Tag 的单个位时,在完整 Tag 点名后使用 [0] 到 [31] 的位序号,通用写法是 `TAG[bit]`,例如 `Device.TAG[0]` 或 `<device-code>.<tag-code>[1]`。写入单个位时使用 Write Tag Bit,目标 Tag 填父整数 Tag,位号填写在 Bit Index 中。
- 读取位语法:`TAG[bit]`
- 读取位:ReadTagBoolean("<device-code>.<tag-code>[1]", false)
- 写位目标:"<device-code>.<tag-code>"
- Bit Index:0 到 31
- Bit Action:Set、Reset、Toggle
ReadTagBoolean("<device-code>.<tag-code>[1]", false) 表达式字段需要同步返回结果,不适合直接放 fetch、Promise 或定时器。需要异步读取外部数据时,应放在 Page Script 或 qteditPageReady 中处理,再把结果写入运行时变量或内部 JSON Tag,动画字段只读取已经准备好的结果。
- 表达式字段:立即返回值
- Page Script / qteditPageReady:处理异步准备
- 动画字段:读取变量、Tag 或函数结果
- 外部数据建议由 HQControl 接口或脚本层整理后再进入页面
`Active` 或 `Enabled` 用于决定行为当前是否参与计算;Quality Border 用于表达数据质量 GOOD / BAD。二者职责不同:Active 控制行为是否启用,Quality Border 告诉用户当前数据是否可信。需要在质量异常时隐藏对象,可结合 `Hide when quality BAD` 使用。
- Active / Enabled:控制行为是否启用
- Quality Border:表达数据质量
- Hide when quality BAD:质量异常时隐藏对象
- 业务状态仍应由实际 Tag 或状态规则表达
var enabled = ReadTagBoolean("<PLC>.<ENABLE_TAG>", false);
var qualityGood = ReadTagQualityGood("<PLC>.<VALUE_TAG>");
// Active
enabled && qualityGood Move:用数值映射对象位移
Move 把一个输入值换算成一个方向上的位移。它适合对象整体移动,不适合对象自身变长或缩短。
Move 读取一个数值,把这个数值按输入范围换算成百分比,再把百分比映射到 Offset Min 和 Offset Max 之间,最终让对象沿水平或垂直方向移动。
- 0% 对应 Offset Min
- 100% 对应 Offset Max
- 中间值按比例移动
Input Value 是来源值;Input Min / Input Max 是来源值范围;Clamp Min / Clamp Max 是参与换算的范围;Offset Min / Offset Max 是实际位移距离;Direction 决定水平或垂直。
- Input Value:数值表达式
- Input Min / Input Max:来源范围
- Clamp Min / Clamp Max:换算范围
- Offset Min / Offset Max:实际移动距离
- Direction:Horizontal 或 Vertical
Input Min / Input Max 描述正常来源范围;Clamp Min / Clamp Max 描述参与换算的限制范围。通常二者相同。需要允许来源值超出正常范围但限制画面移动距离时,再单独调整 Clamp。
- 正常场景:Input Min / Max 与 Clamp Min / Max 保持一致
- 来源值可超限但画面不继续移动:Clamp 限制位移
- 需要超限隐藏时,开启 Hide if value exceeds limits
Offset 不是百分比,而是画布距离。可以写固定数字,也可以使用当前对象尺寸。
- 向右移动一个对象宽度:shape.width
- 向左移动一个对象宽度:-shape.width
- 向下移动半个对象高度:shape.height * 0.5
- 向上移动两个对象高度:-shape.height * 2
Input Value = ReadTagDouble("<device-code>.<position-tag>", 0)
Input Min = 0
Input Max = 100
Offset Min = 0
Offset Max = shape.width
Direction = Horizontal 先确定来源 Tag 和量程,再确定移动方向,最后填写 Offset。配置完成后,再决定是否开启超限隐藏和质量边框。
- 第一步:确认输入值和量程
- 第二步:选择 Horizontal 或 Vertical
- 第三步:填写 Offset Min / Offset Max
- 第四步:按需要开启 Hide if value exceeds limits
- 第五步:按需要开启 Quality Border
滑块、行程、位置指示适合 Move。液位柱、进度条和填充条通常不应使用 Move,因为它们表达的是长度变化,应使用 Scale。
Rotate:用角度表达方向和旋转
Rotate 根据角度值旋转对象。真正关键的是 Pivot,也就是对象围绕哪个位置旋转。
Rotate 读取当前角度,把对象围绕指定 Pivot 旋转。它适合风机、指针、阀门和方向件。
- Current Angle 决定当前角度
- Max Rotation 限制最大角度
- Pivot 决定旋转中心
Current Angle 填角度表达式;Max Rotation 填最大旋转角度;Pivot 选择旋转中心。需要偏移中心时使用相关 X / Y 字段。
- Current Angle:角度值或角度表达式
- Max Rotation:90、180、360 等最大角度
- Pivot:Centre、Top、Bottom、Left、Right
Rotate 负责角度或旋转表达,不负责判断设备是否处于运行状态。风机、指针和阀门常见做法是:Rotate 表达方向或角度,State Color 表达运行、停止、报警或手自动状态。
- 角度来源:Current Angle
- 运行状态:State Color 或 Multi-State Color
- 数据质量:Quality Border
角度字段可以直接读取 Tag,也可以根据百分比换算成角度。
- 直接角度:ReadTagDouble("<device-code>.<angle-tag>", 0)
- 百分比换算:ReadTagDouble("<device-code>.<speed-tag>", 0) * 3.6
- 读取原始角度:shape.rotation
Current Angle = ReadTagDouble("<device-code>.<angle-tag>", 0)
Max Rotation = 360
Pivot = Centre 先确认对象的机械中心,再选择 Pivot。对象中心选错时,即使角度正确,旋转也会显得不稳定。
- 第一步:确认对象原始方向
- 第二步:选择 Pivot
- 第三步:填写 Current Angle
- 第四步:填写 Max Rotation
- 第五步:按需要开启质量边框
风机、指针和阀门适合 Rotate。对象只是左右移动时应使用 Move;对象长度变化时应使用 Scale。
Scale:用比例表达增长和缩短
Scale 根据输入值改变对象尺寸。它的关键不是放大多少,而是哪一边固定。
Scale 把输入值换算成一个比例,让对象从指定边缘向外增长或缩短。它适合液位、进度条、负载条和填充条。
- Scale Min 对应最低比例
- Scale Max 对应最高比例
- Anchor Edge 决定固定边
Input Value 是来源值;Input Min / Input Max 是来源范围;Clamp Min / Clamp Max 是参与换算的范围;Scale Min / Scale Max 是缩放比例;Anchor Edge 决定固定边。
- Scale Min / Scale Max:常见为 0 到 1 或 0.5 到 1.5
- Anchor Edge = Bottom:底部固定,向上增长
- Anchor Edge = Left:左侧固定,向右增长
- Anchor Edge = Right:右侧固定,向左增长
Scale 适合对一个独立填充对象做比例变化。液位、进度条和负载条通常应拆成背景容器和前景填充对象,再让前景对象按固定边增长。不要直接缩放包含文字、边框和图标的复杂组合,否则文字和边框也会跟随变形。
- 背景容器保持固定
- 前景填充对象参与 Scale
- 文字和单位建议单独放置
- 复杂设备组不直接整体 Scale
Scale 的输入值使用数值表达式,比例字段使用数值或计算表达式。
- 液位:Scale Min = 0,Scale Max = 1
- 轻微变化:Scale Min = 0.8,Scale Max = 1.2
- 输入值:ReadTagDouble("<device-code>.<level-tag>", 0)
Input Value = ReadTagDouble("<device-code>.<level-tag>", 0)
Input Min = 0
Input Max = 100
Scale Min = 0
Scale Max = 1
Anchor Edge = Bottom 先确定对象应从哪一边增长,再设置 Anchor Edge。液位类对象通常固定底部,进度条通常固定左侧。
- 第一步:确认增长方向
- 第二步:设置 Anchor Edge
- 第三步:填写输入量程
- 第四步:填写 Scale Min / Scale Max
- 第五步:按需要叠加 Range Color
Scale 适合长度或填充比例变化。对象整体移动时使用 Move;对象转动时使用 Rotate。
Blink:用闪烁表达强提醒
Blink Color 是提醒类行为,只应用于少数关键状态。它不适合普通运行状态。
Blink Color 在条件成立时,让对象在 ON 和 OFF 两组显示状态之间切换。条件不成立时,可以使用 False 状态。
- ON 状态:条件成立时的闪烁亮态
- OFF 状态:条件成立时的闪烁暗态
- False 状态:条件不成立时的普通状态
Condition 决定是否进入闪烁;Fill On / Fill Off 决定闪烁颜色;Blink Interval 决定切换节奏;Visibility 可控制闪烁时是否显隐变化。
- Condition:布尔表达式
- Fill On / Fill Off / Fill False:颜色
- Stroke On / Stroke Off / Stroke False:边框色
- Visible When On / Off / False:显隐
- Blink Interval:毫秒
Blink Interval 使用毫秒。报警和强提醒应保持节奏清晰,过快会造成阅读疲劳,过慢会削弱提示效果。正式页面建议只给少数关键对象开启闪烁,并避免整页多个区域同时闪烁。
- 常规提醒可从 650ms 开始
- 关键报警可按项目规范调整
- 普通运行状态不建议闪烁
- 同一页面应控制闪烁对象数量
Condition 可以读取布尔 Tag,也可以组合状态码和质量判断。
var alarm = ReadTagBoolean("<device-code>.<alarm-tag>", false);
var qualityGood = ReadTagQualityGood("<device-code>.<alarm-tag>");
alarm === true && qualityGood === true 先写清楚触发条件,再设置亮态、暗态和普通态,最后设置闪烁间隔。需要区分数据质量时开启 Quality Border。
- 第一步:填写 Condition
- 第二步:设置 ON 颜色
- 第三步:设置 OFF 颜色
- 第四步:设置 False 状态
- 第五步:设置 Blink Interval
报警灯、故障块、超限提醒适合 Blink。运行、停止、自动、手动等普通状态优先使用 State Color 或 Multi-State Color。
Range:用区间表达连续值状态
Range Color 把一个数值拆成多个区间,用颜色、边框或显隐表达当前区间。
Range Color 读取一个数值,把它落入预设 Limits 的区间,再根据区间选择颜色、边框和显隐状态。
- 适合连续值
- 适合低、中、高、危险等区间
- 默认 4 个分割点形成 5 个区间
Rule 返回数值;Limits 是区间分割点;Fill Colors、Stroke Colors、Visible States 分别决定每个区间的填充、边框和显隐。
- Rule:数值表达式
- Limits:区间边界
- Fill Colors:区间填充色
- Stroke Colors:区间边框色
- Visible States:区间显隐
Limits 按从小到大排列。4 个分割点会形成 5 个区间:小于第一个分割点、第 1 到第 2 区间、第 2 到第 3 区间、第 3 到第 4 区间、大于等于最后一个分割点。颜色数量应与区间数量对应。
- Limits 示例:20, 40, 60, 80
- 形成区间:<20、20-40、40-60、60-80、>=80
- 先确定单位和工程量程,再确定区间颜色
Rule 通常读取模拟量 Tag。Limits 使用从低到高的数值。
var value = ReadTagDouble("<device-code>.<temperature-tag>", 0);
value
Limits = 20, 40, 60, 80 先确认数值单位和量程,再确定区间边界。边界写完后,再设置每个区间的颜色和显隐。
- 第一步:确认 Tag 和单位
- 第二步:填写 Rule
- 第三步:填写 Limits
- 第四步:设置每个区间颜色
- 第五步:按需要开启质量边框
温度、压力、负载、液位等连续值适合 Range。固定状态码使用 Discrete Color;复杂优先级状态使用 Multi-State Color。
先选对动画类型,再谈参数
动画配置首先要确认表达目标。类型选错后,即使参数正确,也可能无法准确表达设备状态。
Blink 最适合报警和强提醒。它不用于表达连续过程,而用于提示用户关注少数关键对象。
当对象本质上是在页面里沿某个方向移动时,例如滑块、行程位置、水平推进件,应使用 Move 表达位置变化。
Rotate 适合指针、风机、阀门和方向件。配置重点是旋转中心与对象机械特征一致。
Scale 最适合液位、进度条、增长条、长度变化件。它真正关心的是哪一边固定、哪一边变化。
Range 本身可以是颜色区间,也可以和几何范围映射配合。它最适合让用户快速判断数值落在哪个段位,而不是只看一个单一数字。
Blink 只适合把注意力拉向少数关键对象。
位置真的在变时,优先用 Move,而不是绕着写脚本。
角度变化和方向感最适合用 Rotate 表达。
长度变化和增长效果通常更适合 Scale。
Move 和 Scale 的选择边界
Move 表达对象位置变化,Scale 表达对象尺寸或填充比例变化。二者应按对象物理含义区分。
如果对象整体坐标发生变化,例如滑块向右移动、行程块沿轨道移动、位置标记上移,应选择 Move。
如果对象一边固定,另一边增长或收缩,例如液位柱向上增长、进度条向右增长,应选择 Scale。
液位类对象通常应由背景容器和前景填充对象组成。背景容器保持不变,前景填充对象使用 Scale,并将 Anchor Edge 设置为 Bottom。若使用 Move,画面表达会变成整体位置变化,不符合液位增长的物理含义。
整体平移类效果看 Move。
一边固定、一边增长类效果看 Scale。
动画数量控制:越重要的状态,越应配置动画
动画不应平均分配给所有对象。清晰稳定的页面通常只在最需要动态表达的层级配置动画。
优先给报警、运动方向、旋转设备、液位变化和进度变化这类静态表达不够直观的信息加动画。普通状态色、普通文字和普通按钮通常不需要额外动画。
如果对象已经通过颜色清晰表达状态,通常不需要再配置同等强度的动画。颜色和动画应分层表达:颜色负责基础状态,动画只强化重点状态。
如果一整页大量对象同时闪烁、旋转或缩放,用户注意力会被分散,关键状态反而不突出。建议只在报警、方向、旋转设备和关键过程变化上配置动画。
Post Operations 适合在几何结果计算完成后补充文本、边框、显隐或运行时变量,不应承载第二套主要 Move、Rotate、Scale 逻辑,也不应承担核心设备写值。主要几何关系应放在对应行为字段中维护。
- 适合补充展示结果
- 适合同步运行时变量
- 不适合作为主要几何规则
- 不适合作为关键写值入口
几个最常见的动画表达场景
这一节不讲抽象概念,直接讲页面里最容易遇到的几种动态表达。
风机通常最适合用 Rotate 表达运行,同时配置基础运行状态色。旋转表达设备正在转动,颜色表达设备是否处于运行态。
报警灯最适合 Blink,旁边再配 Script Text 或 Tag Text 显示报警内容。这样用户既知道有问题,也知道具体是什么问题。
液位通常最适合 Scale 从底边往上长,再叠一个 Range Color 或状态区间颜色。这样既有形态变化,也有区间感知。
滑块、行程件和推进块更适合 Move。必要时可以再根据位置区间改变颜色,但不要把本该位移的对象做成整体缩放。
区间感和动态感结合起来时,用户更容易快速读懂数值状态。