# 进阶

# 官方后端数据源下载并开发

TIP

官方提供了标准的后端数据源,并同时提供了源代码,首先需要下载数据源源代码,并写好自己的数据源逻辑,启动数据源

元素的锁定

  • 打开下载的java项目(可以使用 Eclipse 或 IDEA )

元素的锁定

  • 主要代码介绍 (WebSocketServer)
package com.lazykee.sourcewebsocketzk.server;

import com.alibaba.fastjson.JSON;
import com.lazykee.sourcewebsocketzk.utils.HttpUtil;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author LAZYKEE
 * @version 1.0
 * @date 2021/12/30 23:20
 */
@ServerEndpoint("/zkSource")
@Component
public class WebSocketServer {

    private static final CopyOnWriteArraySet<WebSocketServer> WEB_SOCKET_SET = new CopyOnWriteArraySet<>();

    public Long heartTime;

    public static Set<WebSocketServer> getWebSocketSet() {
        return WEB_SOCKET_SET;
    }

    private Session session;

    @OnOpen
    public void onOpen(Session session) throws IOException {
        this.session = session;
        WEB_SOCKET_SET.add(this);
        this.heartTime = System.currentTimeMillis();

        // 发送示例数据
        String demo = "{\"num_1_1\":0.2503,\"num_1_2\":0.1752,\"num_10_5\":8.2418,\"num_100_1\":75.6374,\"num_1000_1\":124.023,\"list_10_1\":[3.5628,6.9725,8.3505,4.636,8.6265],\"list_100_1\":[24.5654,99.8544,5.1336,86.5468,55.3747],\"text_1\":\"黄梅时节家家雨\",\"img_1\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAYAAADDhn8LAAAAAXNSR0IArs4c6QAAAqRJREFUeF7t1bERgEAMBDEojv5LggaAYNMTuQPLv8N5X8d9+AgQeBU4BeJlEPgWEIjXQeBHQCCeBwGBeAMEmoA/SHMzNSIgkJFDW7MJCKS5mRoREMjIoa3ZBATS3EyNCAhk5NDWbAICaW6mRgQEMnJoazYBgTQ3UyMCAhk5tDWbgECam6kRAYGMHNqaTUAgzc3UiIBARg5tzSYgkOZmakRAICOHtmYTEEhzMzUiIJCRQ1uzCQikuZkaERDIyKGt2QQE0txMjQgIZOTQ1mwCAmlupkYEBDJyaGs2AYE0N1MjAgIZObQ1m4BAmpupEQGBjBzamk1AIM3N1IiAQEYObc0mIJDmZmpEQCAjh7ZmExBIczM1IiCQkUNbswkIpLmZGhEQyMihrdkEBNLcTI0ICGTk0NZsAgJpbqZGBAQycmhrNgGBNDdTIwICGTm0NZuAQJqbqREBgYwc2ppNQCDNzdSIgEBGDm3NJiCQ5mZqREAgI4e2ZhMQSHMzNSIgkJFDW7MJCKS5mRoREMjIoa3ZBATS3EyNCAhk5NDWbAICaW6mRgQEMnJoazYBgTQ3UyMCAhk5tDWbgECam6kRAYGMHNqaTUAgzc3UiIBARg5tzSYgkOZmakRAICOHtmYTEEhzMzUiIJCRQ1uzCQikuZkaERDIyKGt2QQE0txMjQgIZOTQ1mwCAmlupkYEBDJyaGs2AYE0N1MjAgIZObQ1m4BAmpupEQGBjBzamk1AIM3N1IiAQEYObc0mIJDmZmpEQCAjh7ZmExBIczM1IiCQkUNbswkIpLmZGhEQyMihrdkEBNLcTI0ICGTk0NZsAgJpbqZGBAQycmhrNgGBNDdTIwICGTm0NZuAQJqbqREBgYwc2ppNQCDNzdSIgEBGDm3NJiCQ5mZqROABWVrikf/PyvkAAAAASUVORK5CYII=\"}";
        sendMessage(demo);
    }

