Rapid development of DataBinding data binding based on HTML5 network topology map application

foreword

I found that everyone is curious about how I directly manipulate node properties from the json file to control the dynamic changes of the interface, so this article will explain data binding and how to use the bound data. I wrote a simple example. , based on the flickering phenomenon of the lights of the equipment on the server of the industrial control in the computer room. We analyze the problem of data binding from two perspectives, 2d and 3d.

renderings

 2d                                                                                  3d

 
 

Code

In fact, whether it is 2d or 3d, in HT, data binding is not dimensional, so the two are very similar in implementation.

Code download address: https://download.csdn.net/download/u013161495/10290996

drawing equipment

The equipment in 2d and 3d is based on the following piece of equipment inside a cabinet drawn with a "vector", and data binding is added to the "flashing light" part of this vector, specifically binding the background color of the "flashing light" As well as the shadow color, changing the shadow color is to make the "light" have a "glowing" effect. The red box in the figure below is the "flickering light".



 

First we have to figure out how to draw a vector ( http://hightopo.com/guide/guide/core/vector/ht-vector-guide.html )? The overall vector drawing of our Demo is more complicated. I will only talk about how the "light" rectangle and text in the above picture are drawn.

We know that drawing a vector json must contain the following three parameters:

Each element must have width and height. These two attributes are not explained. The comps attribute is quite powerful. As mentioned in the third point above, this is an array. The actual operation of drawing graphics and text is as follows:

{
     "width": 48, // the overall width of the vector 
    "height": 262, // the overall height of the vector 
    "comps" : [
    {
        "type": "text", // text 
        "text": "port 3", // text content 
        "align": "center", // text alignment 
        "color": "rgb(255,255,255)", // Font color 
        "font": "8px arial, sans-serif", // text font size 
        "rect": [ // The rectangle border of the component drawn in the vector 
            18.28654, // the x-axis coordinate 
            39.80679, // the y-axis coordinate 
            27.82265 , // width 
            11.5434 // height 
        ]
    },
    {
        "type": "rect", // rectangle 
        "background": "rgb(255,0,0)", // property default value "shadow": true , // set to true to show shadow "shadowOffsetX": 0, // The shadow horizontal offset of the selected primitive 
        "shadowOffsetY": 0, // The vertical offset of the shadow of the selected primitive 
        "rect": [ // The rectangle boundary of the component drawn in the vector is 
            4.38544, // The x-axis coordinate 
            is 32.55505, // y-axis coordinate 
            14.46481, // width 
            6.1554 // height 
        ]
    }]  
}

This code draws a rectangle and a text.

After drawing the vector, we can display the vector by setting a picture for the node. Of course, the vectors drawn above are not all the codes for drawing vectors. For details, please refer to: https://download.csdn.net/download/u013161495/10290996 .

To dynamically change the properties of a node, we must first obtain the node. We can traverse the data model DataModel, or obtain the node through the tag tag, or through the mouse click event and so on. There are many nodes that need to be manipulated in this Demo, so I choose to traverse the data model to get the nodes. So the question is, how do I locate this node through a picture or a vector? If the nodes are not created, it is impossible to obtain the node corresponding to the picture (or if the vector image is directly used as a picture of a node, it may happen that the changes of the six devices are exactly the same! After all, it is the same node!). So we have to remove these special parts from the picture, then fill in the nodes in the corresponding positions, and then set the vector diagrams of the devices on the nodes. First delete the vector diagram of the corresponding position, as shown in the red box below:



 

We create eight device nodes separately in the red box, and set the same vector diagram for these eight nodes. Eh? You may be wondering why the same image is displayed differently (the lights change in a different order), let's see how this is done.

 

 

So how do these eight devices with the same vector diagram control the blinking lights to change randomly through code? The key is in the vector diagram we drew above, and this part was intentionally skipped earlier: data binding.

data binding

Since the light flickering is achieved by setting the background color of the rectangle (of course, I also added a shadow here, in order to have the effect of "lighting on"), so we data bind the background color property of this rectangle, and then pass the data .a methods get and set property values.

{
    "type": "rect",//矩形
    "background": {//矩形背景
        "func": "attr@rectBg2",//数据绑定string类型若以attr@***开头,则返回data.getAttr(***)值,其中***代表attr的属性名
        "value": "rgb(255,0,0)"//属性默认值
    },
    "shadow": true,//设置为true显示阴影
    "shadowColor": {//阴影颜色
        "func": "attr@shadowColor2",//数据绑定string类型
        "value": "rgba(255,0,0,0.35)"//属性默认值
    },
    "shadowOffsetX": 0,//选中图元的阴影水平偏移
    "shadowOffsetY": 0,//选中图元的阴影垂直偏移
    "rect": [//组件绘制在矢量中的矩形边界
        4.38544,//x 轴坐标
        32.55505,//y 轴坐标
        14.46481,//width
        6.1554//height
    ]
}

上面是我对矩形灯矢量的部分重新绘制后的代码,看出什么不同了?对,background 属性和 shadowColor 属性都出现了两个值,并且这两个值看起来“怪怪的”?数据绑定(http://hightopo.com/guide/guide/core/databinding/ht-databinding-guide.html)没有那么难,绑定的格式很简单,只需将以前的参数值用一个带 func 属性的对象替换即可,如果对应的 func 取得的值为 undefined 或 null 时,则会采用 value 属性定义的默认值。

func 的内容有以下几种类型:

  • function 类型,直接调用该函数,并传入相关 Data 和 view 对象,由函数返回值决定参数值,即 func(data, view) 调用。
  • string 类型:
    • style@*** 开头,则返回 data.getStyle(***) 值,其中 *** 代表 style 的属性名。
    • attr@*** 开头,则返回 data.getAttr(***) 值,其中 *** 代表 attr 的属性名。
    • field@*** 开头,则返回 data.*** 值,其中 *** 代表 data 的属性名。
    • 如果不匹配以上情况,则直接将 string 类型作为 data 对象的函数名调用 data.***(view),返回值作为参数值。

 所以我们通过 "func" 来绑定数据,这里用的是 attr@*** 的方式绑定,到时候要调用这个属性的时候就直接通过 data.getAttr(***) 或者缩写 data.a(***) ;然后通过 "value" 设置一个默认值,作为 func 返回的值为空时的“备用”。

一般我们将代码比较多的矢量图放在一个 json 文件中,我取名叫做 service3d.json 放在 scene 文件夹下 ,通过 ht.Default.xhrLoad 方法解析 json 文件的内容,如下:

ht.Default.xhrLoad('scene/service3d.json', function(text) {
    var json = ht.Default.parse(text);
    dm.deserialize(json);//反序列化
})

其中 deserialize 反序列化函数是将数据反序列化到模型,传入的参数 json 为数据信息对象,用于解析生成对应的 Data 对象并添加到数据容器中。

因为 xhrLoad 方法是异步加载,为了避免后面出现获取不到数据的问题,我们将剩下的节点属性控制代码也写在 xhrLoad  函数中:

dm.each(function(data) {//遍历dataModel
    var infos = [//我设置的业务属性名称
        {shadowColor: 'shadowColor1', background: 'rectBg1'},
        {shadowColor: 'shadowColor2', background: 'rectBg2'},
        {shadowColor: 'shadowColor3', background: 'rectBg3'},
        {shadowColor: 'shadowColor4', background: 'rectBg4'},
        {shadowColor: 'shadowColor5', background: 'rectBg5'},
    ];
    infos.forEach(function(info) {//遍历infos数组
        data.a(info.shadowColor, 'rgba(255, 0, 0, 0.35)');//注册业务属性 attr 为业务属性 简写为 a
        data.a(info.background, 'rgb(255, 0, 0)');
    });

    setInterval(function() {//设置动画 动态变化闪烁灯的亮和灭的显示
        var random = Math.ceil(Math.random() * 5);//获取5以内一个随机整数 (可以配合我设置的业务属性名称)
        var shadowName = 'shadowColor' + random,
            bgName = 'rectBg' + random;

        if(data.a(shadowName) === 'rgba(255, 0, 0, 0.35)') {//如果是红色透明
            data.a(shadowName, 'rgba(0, 255, 0, 0.35)');//设置为绿色透明
        }
        else if(data.a(shadowName) === 'rgba(0, 255, 0, 0.35)') {//如果是绿色透明
            data.a(shadowName, 'rgba(255, 0, 0, 0.35)');//设置为红色透明
        }

        if(data.a(bgName) === 'rgb(255, 0, 0)') {//如果是红色
            data.a(bgName, 'rgb(0, 255, 0)');//设置为绿色
        }
        else if(data.a(bgName) === 'rgb(0, 255, 0)') {//如果是绿色
            data.a(bgName, 'rgb(255, 0, 0)');//设置为红色
        }
    }, 1000);
    
});

值得注意的一点是,虽然我们在 json 中已经绑定了业务属性(这里是“shadowColor1,2,3,4,5...”和“rectBg1,2,3,4,5”),但是节点上并没有这个属性,所以我们需要注册一下这些属性,并给这些属性设置属性值。

然后我们就可以通过调用这些属性来动态更新 Data 上的属性值图形界面就会自动刷新,从而达到实时显示数据的效果。因为 HT 只有一个数据模型,绑定 DataModel 的图形组件并没有组件内部的其他数据模型,所以组件都是如实根据 DataModel 来呈现界面效果,因此当用户拖拽图元移动时, 本质也是修改了数据模型中 Node 的 position 位置值,而该属性变化触发的事件通过模型再次派发到图形组件,引发图形组件根据新的模型信息刷新界面。

总结

其实数据绑定没有什么很深奥的部分,HT 也不需要你考虑太多,一切以最简单的方式进行着。这个 Demo 需要注意的就是,相同的图片,如果要显示不同,那么肯定需要创建不同的节点,若是节点相同,那么变化肯定相同的!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326077694&siteId=291194637