乐吾乐大屏上动态绘制卡片界面
自动渲染界面上的故障详情
公司最近用乐吾乐大屏可视化组态软件这个编辑工具,因为工具支持以2D/2.5D等形式构建实时数据展示、监控告警、动态交互的组态画面,完全满足国产化需求。(上面这么多基本不用看 我就是复制官网的介绍语介绍下)其实主要是目的就是把自己写的东西记录下来!
开始
1. 导入数据
注意这里导入的数据,属性名 和ws接口推送过来的id要保持一致,不然数据不能同步
2. 在初始化中开始写代码
在这个里面将静态界面绘制出来
let newArr = meta2d.store.data.networks[0].children; //获取刚才导入的excel数据
const bottleImage = "/file/2025/0227/1/1/绿色边框_5496fd7b.png";
const normalIcon = "/file/2025/0227/1/1/正常_dfae3f67.png";
const warningIcon = "/file/2025/0227/1/1/预警_2a00e0ce.png";
// 按比例缩小的尺寸
const startX = 74;
const startY = 74;
const BGSizeW = 337; // 原421 * 0.8
const BGSizeH = 66; // 原82 * 0.8
const horizontalSpacing = 16; // 原20 * 0.8
const verticalSpacing = 16; // 原20 * 0.8
const colsPerRow = 5;
// 按类别分组
const groupedData = {};
newArr.forEach(item => {
const category = item.label.split('#')[0] + '#';
if (!groupedData[category]) {
groupedData[category] = [];
}
groupedData[category].push(item);
});
let currentY = startY;
const categories = Object.keys(groupedData);
for (let catIndex = 0; catIndex < categories.length; catIndex++) {
const category = categories[catIndex];
const categoryItems = groupedData[category];
// 如果是第一个类别之后,增加额外的垂直间距
if (catIndex > 0) {
currentY += verticalSpacing * 2;
}
for (let i = 0; i < categoryItems.length; i++) {
const row = Math.floor(i / colsPerRow);
const col = i % colsPerRow;
const bgX = startX + col * (BGSizeW + horizontalSpacing);
const bgY = currentY + row * (BGSizeH + verticalSpacing);
// 添加背景图(按比例缩小)
meta2d.addPen({
image: bottleImage,
x: bgX,
y: bgY,
width: BGSizeW,
height: BGSizeH,
id: `bg_${category}_${i + 1}`,
name: "image",
canvasLayer: 3,
}, true, true, true);
// 添加状态图标(按比例缩小)
const statusIcon = categoryItems[i].value == "0" ? warningIcon : normalIcon;
meta2d.addPen({
image: statusIcon,
x: bgX + 8, // 缩小偏移量
y: bgY + 16, // 缩小偏移量
width: 32, // 原40 * 0.8
height: 32, // 原40 * 0.8
id: categoryItems[i].id + 'status',
name: "image",
canvasLayer: 3,
}, true, true, true);
// 添加文本标签(按比例缩小)
meta2d.addPen({
text: categoryItems[i].label,
x: bgX + 48, // 缩小偏移量
y: bgY + (BGSizeH - 32) / 2, // 调整垂直居中
height: 32, // 原40 * 0.8
width: 265, // 原331 * 0.8
textAlign: "center",
color: categoryItems[i].value == '0' ? "#ff5959" : "#000000",
fontStyle: "bold",
fontSize: 18, // 原22 * 0.8
borderRadius: 4, // 原5 * 0.8
id: categoryItems[i].id,
visible: true,
name: "text",
canvasLayer: 3,
}, true, true, true);
}
// 更新当前Y坐标,为下一个类别准备位置
const rowsInCategory = Math.ceil(categoryItems.length / colsPerRow);
currentY += rowsInCategory * (BGSizeH + verticalSpacing);
}
3. 从webscoker接口获取数据
接着在初始化中写代码
// 创建一个WebSocket连接 地址乱写一个
var socket = new WebSocket('ws://192.0.0.0:8085//ws/iot/scada');
// 建立连接之后发送数据:字符串 -- 所有属性名的组合用逗号隔开。
socket.onopen = function (event) {
let idString = newArr.map(item => item.id).join(',');
socket.send(idString);
};
// 接收到消息时触发
socket.onmessage = function (event) {
let newArr = JSON.parse(event.data); //拿到返回值了
newArr.forEach(item => {
const id = item.id; // 获取数据项的ID
const value = item.value; // 获取值
// 根据value值设置文字颜色和图标
if (value == "0") {
meta2d.setValue({
id: id,
color: "#ff5959", // 红色
}, { render: true });
meta2d.setValue({
id: id + 'status',
image: "/file/2025/0227/1/1/预警_2a00e0ce.png" // 预警图标
}, { render: true });
} else if (value == "1") {
// 值为1:正常状态 - 黑色文字,正常图标
meta2d.setValue({
id: id,
color: "#000000", // 黑色
}, { render: true });
meta2d.setValue({
id: id + 'status',
image: "/file/2025/0227/1/1/正常_dfae3f67.png" // 正常图标
}, { render: true });
}
});
};
// 连接关闭时触发
socket.onclose = function (event) {
console.log('Connection closed.');
// 关闭连接
socket.close();
};
// 发生错误时触发
socket.onerror = function (error) {
console.error('WebSocket Error: ', error);
};
这样在onmessage里可以更改刚才创建的卡片的状态和文字 通过meta2d.setValue方法,对了这里通过id去更改 ,所有创建初始化的id需要有规则
最后的界面
结束语
这种写法可以根据故障信息自动生成全界面渲染,无需手动绘制卡片; 点位状态实时驱动文字颜色、图标动态变化(故障红色警示/正常绿色);
解决的问题: 消除人工绑定点位与卡片的重复劳动,维护成本降低。 状态反馈延迟降低至毫秒级,提升故障响应速度。