拖拽式制作
FreeForm (拖拽) 模式是 Darra HMI 的默认编辑方式, 全流程无需写代码, 通过 GrapesJS 画布 + 左侧 Block 面板 + 右侧 Trait 面板完成页面制作, 保存时自动生成 HtmlCode / CssCode / JsCode / Elements[] 四段。
全流程概览
1. 新建 HMI 项目/页面
↓
2. 选择模板或空白
↓
3. Block 面板拖控件入画布
↓
4. Trait 面板填 var / 其他属性
↓
5. Style 面板调 CSS
↓
6. 切换皮肤预览
↓
7. 保存 → HMIPageDef
↓
8. 预览 / 真机 / 浏览器访问
步骤 1: 新建项目
IDE 菜单 HMI → 新建 LocalHMI 项目:
┌────────────────────────────────┐
│ 新建 HMI 项目 │
├────────────────────────────────┤
│ 名称: [ 主控台 ] │
│ 类型: ● Local ○ Web │
│ 模板: [ 现代仪表盘 ▼] │
│ 分辨率: [1920 × 1080 ▼] │
│ 皮肤: [ modern ▼] │
│ │
│ [ 创建 ] [ 取消 ] │
└────────────────────────────────┘
步骤 2: 新建页面
项目节点右键 → 新建页面:
| 字段 | 示例 |
|---|---|
| 页面名 | 反应釜 |
| 路由 | /reactor |
| 是否首页 | 否 |
| 模板 | 空白 |
保存后 IDE 目录树多一个页面节点, 双击打开设计器。
步骤 3: 拖入控件
左侧 Block 面板 按分类列出所有 <darra-*>。鼠标按下拖到画布, 松开后:
- 画布自动生成
<darra-led>/<darra-tank>/<darra-dx-grid>等标签 - 控件位于鼠标释放点 (吸附 10px 网格)
- 右侧 Trait 面板自动显示该控件的属性列表
拖多个控件可使用:
- Ctrl+D 复制选中控件
- Alt+拖 拖拽复制
- 按住 Shift 多选
步骤 4: 配置 Trait (变量 + 属性)
以 <darra-tank> 为例, 右侧 Traits:
| Trait | 填入 |
|---|---|
变量 (var) | DB1.Level |
量程最大 (max) | 100 |
液体颜色 (color) | #1E90FF |
显示标签 (show-label) | 勾选 |
修改即刻写入标签:
<darra-tank var="DB1.Level" max="100" color="#1E90FF" show-label></darra-tank>
步骤 5: 调整样式 (Style 面板)
选中控件 → 右侧 Style 标签:
position: absolute / relativeleft/top/width/height: 坐标尺寸font-size/color/background: 文字/底色transform:rotate(45deg)/scale(1.5)等transition: 过渡动画 (all .3s ease)
CSS 会累积到 HMIPageDef.CssCode:
.tank-1 {
position: absolute;
left: 120px;
top: 80px;
width: 180px;
height: 280px;
}
步骤 6: 图层与对齐
顶部工具栏 对齐工具:
- 多选控件 → 左对齐 / 水平居中 / 右对齐
- 垂直对齐同理
- 等间距分布: 水平 / 垂直
图层面板:
- 拖拽调整 DOM 顺序 (影响
z-index) - 右键 →
组合把多个控件包进<darra-panel> - 锁定/隐藏 (设计期隔离)
步骤 7: 切换皮肤预览
顶部工具栏 皮肤 下拉:
modern(深色)industrial(浅色)brandRed(自定义)
切换仅影响 IDE 预览, 最终皮肤由 HMIProjectDef.ActiveSkin 决定。建议两种皮肤各验一次, 确保对比度、可读性无问题。
步骤 8: 保存 (Ctrl+S)
保存会序列化为 HMIPageDef:
{
"Name": "反应釜",
"Route": "/reactor",
"IsHome": false,
"HtmlCode": "<div class='page-reactor'>...</div>",
"CssCode": ".page-reactor { padding: 20px; background: var(--darra-bg); }",
"JsCode": "",
"Elements": [
{
"Id": "el_001",
"Type": "Tank",
"X": 120, "Y": 80, "Width": 180, "Height": 280,
"VariableBinding": "DB1.Level",
"Properties": { "max": 100, "color": "#1E90FF", "show-label": true }
},
{
"Id": "el_002",
"Type": "Gauge",
"X": 340, "Y": 80, "Width": 200, "Height": 200,
"VariableBinding": "DB1.Pressure",
"Properties": { "min": 0, "max": 10, "unit": "MPa" }
}
]
}
HtmlCode是运行时直接用,Elements[]是下次打开设计器还原用, 两者必须同步。
步骤 9: 预览
内嵌预览
设计器顶部 预览 → 弹出右侧面板, 实时渲染 (无 PLC 数据, 仅结构)。
真机预览
IDE 菜单 运行 → F5:
- 启动 PLC Service (若未启动)
- 启动 HmiWebServer (18823)
- 启动
Darra.PLC.HMI.exe全屏加载 - 自动导航到首页
浏览器预览
打开 Edge/Chrome 输入 http://localhost:18823/local/reactor, 按 F12 看 WebSocket 帧。
完整示例: 3 分钟做一个反应釜监控页
- 新建页面
/reactor, 皮肤industrial - 左侧工业控件拖
<darra-tank>到画布, Trait 填var=DB1.Level,max=100 - 拖
<darra-gauge>到右边,var=DB1.Temp,min=0,max=150,unit=℃ - 拖
<darra-gauge>,var=DB1.Pressure,min=0,max=10,unit=MPa - 拖
<darra-button>(启动 / 停止 / 排料), 分别var=M0.0 / M0.1 / M0.2 - 拖
<darra-alarm-list>到底部,max-rows=5 - 顶部拖
<darra-label>写 "1# 反应釜监控" - Ctrl+S 保存, F5 运行
生成的 HtmlCode 核心:
<div class="page-reactor">
<darra-label class="title">1# 反应釜监控</darra-label>
<darra-tank class="tank-1" var="DB1.Level" max="100" color="#1E90FF" show-label></darra-tank>
<darra-gauge class="gauge-temp" var="DB1.Temp" min="0" max="150" unit="℃"></darra-gauge>
<darra-gauge class="gauge-press" var="DB1.Pressure" min="0" max="10" unit="MPa"></darra-gauge>
<div class="btn-group">
<darra-button var="M0.0" mode="toggle">启动</darra-button>
<darra-button var="M0.1" mode="toggle">停止</darra-button>
<darra-button var="M0.2" mode="momentary">排料</darra-button>
</div>
<darra-alarm-list max-rows="5"></darra-alarm-list>
</div>
Tips 和陷阱
| Tip | 说明 |
|---|---|
| 吸附与自由 | 按 Alt 暂时取消网格吸附; 微调用方向键 1px |
| 多选复制 | Shift+点选 多个 → Ctrl+D 整体复制 |
| 同步 Elements | 手动改 HtmlCode 后, Elements 可能失步; 保存时 IDE 会尝试重建 |
| 组合容器 | 相关控件打包进 <darra-panel> 方便整体拖 |
| 锁定背景图 | 大背景图拖入后立即右键锁定, 避免误触 |
| 渐进添加 | 先把所有控件拖到画布 (Trait 留空), 再一次性回填 var |
| 使用模板 | 复杂行业页面 (SCADA) 从 template-industrial.html 起手, 改比从零写快 |
常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
| 拖入后画布卡住 | 控件依赖的 JS 未加载 | 检查 Service 启动, /static/darra-controls.js 可访问 |
| Trait 填了 var 但没数据 | 变量名拼错 / DB 不存在 | F12 Network WS 看 subscribe 帧, 确认订阅成功 |
| 控件挤在一起 | 未设 position: absolute | Style 面板设 position, 或用 <darra-panel> 容器 |
| 保存后位置错位 | CSS 变量冲突 | 检查 GlobalCss 有没有覆盖 .page 的 padding |
| 切 Code 模式丢 Elements | 手写 HTML 无法反向解析 | 手动补 Elements 或忽略 (继续 Code 模式即可) |