MyException - 我的异常网
当前位置:我的异常网» HTML5 » 快速开发基于 HTML5 网络拓扑图当用之 DataBinding

快速开发基于 HTML5 网络拓扑图当用之 DataBinding 数据绑定篇

www.MyException.Cn  网友分享于:2018-04-03  浏览:1次
快速开发基于 HTML5 网络拓扑图应用之 DataBinding 数据绑定篇

前言

发现大家对于我从 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 必须包含以下三个参数:

  • width 矢量图形的宽度
  • height 矢量图形的高度
  • comps 矢量图形的组件 Array 数组,每个数组对象为一个独立的组件类型(http://hightopo.com/guide/guide/core/vector/ht-vector-guide.html#ref_type),数组的顺序为组件绘制先后顺序

每个元素肯定都是要宽度和高度的,这两个属性不做说明,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 需要注意的就是,相同的图片,如果要显示不同,那么肯定需要创建不同的节点,若是节点相同,那么变化肯定相同的!

文章评论

聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
旅行,写作,编程
旅行,写作,编程
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
为什么程序员都是夜猫子
为什么程序员都是夜猫子
程序员都该阅读的书
程序员都该阅读的书
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
我的丈夫是个程序员
我的丈夫是个程序员
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
那些争议最大的编程观点
那些争议最大的编程观点
每天工作4小时的程序员
每天工作4小时的程序员
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
编程语言是女人
编程语言是女人
Java程序员必看电影
Java程序员必看电影
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
中美印日四国程序员比较
中美印日四国程序员比较
 程序员的样子
程序员的样子
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序员和编码员之间的区别
程序员和编码员之间的区别
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
如何成为一名黑客
如何成为一名黑客
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
鲜为人知的编程真相
鲜为人知的编程真相
10个调试和排错的小建议
10个调试和排错的小建议
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员应该关注的一些事儿
程序员应该关注的一些事儿
漫画:程序员的工作
漫画:程序员的工作
我是如何打败拖延症的
我是如何打败拖延症的
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
程序员必看的十大电影
程序员必看的十大电影
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
老程序员的下场
老程序员的下场
代码女神横空出世
代码女神横空出世
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有