    @OnClose
    public void onClose() {
        System.out.println("连接关闭");
        WEB_SOCKET_SET.remove(this);
    }

    @OnMessage
    public void onMessage(String message) {
        Map map = JSON.parseObject(message, Map.class);
        String name = (String) map.get("name");
        /**
         *  数据源心跳监听接口
         *      该接口用户切勿修改,是数据源心跳的监听接口
         */
        if ("zk_heart".equals(name)) {
            try {
                this.session.getBasicRemote().sendText("zk_heart");
                this.heartTime = System.currentTimeMillis();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         *  注册测点登记接口
         *      该接口用户切勿修改,可进行逻辑处理
         *      接收到的值为:图纸上对该数据源的所有注册点位信息
         *                  用户可根据注册的点位信息筛选发送的数据
         */
        if ("register".equals(name)){
            System.out.println("--------------------------------");
            System.out.println("收到用户注册测点");
            List<String> registerPointList = (List<String>) map.get("data");
            for (String point : registerPointList) {
                System.out.print(point + ", ");
            }
            System.out.println("");
            System.out.println("--------------------------------");
        }
        /**
         *  HTTP GET 代理数据源
         *  该接口封装了代理的 HTTP GET 请求接口
         *      封装目的:没有同源限制,客户端可以与任意服务器通信
         *      返回的数据用户可通过 sendMessage() 方法向页面输出
         */
        if ("HTTPGET".equals(name)){
            System.out.println("--------------------------------");
            System.out.println("收到 HTTPGET 请求");
            String url = (String) map.get("url");
            Map<String, String> header = (Map<String, String>) map.get("header");
            System.out.println(url);
            System.out.println(header);
            String res = HttpUtil.httpGet(url, header);
            System.out.println(res);
            System.out.println("--------------------------------");
        }
        /**
         *  HTTP POST 代理数据源
         *  该接口封装了代理的 HTTP POST 请求接口
         *      封装目的:没有同源限制,客户端可以与任意服务器通信
         *      返回的数据用户可通过 sendMessage() 方法向页面输出
         */
        if ("HTTPPOST".equals(name)){
            System.out.println("--------------------------------");
            System.out.println("收到 HTTPPOST 请求");
            String url = (String) map.get("url");
            Map<String, Object> params = (Map<String, Object>) map.get("params");
            Map<String, String> header = (Map<String, String>) map.get("header");
            String res = HttpUtil.httpPost(url, params, header);
            System.out.println(res);
            System.out.println("--------------------------------");
        }
        // 用户动画发送数据
        /**
         * 接收页面写入的Websocket数据,用户可自行数据进行后续处理
         */
        if ("data".equals(name)){
            System.out.println("收到用户发送数据");
            Object userData = map.get("data");
            System.out.println(JSON.toJSONString(userData));
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
    }

    /**
     * 数据推送接口,该接口将数据发送给页面
     */
    public static void sendMessage(String message) throws IOException {
        for (WebSocketServer item : WEB_SOCKET_SET) {
            if (item.session.isOpen()) {
                item.session.getBasicRemote().sendText(message);
            }
        }
    }
}

编写好相应的后端数据源逻辑后,启动后端数据源项目


# 前端数据源连接

# 1. 打开数据源管理面板

TIP

数据源管理面板的打开有两种方式:

  1. 数据源在点击图纸空白处时,在配置栏选择数据源面板,点击数据源 元素的锁定

  2. 在用户头像上单击,点击数据源管理
    元素的锁定

数据源管理面板如图所示
元素的锁定

# 2. 在弹出面板点击添加项目

元素的锁定

  • 输入项目相关信息,点击添加,选择刚才新建的项目
    元素的锁定

# 3. 新建的项目下,添加数据源

点击添加数据源,输入相关数据源信息

元素的锁定

# 4. 建好的数据源添加测点

  • 选择新建的数据源,右侧出现数据源配置信息

元素的锁定

TIP

  • 原始点管理:能从服务器接收到的测点数据信息,可直接勾选进行添加
  • 添加原始点:从服务器暂时未获取到的测点数据信息,在后面会有数据,则可以通过手动添加
  • 添加中间点:用户需要对原始点数据进行一定的处理和运算,则可以添加中间测点

# 5. 原始点添加

  • 点击原始点管理

元素的锁定

  • 勾选需要的测点,点击保存更改

元素的锁定 元素的锁定

  • 在数据源信息面板可以看到添加好的原始点

TIP

如果原始点管理面板中没有需要的测点,说明这个测点的数据可能是延迟发送的,此时,可以在确定测点数据结构(key)的情况下,手动添加原始点

  • 手动添加原始点,点击添加原始点

元素的锁定

  • 弹出的面板中填写原始点信息

元素的锁定

  • 点击确定,可在原始点中查看到添加好的原始点

# 6. 添加中间点

TIP

当用户需要对原始测点的结果进行计算或相应的逻辑处理时,可以添加中间点,中间点支持js语法编辑

  • 点击添加中间点 元素的锁定

  • 左侧为源测点,可通过点击快速复制引用的测点

元素的锁定

  • 编辑完成后,点击连接开启,即可观察实时计算值是否正确

元素的锁定

# 图纸中数据源添加

TIP

图纸中的数据源支持在数据源中自定义添加的数据源,也可导入管理员预置的数据源

# 1. 点击导入我的数据源

元素的锁定

  • 展开对应项目,选择数据源进行导入

元素的锁定

  • 导入成功后,可在数据源列表中查看到数据源

元素的锁定

  • 点击实时数据查看,可查看该数据源下的实时数据点位值

元素的锁定

  • 可点击测点列表,查看全部数据源的所有点位信息

元素的锁定 元素的锁定

# 2. 导入公共数据源

管理员可预置内部数据源,用户可自行导入管理员预置好的数据源进行导入

元素的锁定 元素的锁定

  • 数据源管理内置了数据源的复制和粘贴功能,便于不同图纸间的数据源迁移,点击复制后,将会弹出粘贴数据源的按钮,在对应图纸中点击粘贴即可应用

元素的锁定

  • 点击更新按钮,数据源将变为可编辑状态,对数据源可进行更改

元素的锁定
注:当更改唯一识别码时,会提示是否将绑定测点的key都进行替换,(对于用户脚本中的key,尚无法替换)方便一次更改图纸的所有数据源

  • 数据源识别码:当同一张图纸上添加多个数据源时,用户辨别数据测点是来自哪一个数据源,同一张图纸的多个数据源,唯一识别码不可重复

# 元素动画使用

说明

当前版本大部分元素支持动画操作,不支持动画的元素组件有(图表组件、视频组件、Vue组件)

# 动画介绍

测点代码
动画的类型分为 连续动画、补间动画、事件动画三种,其具体解释如下

  • 连续动画
    当图纸/导出网页一旦打开就会启动连续动画,直至网页关闭。(如图形的连续旋转、线条的连续流动、颜色的连续闪烁等等)

  • 补间动画
    当达到相应的启动条件时,动画过渡到目标状态,当动画达到停止条件时,动画还原到初始状态。(如旋转一定角度、进行一定的位移、背景变为某种颜色、图形进行隐藏/显示等)

  • 事件动画 当达到一定条件时,执行相应的特殊条件,如向后台发送请求、播放音频、弹出面板、页面跳转等特殊的动作

# 动画启动/停止条件

启动条件包含立即启动、动作条件启动和数据阈值启动三种
停止条件包含不停止、动作条件停止和数据阈值停止三种 测点代码

  • 启动条件:立即启动
    画布打开后,立即启动该动画

  • 启动条件:动作条件启动
    通过识别用户的交互动作进行启动,如点击、鼠标移入等,实现动画的启动

  • 启动条件:数据阈值启动
    通过绑定相应的数据测点,当该数据满足阈值区间时,进行动画的启动

  • 停止条件:不停止
    动画启动后,不再停止,持续运动下去

  • 停止条件:动作条件停止
    通过识别用户的交互动作进行启动,如点击、鼠标移入等,实现动画的停止

  • 停止条件:数据阈值停止
    通过绑定相应的数据测点,当该数据满足阈值区间时,进行动画的停止

# 添加一个立即启动动画

  1. 设置动画参数
    其他参数说明
  • 执行动作:动画的动作类型
  • 旋转中心:动画运动时围绕的中心点
  • 旋转方向:正向/逆向旋转
  • 速度绑定:绑定数据测点,运动的速度随测点值的变化而变化
  • 速度:运动的速度,范围在0-100之间
    测点代码
  1. 添加动画,长按F1预览动画效果,按F4打开预览窗口
    测点代码

# 添加一个随数据变化启动/停止的动画

  • 将启动条件设置为数据阈值启动,将停止条件设置为数据阈值停止
    测点代码
  • 点击测点选择,在弹出面板中选择需要的测点
    测点代码
  • 配置项说明
  1. 测点选择:选择触发动画的数据测点
  2. 启动判断:
    设置启动/停止时数值判断时,条件框以 x 标识当前的测点值,使用js语法进行条件的判断
  • 如当需要测点值大于 5时启动条件应设置为
x > 5
  • 如当需要测点值等于 1时启动条件应设置为
x === 1
  • 当需要测点值大于等于3,并且小于8的时候启动,则启动条件应设置为
3 <= x < 8 
或 
(x >= 3) && (x < 8)
  • 当需要测点值小于3,或大于等于8的时候启动,则启动条件应设置为
(x < 3) || (x >= 8)

其他配置参数参考上述介绍

# 添加一个随数据大小动画速度随之改变的动画

  • 打开速度绑定
    测点代码
  • 点击测点选择,在弹出面板中选择需要的测点
    测点代码
  • 设置速度测点值 说明:速度测点值为从数据源接收的测点数据值
    如测点数据值的范围在[10, 20]之间,则速度测点值可设置为 10 - 20, 当接收到的值为 10 时,动画的速度为0(停止运动),当测点值为20时,速度达到100(速度最大值)

# 数据绑定

数据绑定介绍

通过于数据测点进行数据绑定,可以实现随着数据的变化,页面数据的实时更新显示,页面元素的高度、宽度、位置、角度随数据变化而变化的效果,数据绑定案例如:

  • 页面实时数据展示
  • 水池水位实时图形化展示
  • 小车位置位置坐标实时图形化左边展示
  • 仪表指针随数值变化旋转到对应位置
  • ...

# 显示测点实时数据

  1. 使用Text文本元素(基础形状/文本)
    测点代码
  2. 配置数据绑定测点
    测点代码
  3. 其他配置:
  • 绑定类型:选择为数据显示
  • 保留小数点:配置显示的测点数据的保留位数
  1. 添加绑定,通过 F2 快速预览数据效果,或 F4 打开预览窗口

# 根据数据变化相应的效果(水位示例)

  1. 添加一个背景元素,作为水池外壳效果,示例设置高度为400
  2. 添加一个数据绑定元素,作为水位展示元素,示例设置高度为10(最低水位高度)
  3. 设置数据绑定元素的样式/边框缩放关闭 测点代码
  4. 为数据绑定元素添加数据绑定配置
    测点代码
  • 高度变化值:
    本示例中背景高度为400,绑定元素高度为10
    高度的变化值为 10 + 变化值 = 最高水位值
    即当数值为水位最小值时(水空位数值)绑定元素的高度为 10 + 0
    数值为水位最大值时(水满位数值)为 10 + 390 等于背景的最大高度
  • 零刻度值:当水位最低点时对应的测点值数值
  • 满刻度值:当水位最高点时对应的测点值数值
    如水位传感器的变化范围在 [80, 160]之间,则零刻度值为80,满刻度值为160
    参考中心:参考中心为图形变化时,位置不动的基点
    参考中心有以下几种
    测点代码
    如水位变化时,需要水位高度向上变化,则设置底部中央为基点,高度变化朝上方增加或减少