前言

发现大家对于我从 json 文件中直接操作节点属性来控制界面的动态变化感到比较好奇,所以这篇就针对数据绑定以及如何使用这些绑定的数据做一篇说明,我写了一个简单的例子,基于机房工控的服务器上设备的灯闪烁现象。我们从 2d 和 3d 两个角度来分析数据绑定的问题。

效果图

2d                                                                                 3d
         

代码实现

其实不管是 2d 还是 3d,在 HT 中,数据绑定不分维度的,所以两者在实现上非常类似。

代码下载地址:https://download.csdn.net/download/u013161495/10290996

绘制设备

2d 和 3d 中的设备都是基于下面这张用“矢量”绘制的一个机柜内部设备,并且对这个矢量的“闪烁灯”部分加了数据绑定,具体绑定了“闪烁灯”的背景颜色以及阴影颜色,改变阴影颜色是为了让“灯”有“发光”的效果,下图中的红色方框即为“闪烁灯”。

首先我们必须清楚如何绘制矢量(http://hightopo.com/guide/guide/core/vector/ht-vector-guide.html)?我们这个 Demo 的整体的矢量绘制比较复杂,我就只说一下上图中的“灯”矩形框和文本是怎么绘制的。

我们知道,绘制一个矢量 json 必须包含以下三个参数:

每个元素肯定都是要宽度和高度的,这两个属性不做说明,comps 这个属性倒是挺厉害的,上面第三点中提到了,这是一个数组,绘制图形和文本的实际操作如下:

{
    "width": 48,//矢量整体宽度
    "height": 262,//矢量整体高度
    "comps": [
    {
        "type": "text",//文本
        "text": "端口3",//文本内容
        "align": "center",//文本对齐方式
        "color": "rgb(255,255,255)",//字体颜色
        "font": "8px arial, sans-serif",//文本字体大小
        "rect": [//组件绘制在矢量中的矩形边界
            18.28654,//x 轴坐标
            39.80679,//y 轴坐标
            27.82265,//width
            11.5434//height
        ]
    },
    {
        "type": "rect",//矩形
        "background": "rgb(255,0,0)",//属性默认值"shadow": true,//设置为true显示阴影"shadowOffsetX": 0,//选中图元的阴影水平偏移
        "shadowOffsetY": 0,//选中图元的阴影垂直偏移
        "rect": [//组件绘制在矢量中的矩形边界
            4.38544,//x 轴坐标
            32.55505,//y 轴坐标
            14.46481,//width
            6.1554//height
        ]
    }]
}

这段代码绘制了一个矩形和一个文本。

绘制完矢量之后,我们就可以通过给节点设置图片的方式来显示这个矢量。当然上面绘制的矢量并不是全部的绘制矢量的代码,具体内容请参考:https://download.csdn.net/download/u013161495/10290996

要动态改变一个节点的属性,那么肯定要先获取到这个节点,我们可以通过遍历数据模型 DataModel,或者通过 tag 标签获取节点,又或者通过鼠标点击事件等等。这个 Demo 中需要操作的节点比较多,所以我选择用遍历数据模型的方法来获取节点。那么问题来了,我怎么通过一张图片或者一个矢量定位这个节点?如果节点都没有创建,也不可能获取到图片对应的节点(或者说如果直接把这个矢量图拿来作为一个节点的图片,有可能出现的情况就是,六个设备的变化情况都一模一样!毕竟是同一个节点!)。所以我们得把这些特殊的部分从图片中删除掉,然后在对应的位置填充上节点,再给节点设置上设备的矢量图。先把对应位置的矢量图删除掉,如下图红框部分:

我们在红框部分单独创建八个设备节点,并给这八个节点分别设置同一张矢量图。诶?你可能会诧异为什么同一张图显示却不同(灯亮的变化顺序不同),下面我们来看看这是怎么完成的。

那么这八个拥有相同矢量图的设备是如何通过代码控制闪烁灯随机变化的呢?关键就在我们上面绘制的矢量图中,前面有意略过了这部分:数据绑定。

数据绑定

由于灯闪烁是通过设置矩形的背景颜色来实现的(当然我这里还加了一个阴影,为了有“亮灯”的效果),所以我们对这个矩形的背景颜色属性进行数据绑定,然后通过 data.a 方法获取和设置属性值。

{
    "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 需要注意的就是,相同的图片,如果要显示不同,那么肯定需要创建不同的节点,若是节点相同,那么变化肯定相同的!

快速开发基于 HTML5 网络拓扑图应用之 DataBinding 数据绑定篇的更多相关文章

  1. 快速开发基于 HTML5 网络拓扑图应用

    采用 HT 开发网络拓扑图非常容易,例如<入门手册>的第一个小例子麻雀虽小五脏俱全:http://www.hightopo.com/guide/guide/core/beginners/e ...

  2. 快速开发基于 HTML5 网络拓扑图应用1

    今天开始我们就从最基础解析如何构建 HTML5 Canvas 拓扑图应用,HT 内部封装了一个拓扑图形组件 ht.graph.GraphView(以下简称 GraphView)是 HT 框架中 2D ...

  3. 快速开发基于 HTML5 网络拓扑图应用--入门篇(一)

    计算机网络的拓扑结构是引用拓扑学中研究与大小,形状无关的点.线关系的方法.把网络中的计算机和通信设备抽象为一个点,把传输介质抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构.网络的拓扑结构 ...

  4. 快速开发基于 HTML5 网络拓扑图应用--入门篇(二)

    上一篇我们绘制了一个 graphView 场景,在场景之上通过 graphView.dm() 获取数据容器,并通过 graphView.dm().add() 函数添加了两个 Node 节点,并通过 s ...

  5. 矢量Chart图表嵌入HTML5网络拓扑图的应用

    使用 HT for Web (以下简称 HT)开发HTML5网络拓扑图的开发者有 Chart 需求的项目的时候,感觉很痛苦,HT 集成的 Chart 组件中,并不包含有坐标,在展现方面不是很直观,但是 ...

  6. paip.提高效率---微信 手机app快速开发平台—微网络撬动大市场

    paip.提高效率---微信 手机app快速开发平台-微网络撬动大市场   手机app快速开发平台 尤其适合crm系统,呼叫中心等业务功能...    作者Attilax  艾龙,  EMAIL:14 ...

  7. 使用PhoneGap开发基于Html5应用二:第一个PhoneGap应用:百度

    上一篇博文使用PhoneGap开发基于Html5应用一:PhoneGap简单介绍 中我介绍了怎样从phonegap官网上下载源代码并启动第一个应用,今天我们把phonegap的应用略微改一下,让他实现 ...

  8. 基于HTML5的拓扑图编辑器(2)

    继续来说编辑器的需求, 前面介绍了拖拽创建节点.以及连线的方法,并加入到了其后的 Qunee 类库,实际应用中需要更多功能,Qunee 的拓扑图编辑器也在逐渐完善,一方面增加多种编辑交互,一方面提供数 ...

  9. HTML5 网络拓扑图性能优化

    HTML5 中的 Canvas 对文本的渲染(fillText,strokeText)性能都不太好,比如设置字体(font).文本旋转(rotation),如果绘制较多的文本时,一些交互操作会手动很大 ...

随机推荐

  1. iOS-UI控件优化

    一.tableView的优化 tableView作为iOS开发中使用最为频繁的控件之一,对其进行优化,对整个应用性能的提升显得至关重要.官方设计的框架中,已经包含了UITableViewCell的重用 ...

  2. core java

    ConsoleTest,这个程序如果在IDE里运行就会因无法获得控制台而报错 import java.io.Console; public class ConsoleTest { public sta ...

  3. Opencv 3.3.0 常用函数

    如何调图像的亮度和对比度? //如何增加图片的对比度或亮度? void contrastOrBrightAdjust(InputArray &src,OutputArray &dst, ...

  4. 合唱团 (线性dp)

    题意:有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积 ...

  5. nyoj234 吃土豆 01背包

    思路:假设我们先只考虑一行,规则就是取了i处的土豆,每一个土豆有两种选择,拿与不拿,那么i-1和i+1处的土豆都不能再取,那么要求某一行的最大取值就用一次动态规划即可,dp(i)表示前i个土豆能取得的 ...

  6. Scrum方法论

    产品负责人: 代表客户或未来游戏玩家.产品负责人需要确保所有有趣的功能都能在游戏中实现,还负责对游戏完整观感的理解. Scrum主管: 代表理性思维.需要主持每日Scrum会议,并确保每个人都在执行任 ...

  7. 64位Kali无法顺利执行pwn1问题的解决方案

    问题描述 ​ 环境:VMware Fusion + kali-linux-2018.1-amd64.iso ​ 问题:在Terminal利用./pwn1执行pwn1会出现 bash: ./pwn1:没 ...

  8. js 滚动到一定位置导航定位在页面最顶部

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. ubuntu 下命令行播放器mplayer 使用详解

    ubuntu 下命令行播放器mplayer 使用详解 2011-01-02 21:00:42|  分类: Linux/Unix |  标签: |字号大中小 订阅 使用 MPlayer 播放媒体文件最简 ...

  10. ActiveMQ的运用

    MQ的消息队列模式有2种,一种是点对点模式,一种是订阅模式. 点对点模式:点对点的模式主要建立在一个队列上面,当连接一个列队的时候,发送端不需要知道接收端是否正在接收,可以直接向ActiveMQ发送消 ...