增城企业网站建设,淮南网络科技有限公司,网站商城建设公司,运行一个网站的成本前言用户鼠标移入时#xff0c;有弹出框出现#xff0c;这样的需求很常见。这在处理 HTML 元素实现时简单#xff0c;但是如果是对 HTML5 Canvas 构成的图形进行处理#xff0c;这种方法不再适用#xff0c;因为 Canvas 使用的是另外一套机制#xff0c;无论在 Canvas 上…前言用户鼠标移入时有弹出框出现这样的需求很常见。这在处理 HTML 元素实现时简单但是如果是对 HTML5 Canvas 构成的图形进行处理这种方法不再适用因为 Canvas 使用的是另外一套机制无论在 Canvas 上绘制多少图形Canvas 都是一个整体。而图形本身实际都是 Canvas 的一部分不可单独获取所以也就无法直接给某个图形增加 JavaScript 事件。然而在HT for Web 中这种需求很容易实现场景如下这个场景图是基于 HT for Web 的 JSON 文件可能大家对怎么生成这样的 JSON 文件有疑惑其实这里是基于这个麻雀虽小五脏俱全的 “HTML5拓扑图编辑器” http://www.hightopo.com/demo/2deditor_20151010/HT-2D-Editor.html 进行了扩展很容易就自定义出满足我需求拓扑编辑器。不仅如此在这个 Demo 中定义的三种类型弹框的矢量图 ‘tips1.json’、‘tips2.json’、‘tips3.json’ 是通过这个矢量编辑器http://www.hightopo.com/demo/vector-editor/index.html 简单绘制了下也还蛮好用。在上述场景中用户将鼠标移入到草地等对象时会有弹出框显示它的详细信息Demo地址http://www.hightopo.com/demo/blog_meadow_20170605/index.html具体实现准备工作引入我们的HThttp://www.hightopo.com/ script srcht.js/scriptdataModel new ht.DataModel();
graphView new ht.graph.GraphView(dataModel);
graphView.addToDOM();HT 提供了自定义的 JSON 格式的矢量描述形式以HT标准定义的 JSON 矢量格式也可以作为图片进行注册和使用HT 的矢量方式比传统格式更节省空间缩放不失真戳 HT for Web 了解详细信息。这里将三种形状的 JSON 弹出框注册成图片以便后续调用ht.Default.setImage(tips1, symbols/tips1.json);
ht.Default.setImage(tips2, symbols/tips2.json);
ht.Default.setImage(tips3, symbols/tips3.json);然后获取有交互效果的对象其中各个对象中的属性名是给各个图元设置好的标签名// 树
var tree {tree1 : true,tree2 : true,tree3 : true
};// 草地
var grass {grass1 : true,grass2 : true,grass3 : true};// 山
var mountain {mountain: true
};弹出框其实弹出框的本质是一个 Node当用户鼠标移入移出时1、控制Node的隐藏和显示可以达到弹框的效果2、鼠标位置的改变伴随着Node位置的改变3、鼠标移入到不同的对象上时Node上的贴图也跟着发生变化4、Node 中的属性值也随着鼠标位置发生变化。所以要实现弹框首先应新建 Node并将其的层级设置为 ‘higher’在这之前还需要将场景图的 JSON 文件反序列化并且给反序列化后的图元均设置为层级 ‘lower’ 防止被已有的图元挡住ht.Default.xhrLoad(meadow.json, function(text) {const json ht.Default.parse(text); if(json.title) document.title json.title;dataModel.deserialize(json);// 设置层级dataModel.each(function(data){data.setLayer(lower);});// 新建nodevar node new ht.Node(); node.s(2d.visible,false);node.setLayer(higher);dataModel.add(node);})然后对底层的 DIV 监听 mousemove 事件判断鼠标的位置是否在上述三个对象之上根据对象类型调用 layout() 函数对 Node 重新布局graphView.getView().addEventListener(mousemove, function(e) {node.s(2d.visible,false);var hoverData graphView.getDataAt(e);pos graphView.getLogicalPoint(e);if(!hoverData) return; if(tree[hoverData.getTag()]){ layout(node, pos, tips1);} else if (grass[hoverData.getTag()]) {layout(node, pos, tips2);} else if (mountain[hoverData.getTag()]) {layout(node, pos, tips3);}
});layout() 函数所做的事情已经在前面详细的阐述其中弹框中属性值的更新是将 JSON 文件的的 text 属性进行数据绑定绑定的格式很简单只需将以前的参数值用一个带 func 属性的对象替换即可func 的内容有一下几种类型1、function类型直接调用该函数并传入相关Data和view对象由函数返回值决定参数值即func(data, view)调用。2、string类型style*** 开头则返回 data.getStyle(***) 值其中 *** 代表 style 的属性名。attr*** 开头则返回 data.getAttr(***) 值其中 *** 代表 attr 的属性名。field*** 开头则返回 data.*** 值其中 *** 代表 attr 的属性名。如果不匹配以上几种情况则直接将 string 类型作为 data 对象的函数名调用 data***(view)返回值作为参数值。除了 func 属性外还可以设置 value 属性作为默认值如果对应的 func 取得的值为 undefined 或者 null 时则会采用 value 属性定义的默认值详情可见 HT for Web 数据绑定手册数据模型手册 - HT for Web 。例如在这里tips1.json 文件中对阳光值进行数据绑定的结果如下text: {func: attrsunshine,value: 阳光值
}下面贴上 layout() 函数的源代码function layout(node, pos, type){node.s(2d.visible,true);node.setImage(type); if(type tips1){node.setPosition(pos.x node.getWidth()/2, pos.y - node.getHeight()/2);node.a({sunshine : 阳光值 : (pos.x/1000).toFixed(2),rain : 雨露值 : (pos.y/1000).toFixed(2),love : 爱心值 ***});} else if(type tips2){node.setPosition(pos.x , pos.y - node.getHeight()/2);node.a({temp : 温度 : 30,humidity : 湿度 : Math.round(pos.x/100)%});} else if(type tips3){node.setPosition(pos.x - node.getWidth()/2, pos.y - node.getHeight()/2);node.a({hight : 海拔 : Math.round(pos.y)米,landscapes : 地貌 : 喀斯特});}
}云移动最后我们的 Demo 还有个云移动的动画效果在 HT 的数据模型驱动的图形组件的设计架构下动画可理解为将某些属性由起始值逐渐变为目标值的过程HT 提供了 ht.Default.startAnim 的动画函数ht.Default.startAnim 支持 Frame-Based 和 Time-Based 两种方式的动画Frame-Based 方式用户通过指定 frames 动画帧数以及 interval 动画帧间隔参数控制动画效果Time-Based 方式用户只需要指定 duration 的动画周期的毫秒数即可HT 将在指定的时间周期内完成动画。详情见 HT for Web。在这里我们用的是 Time-Based 方式源码如下var cloud dataModel.getDataByTag(cloud);
parent dataModel.getDataByTag(mountain);
round1 parent.getPosition().x - parent.getWidth()/2 cloud.getWidth()/2;
round2 parent.getPosition().x parent.getWidth()/2 - cloud.getWidth()/2;
end round1;// 云运动动画
var animParam {duration: 10000,finishFunc: function() { end (end round1) ? round2 : round1;ht.Default.startAnim(animParam);},action: function(v, t) {var p cloud.getPosition();cloud.setPosition(p.x (end - p.x) * v , p.y);}
};
ht.Default.startAnim(animParam);总结最后再放上我们的 Demo 供大家参考。