敏捷支付基于,的交互式地铁线路图

据悉 HTML5 Canvas 的交互式地铁线路图

2018/03/14 · HTML5 ·
Canvas

原文出处: xhload3d   

 前言

前二日在 echarts
上搜索灵感的时候,看到了累累有关地图类似的事例,地图定位等等,可是好像就是从未大巴线路图,就融洽花了一部分小时捣鼓出来了那一个交互式地铁线路图的
Demo,大巴线路上的点是在网上随便下载了一个,这篇小说记录自己的有些得到(毕竟我要么个菜鸟)以及代码的贯彻,希望可以帮到一些对象。当然,假若有哪些意见的可以直接跟自己说,大家一齐互换才会向上。

分子力(molecular
force),又称分子间成听从、范得瓦耳斯力,是指成员间的相互功能。当二分子相距较远时,首要表现为吸引力,这种力重点来源一个成员被另一个成员随时间火速生成的电偶极矩所极化而滋生的彼此功用;当二分子极度类似时,则排斥力成为重中之重的,这是出于各成员的外层电子云开始重叠而发生的排斥功效。

根据自身的项目执行意况,首若是多少个关键点:

上一篇大家绘制了一个 graphView 场景,在场景之上通过 graphView.dm()
获取数据容器,并透过 graphView.dm().add() 函数添加了五个 Node
节点,并由此 setPosition 设置节点地点以及 setImage
给节点添加图片;接着在八个节点之间通过 ht.Edge(sourceNode, targetNode)
添加了两条连线(实际上还是可以更多),并给连线添加了 label
标签展现文字,同时也通过 label.position 设置了文字在连线上的职位。

效果图

亚洲必赢官网 1

地图稍微内容有点多,要全体来得,字显得有点小了,但是没什么,可以服从必要加大减少,字体和制图的内容并不会失真,毕竟都是用矢量绘制的~

HT for Web提供了弹力布局(也号称力导向布局)的功效,即基于节点之间存在互斥力,相互连接的节点间存在引力,
弹力布局运行一段时间后,全体拓扑网络布局会日趋达到没有稳定的平衡情况。那几个效应很风趣,明天我们就将它的魅力展现出来。

1:协助静态的树,即两次性将所有多少加载到客户端。
2:异步树,即四遍只加载一级或若干级节点,子节点可以异步加载数据。
3:Checkbox树(可能是静态树也恐怕是异步树),用于拔取(如选用社团单位,选用数据字典项)等,最好是力所能及扶助节点级联(这一个是难题)
4:可以承接大数据量,并品质表现卓越
5:可以在主流浏览器中运作卓绝

这一篇我的想法是在右边添加一个来得所有节点的“树”节点列表,就是将气象中装有的节点都加上到这一个“树”列表中。这一个部分在我看来简直是简容易单到极点啊,当然,HT
很多零件都跟那个看似,分外有益。

界面生成

底层的 div 是因而 ht.graph.GraphView 组件生成的,然后就可以运用 HT for
Web 提供好的法子,调用 canvas 画笔随便绘制就好,先来探视怎么生成底层
div:

var dm = new ht.DataModel();//数据容器 var gv = new
ht.graph.GraphView(dm);//拓扑组件
gv.addToDOM();//将拓扑图组件添加进body中

1
2
3
var dm = new ht.DataModel();//数据容器
var gv = new ht.graph.GraphView(dm);//拓扑组件
gv.addToDOM();//将拓扑图组件添加进body中

addToDOM 函数声明如下:

addToDOM = function(){ var self = this, view = self.getView(), style =
view.style; document.body.appendChild(view); //将组件底层div添加到body中
style.left = ‘0’;//默许组件是纯属定位,所以要设置职分 style.right = ‘0’;
style.top = ‘0’; style.bottom = ‘0’; window.add伊芙ntListener(‘resize’,
function () { self.iv(); }, false); //窗口变化事件 }

1
2
3
4
5
6
7
8
9
10
11
addToDOM = function(){  
    var self = this,
        view = self.getView(),  
        style = view.style;
    document.body.appendChild(view); //将组件底层div添加到body中          
    style.left = ‘0’;//默认组件是绝对定位,所以要设置位置
    style.right = ‘0’;
    style.top = ‘0’;
    style.bottom = ‘0’;      
    window.addEventListener(‘resize’, function () { self.iv(); }, false); //窗口变化事件          
}

今昔自己就可以在这些 div
上乱涂乱画了~首先自己赢得下载好的客车线路图上的点,我将它们位于 subway.js
中,那个 js
文件全体都是下载的始末,我从不做其余的变动,重若是将这些点按照线路来分分配添加到数组中,比如:

mark_Point13 = [];//线路
数组内包括线路的源点和顶峰坐标以及那条路线的称呼 t_Point13 =
[];//换成站点 数组内包含线路中的换乘站点坐标以及换成站点名称
n_Point13 = [];//小站点 数组内包罗线路中的小站点坐标以及小站点名称
mark_Point13.push({ name: ‘十三号线’, value: [113.4973,23.1095]});
mark_Point13.push({ name: ‘十三号线’, value: [113.4155,23.1080]});
t_Point13.push({ name: ‘鱼珠’, value: [亚洲必赢官网 ,113.41548,23.10547]});
n_Point13.push({ name: ‘裕丰围’, value: [113.41548,23.10004]});

1
2
3
4
5
6
7
mark_Point13 = [];//线路 数组内包含线路的起点和终点坐标以及这条线路的名称
t_Point13 = [];//换成站点 数组内包含线路中的换乘站点坐标以及换成站点名称
n_Point13 = [];//小站点 数组内包含线路中的小站点坐标以及小站点名称
mark_Point13.push({ name: ‘十三号线’, value: [113.4973,23.1095]});
mark_Point13.push({ name: ‘十三号线’, value: [113.4155,23.1080]});
t_Point13.push({ name: ‘鱼珠’, value: [113.41548,23.10547]});
n_Point13.push({ name: ‘裕丰围’, value: [113.41548,23.10004]});

接下去来形容客车线路,我评释了一个数组 lineNum,用来装 js
中拥有的大巴线路的数码,以及一个 color
数组,用来装所有的地铁线的水彩,这个颜色的 index 与 lineNum
中大巴线编号的 index 是逐一对应的:

var lineNum = [‘1’, ‘2’, ‘3’, ’30’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ’13’,
’14’, ’32’, ’18’, ’21’, ’22’, ’60’, ’68’]; var color = [‘#f1cd44’,
‘#0060a1’, ‘#ed9b4f’, ‘#ed9b4f’, ‘#007e3a’, ‘#cb0447’, ‘#7a1a57’,
‘#18472c’, ‘#008193’, ‘#83c39e’, ‘#8a8c29’, ‘#82352b’, ‘#82352b’,
‘#09a1e0’, ‘#8a8c29’, ‘#82352b’, ‘#b6d300’, ‘#09a1e0’];

1
2
var lineNum = [‘1’, ‘2’, ‘3’, ’30’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ’13’, ’14’, ’32’, ’18’, ’21’, ’22’, ’60’, ’68’];
var color = [‘#f1cd44’, ‘#0060a1’, ‘#ed9b4f’, ‘#ed9b4f’, ‘#007e3a’, ‘#cb0447’, ‘#7a1a57’, ‘#18472c’, ‘#008193’, ‘#83c39e’, ‘#8a8c29’, ‘#82352b’, ‘#82352b’, ‘#09a1e0’, ‘#8a8c29’, ‘#82352b’, ‘#b6d300’, ‘#09a1e0’];

跟着遍历 lineNum,将 lineNum 中的元素和颜料传到 createLine
函数中,按照那五个参数来绘制地铁线路以及配色,毕竟 js
文件中的命名格局也是有规律的,哪一条线路,则命名前边必然会加上对应的数字,所以大家只必要将字符串与这些编号结合即可取得
js 中对应的数组了:

let lineName = ‘Line’ + num; let line = window[lineName];

1
2
let lineName = ‘Line’ + num;
let line = window[lineName];

createLine
的概念也相当简单,我的代码设置了很多的体裁,所以看起来有点多。创设一个
ht.Polyline 管线,我们得以由此 polyline.addPoint()
函数向那些变量中添加具体的点,通过 setSegments 可以设置点的总是方式。

function createLine(num, color) {//绘制地图线 var polyline = new
ht.Polyline();//多边形 管线
polyline.setTag(num);//设置节点tag标签,作为唯一标示 if(num === ’68’)
polyline.setToolTip(‘A P M’);//设置提醒消息 else if(num === ’60’)
polyline.setToolTip(‘G F’); else polyline.setToolTip(‘Line’ + num);
if(color) { polyline.s({//s 为 setStyle 的简写,设置样式
‘shape.border.width’: 0.4,//设置多边形的边框宽度 ‘shape.border.color’:
color,//设置多边形的边框颜色 ‘select.width’:
0.2,//设置选中节点的边框宽度 ‘select.color’:
color//设置选中节点的边框颜色 }); } let lineName = ‘Line’ + num; let
line = window[lineName]; for(let i = 0; i < line.length; i++) {
for(let j = 0; j < line[i].coords.length; j++) {
polyline.addPoint({x: line[i].coords[j][0]*300, y:
-line[i].coords[j][1]*300}); if(num ===
’68’){//APM线(有两条,不过点是在同一个数组中的) if(i === 0 && j === 0)
{ polyline.setSegments([1]); } else if(i === 1 && j === 0) {
polyline.getSegments().push(1); } else { polyline.getSegments().push(2);
} } } } polyline.setLayer(‘0’);//将线设置在下层,点设置在上层“top”
dm.add(polyline);//将管线添加进数据容器中贮存,不然那些管线属于“游离”状态,是不会来得在拓扑图上的
return polyline; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function createLine(num, color) {//绘制地图线
    var polyline = new ht.Polyline();//多边形 管线
    polyline.setTag(num);//设置节点tag标签,作为唯一标示
    
    if(num === ’68’) polyline.setToolTip(‘A P M’);//设置提示信息
    else if(num === ’60’) polyline.setToolTip(‘G F’);
    else polyline.setToolTip(‘Line’ + num);
 
    if(color) {
        polyline.s({//s 为 setStyle 的简写,设置样式
            ‘shape.border.width’: 0.4,//设置多边形的边框宽度
            ‘shape.border.color’: color,//设置多边形的边框颜色
            ‘select.width’: 0.2,//设置选中节点的边框宽度
            ‘select.color’: color//设置选中节点的边框颜色
        });
    }
 
    let lineName = ‘Line’ + num;
    let line = window[lineName];
    for(let i = 0; i < line.length; i++) {
        for(let j = 0; j < line[i].coords.length; j++) {
            polyline.addPoint({x: line[i].coords[j][0]*300, y: -line[i].coords[j][1]*300});
            if(num === ’68’){//APM线(有两条,但是点是在同一个数组中的)
                if(i === 0 && j === 0) {
                    polyline.setSegments([1]);
                }
                else if(i === 1 && j === 0) {
                    polyline.getSegments().push(1);
                }
                else {
                    polyline.getSegments().push(2);
                }
            }    
        }
    }
 
    polyline.setLayer(‘0’);//将线设置在下层,点设置在上层“top”
    dm.add(polyline);//将管线添加进数据容器中储存,不然这个管线属于“游离”状态,是不会显示在拓扑图上的
    return polyline;
}

地方代码中添加大巴线上的点有分为三种意况,是因为 js 中设置线的时候
Line68 有一个“跳跃”点的意况,所以大家不可以不“跳跃”过去,篇幅有限 Line68
数组具体的扬言自行看 subway.js。

此处表明某些,要是用的是 addPoint 函数,不安装 segments
时,默许将添加进的点用直线连接,segments 的概念如下:

  • 1: moveTo,占用 1 个点新闻,代表一个新路线的起点
  • 2: lineTo,占用 1 个点新闻,代表从上次最终点连接到该点
  • 3: quadraticCurveTo,占用 2
    个点音讯,第一个点作为曲线控制点,第三个点作为曲线截止点
  • 4: bezierCurveTo,占用 3
    个点音讯,第一和第三个点作为曲线控制点,第二个点作为曲线停止点
  • 5:
    closePath,不占用点音信,代表本次路径绘制截至,并关闭到路径的早先点

所以大家要做“跳跃”的作为设置 segments 为 1 即可。

最终绘制这几个大巴线上的点,这些有些 subway.js
中也分离出来了,命名以“mark_Point”、“t_Point”以及“n_Point”初阶,我在面前
js 的显得部分有对那一个数组举行分解,我们动动中指划上去看望。

俺们在这一个点的义务添加 ht.Node 节点,当节点一添加进 dm
数据容器中时,就会在拓扑图上展现,当然,前提是以此拓扑图组件 gv
设置的数目容器是那么些dm。篇幅有限,添加大巴线上的点的代码部分自己只突显丰盛“换乘站点”的点:

var tName = ‘t_Point’ + num; var tP = window[tName];//大站点 if(tP)
{//有些线路没有“换乘站点” for(let i = 0; i < tP.length; i++) { let
node = createNode(tP[i].name, tP[i].value,
color[index]);//在收获的路线上的点的坐标地方添加节点
node.s({//设置节点的体裁style ‘label.scale’:
0.05,//文本缩放,可以幸免浏览器限制的细小字号难点 ‘label.font’: ‘bold
12px arial, sans-serif’//设置文本的font }); node.setSize(0.6,
0.6);//设置节点大小。由于js中各类点时期的偏移量太小,所以我只好把节点设置小片段
node.setImage(‘images/旋转箭头.json’);//设置节点的图样
node.a(‘alarmColor1’, ‘rgb(150, 150,
150)’);//attr属性,可以在那其中安装任何的东西,alarmColor1是在地点安装的image的json中绑定的特性,具体参看
HT for Web
矢量手册()
node.a(‘alarmColor2’, ‘rgb(150, 150, 150)’);//同上 node.a(‘tpNode’,
true);//那一个特性设置只是为着用来不一样“换乘站点”和“小站点”的,前边会用上 }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var tName = ‘t_Point’ + num;
var tP = window[tName];//大站点
if(tP) {//有些线路没有“换乘站点”
    for(let i = 0; i < tP.length; i++) {
        let node = createNode(tP[i].name, tP[i].value, color[index]);//在获取的线路上的点的坐标位置添加节点
        node.s({//设置节点的样式style
            ‘label.scale’: 0.05,//文本缩放,可以避免浏览器限制的最小字号问题
            ‘label.font’: ‘bold 12px arial, sans-serif’//设置文本的font
        });
        node.setSize(0.6, 0.6);//设置节点大小。由于js中每个点之间的偏移量太小,所以我不得不把节点设置小一些
        node.setImage(‘images/旋转箭头.json’);//设置节点的图片
        node.a(‘alarmColor1’, ‘rgb(150, 150, 150)’);//attr属性,可以在这里面设置任何的东西,alarmColor1是在上面设置的image的json中绑定的属性,具体参看 HT for Web 矢量手册(http://www.hightopo.com/guide/guide/core/vector/ht-vector-guide.html#ref_binding)
        node.a(‘alarmColor2’, ‘rgb(150, 150, 150)’);//同上
        node.a(‘tpNode’, true);//这个属性设置只是为了用来区分“换乘站点”和“小站点”的,后面会用上
    }
}

所有的地铁线路以及站点都丰硕落成。可是!你可能会看不见自己绘制的图,因为她俩太小了,那一个时候可以设置
graphView 拓扑组件上的 fitContent
函数,大家顺便将拓扑图上的享有东西不足移动也设置一下:

gv.fitContent(false,
0.00001);//自适应大小,参数1为是或不是动画,参数2为gv与边框的padding值
gv.setMovableFunc(function(){ return false;//设置gv上的节点不可移动 });

1
2
3
4
gv.fitContent(false, 0.00001);//自适应大小,参数1为是否动画,参数2为gv与边框的padding值
gv.setMovableFunc(function(){
    return false;//设置gv上的节点不可移动
});

那下你的大巴线路图就可以突显啦~接下来看看互相。

本例地址:

那我要创立的TreeView就是为了促成这些5个主要目标的。

首先大家得创设那一个“树”,HT
中的 ht.widget.treeView 组件就是用来创建“树列表”的。大家在上一篇中有介绍过
addToDOM 函数,用来将零件添加进 body
体中,我们要促成左侧是“数列表”左侧是拓扑场景,该如何做吗?那里再引入一个零部件 ht.widget.SplitView,顾名思义“分割”组件。分割组件用于左右或左右分割四个子组件,
子组件可为HT框架提供的零部件,也可为 HTML 的原生组件,子组件以 position
为 absolute 方式开展相对定位。

交互

率先是鼠标移动事件,鼠标滑过具体路线时,线路会变粗,悬停一会儿还是能看到那条线路的编号;当鼠标移动到“换乘站点”或“小站点”,站点对应的图标都会变大并且变色,字体也会变大,鼠标移开图标变回原来的水彩并且字体变小。分裂点在于鼠标移动到“换乘站点”时,“换乘站点”会旋转。

亚洲必赢官网 2

鼠标滑动事件,我直接基于 gv 的底层 div 举行的 mousemove 事件,通过 ht
封装的 getDataAt 函数传入事件 event
参数,获取事件下相应的节点,然后就足以轻易操作节点了:

gv.getView().add伊芙ntListener(‘mousemove’, function(e) { var data =
gv.getDataAt(e);//传入逻辑坐标点或者交互event事件参数,重临当前点下的图元
if(name) { originNode(name);//不管几时都要让节点保持原来的大小 } if
(data instanceof ht.Polyline) {//判断事件节点的体系dm.sm().ss(data);//选中“管道” name = ”; clearInterval(interval); } else
if (data instanceof ht.Node) { if(data.getTag() !== name &&
data.a(‘tpNode’))
{//若不是同一个节点,并且mousemove的事件目的为ht.Node类型,那么设置节点的转动
interval = setInterval(function() { data.setRotation(data.getRotation()

  • Math.PI/16); //在本人旋转的根基上再旋转 }, 100); }
    if(data.a(‘npNode’)) {//假如鼠标移到“小站点”也要停下动画
    clearInterval(interval); } expandNode(data,
    name);////自定义的加大节点函数,比较简单,我不粘代码了,可以去
    查看 dm.sm().ss(data);//设置选中节点 name =
    data.getTag();//作为“上一个节点”的蕴藏变量,可以透过这几个值来取得节点 }
    else {//其他任何动静则不选中任何内容还要消除“换乘站点”上的卡通
    dm.sm().ss(null); name = ”; clearInterval(interval); } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
gv.getView().addEventListener(‘mousemove’, function(e) {
    var data = gv.getDataAt(e);//传入逻辑坐标点或者交互event事件参数,返回当前点下的图元
    if(name) {
        originNode(name);//不管什么时候都要让节点保持原来的大小
    }
 
    if (data instanceof ht.Polyline) {//判断事件节点的类型
        dm.sm().ss(data);//选中“管道”
        name = ”;
        clearInterval(interval);
    }
    else if (data instanceof ht.Node) {
        if(data.getTag() !== name && data.a(‘tpNode’)) {//若不是同一个节点,并且mousemove的事件对象为ht.Node类型,那么设置节点的旋转
            interval = setInterval(function() {
                data.setRotation(data.getRotation() – Math.PI/16); //在自身旋转的基础上再旋转
            }, 100);
        }
        if(data.a(‘npNode’)) {//如果鼠标移到“小站点”也要停止动画
            clearInterval(interval);
        }
        expandNode(data, name);////自定义的放大节点函数,比较容易,我不粘代码了,可以去http://hightopo.com/   查看
        dm.sm().ss(data);//设置选中节点
        name = data.getTag();//作为“上一个节点”的存储变量,可以通过这个值来获取节点
    }
    else {//其他任何情况则不选中任何内容并且清除“换乘站点”上的动画
        dm.sm().ss(null);
        name = ”;
        clearInterval(interval);
    }
});

鼠标悬停在大巴线路上时显示“具体路线新闻”,我是通过安装 tooltip
来形成的(注意:要打开 gv 的 tooltip 开关):

gv.enableToolTip();//打开 tooltip 的开关 if(num === ’68’)
polyline.setToolTip(‘A P M’);//设置提示音讯 else if(num === ’60’)
polyline.setToolTip(‘G F’); else polyline.setToolTip(‘Line’ + num);

1
2
3
4
gv.enableToolTip();//打开 tooltip 的开关
if(num === ’68’) polyline.setToolTip(‘A P M’);//设置提示信息
else if(num === ’60’) polyline.setToolTip(‘G F’);
else polyline.setToolTip(‘Line’ + num);

下一场自己利用右下角的 form
表单,单击表单上的切实线路,或者双击拓扑图上肆意一个“站点”或者线路,则拓扑图会自适应到对应的局地,将被双击的局地展现到拓扑图的焦点。

亚洲必赢官网 3

form 表单的声明部分自己好像还不曾表达。。。就是经过 new 一个
ht.widget.FomePane 类创立一个 form 表单组件,通过 form.getView()
获取表单组件的底部 div,将以此 div 摆放在 body 右下角,然后经过 addRow
函数向 form 表单中添加一行的表单项,可以在那行中添加任意多少个项,通过
addRow
函数的第四个参数(一个数组),对添加进的表单项举办大幅度的安装,通过第多个参数设置这行的冲天:

function createForm() {//创立右下角的form表单 var form = new
ht.widget.FormPane(); form.setWidth(200);//设置表单宽度
form.setHeight(416);//设置表单高度 let view = form.getView();
document.body.appendChild(view);//将表单添加进body中 view.style.zIndex =
1000; view.style.bottom = ’10px’;//ht组件大约都设置相对路径
view.style.right = ’10px’; view.style.background = ‘rgba(211, 211, 211,
0.8)’; names.forEach(function(nameString) {
form.addRow([//向表单中添加行 {//这一行中的第四个表单项 button:
{//向表单中添加button按钮 icon:
‘images/Line’+nameString.value+’.json’,//设置按钮的图标 background:
”,//设置按钮的背景 borderColor: ”,//设置按钮的边框颜色 clickable:
false//设置按钮不可点击 } }, {//第四个表单项 button: { label:
nameString.name, labelFont: ‘bold 14px arial, sans-serif’, labelColor:
‘#fff’, background: ”, borderColor: ”, onClicked: function()
{//按钮点击回调事件
gv.sm().ss(dm.getDataByTag(nameString.value));//设置选中按下的按钮对应的线路
gv.fitData(gv.sm().ld(), true, 5);//将入选的大巴线路突显在拓扑图的主题 }
} } ], [敏捷支付基于,的交互式地铁线路图。0.1, 0.2],
23);//第一个参数是安装第一参数中的数组的增幅,小于1是比例,大于1是实际上增幅。第五个参数是该行的莫大
}); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function createForm() {//创建右下角的form表单
    var form = new ht.widget.FormPane();
    form.setWidth(200);//设置表单宽度
    form.setHeight(416);//设置表单高度
    let view = form.getView();
    document.body.appendChild(view);//将表单添加进body中
    view.style.zIndex = 1000;
    view.style.bottom = ’10px’;//ht组件几乎都设置绝对路径
    view.style.right = ’10px’;
    view.style.background = ‘rgba(211, 211, 211, 0.8)’;
 
    names.forEach(function(nameString) {
        form.addRow([//向表单中添加行
            {//这一行中的第一个表单项
                button: {//向表单中添加button按钮
                    icon: ‘images/Line’+nameString.value+’.json’,//设置按钮的图标
                    background: ”,//设置按钮的背景
                    borderColor: ”,//设置按钮的边框颜色
                    clickable: false//设置按钮不可点击
                }
            },
            {//第二个表单项
                button: {
                    label: nameString.name,
                    labelFont: ‘bold 14px arial, sans-serif’,
                    labelColor: ‘#fff’,
                    background: ”,
                    borderColor: ”,
                    onClicked: function() {//按钮点击回调事件
                        gv.sm().ss(dm.getDataByTag(nameString.value));//设置选中按下的按钮对应的线路
                        gv.fitData(gv.sm().ld(), true, 5);//将选中的地铁线路显示在拓扑图的中央
                    }
                }
            }
        ], [0.1, 0.2], 23);//第二个参数是设置第一参数中的数组的宽度,小于1是比例,大于1是实际宽度。第三个参数是该行的高度
    });
}

单击“站点”展现青色标注,双击节点自适应放置到拓扑图中心以及双击空白处将黑色标注隐藏的情节都是通过对拓扑组件
gv 的风云监听来控制的,分外清晰易懂,代码如下:

var node = createRedLight();//创建一个新的节点,突显为“红灯”的样式
gv.mi(function(e) {//ht 中拓扑组件中的事件监听 if(e.kind === ‘clickData’
&& (e.data.a(‘tpNode’) || e.data.a(‘npNode’)))
{//e.kind获取当前事变类型,e.data获取当前风云下的节点
node.s(‘2d.visible’, true);//设置node节点可知node.setPosition(e.data.getPosition().x,
e.data.getPosition().y);//设置node的坐标为当下风云下节点的义务 } else
if(e.kind === ‘doubleClickData’) {//双击节点 gv.fitData(e.data, false,
10);//将事件下的节点自适应到拓扑图的宗旨,参数1为自适应的节点,参数2为是不是动画,参数3为gv与边框的padding
} else if(e.kind === ‘doubleClickBackground’) {//双击空白处
node.s(‘2d.visible’, false);//设置node节点不可知 查看 HT for Web
样式手册(
} });

1
2
3
4
5
6
7
8
9
10
11
12
13
var node = createRedLight();//创建一个新的节点,显示为“红灯”的样式
gv.mi(function(e) {//ht 中拓扑组件中的事件监听
    if(e.kind === ‘clickData’ && (e.data.a(‘tpNode’) || e.data.a(‘npNode’))) {//e.kind获取当前事件类型,e.data获取当前事件下的节点
        node.s(‘2d.visible’, true);//设置node节点可见
        node.setPosition(e.data.getPosition().x, e.data.getPosition().y);//设置node的坐标为当前事件下节点的位置
    }
    else if(e.kind === ‘doubleClickData’) {//双击节点
        gv.fitData(e.data, false, 10);//将事件下的节点自适应到拓扑图的中央,参数1为自适应的节点,参数2为是否动画,参数3为gv与边框的padding
    }
    else if(e.kind === ‘doubleClickBackground’) {//双击空白处
        node.s(‘2d.visible’, false);//设置node节点不可见 查看 HT for Web 样式手册(http://www.hightopo.com/guide/guide/core/theme/ht-theme-guide.html#ref_style)
    }
});

只顾 s(style) 和 a(attr) 定义是这样的,s 是 ht
预约义的部分样式属性,而 a
是大家用户来源定义的性质,一般是透过调用字符串来调用结果的,那一个字符串对应的可以是常量也得以是函数,如故很灵巧的。

末尾还做了一个不大的有些,选中“站点”,则该“站点”的顶端会来得一个革命的会“呼吸”的用来评释当前相中的“站点”。

亚洲必赢官网 4

“呼吸”的一些是使用 ht 的 setAnimation
函数来已毕的,在用这几个函数从前要先开辟数据容器的卡通开关,然后设置动画:

dm.enableAnimation();//打开数据容器的动画片开关 function createRedLight()
{ var node = new ht.Node();
node.setImage(‘images/红灯.json’);//设置节点的图片 node.setSize(1,
1);//设置节点的轻重 node.setLayer(‘firstTop’);//设置节点呈现在gv的最上层
node.s(‘2d.visible’, false);//节点不可知 node.s(‘select.width’,
0);//节点选中时的边框为0,不可知 node.s(‘2d.selectable’,
false);//设置这么些特性,则节点不可选中 node.setAnimation({//设置动画
具体参见 HT for Web
动画手册(
expandWidth: { property: “width”,//设置这些特性,并且未安装
accessType,则默认通过 setWidth/getWidth 来设置和获取属性。那里的 width
和底下的 height 都是透过前边设置的 size 获得的 from: 0.5,
//动画开始时的属性值 to: 1,//动画停止时的习性值 next:
“collapseWidth”//字符串类型,指定当前动画达成未来,要履行的下个卡通,可将两个卡通融合
}, collapseWidth: { property: “width”, from: 1, to: 0.5, next:
“expandWidth” }, expandHeight: { property: “height”, from: 0.5, to: 1,
next: “collapseHeight” }, collapseHeight: { property: “height”, from: 1,
to: 0.5, next: “expandHeight” }, start: [“expandWidth”,
“expandHeight”]//数组,用于指定要启动的一个或八个动画 }); dm.add(node);
return node; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
dm.enableAnimation();//打开数据容器的动画开关
function createRedLight() {
    var node = new ht.Node();
    node.setImage(‘images/红灯.json’);//设置节点的图片
    node.setSize(1, 1);//设置节点的大小
    node.setLayer(‘firstTop’);//设置节点显示在gv的最上层
    node.s(‘2d.visible’, false);//节点不可见
    node.s(‘select.width’, 0);//节点选中时的边框为0,不可见
    node.s(‘2d.selectable’, false);//设置这个属性,则节点不可选中
 
    node.setAnimation({//设置动画 具体参见 HT for Web 动画手册(http://www.hightopo.com/guide/guide/plugin/animation/ht-animation-guide.html)
        expandWidth: {
            property: "width",//设置这个属性,并且未设置 accessType,则默认通过 setWidth/getWidth 来设置和获取属性。这里的 width 和下面的 height 都是通过前面设置的 size 得到的
            from: 0.5, //动画开始时的属性值
            to: 1,//动画结束时的属性值
            next: "collapseWidth"//字符串类型,指定当前动画完成之后,要执行的下个动画,可将多个动画融合
        },
        collapseWidth: {
            property: "width",
            from: 1,
            to: 0.5,
            next: "expandWidth"
        },
        expandHeight: {
            property: "height",
            from: 0.5,
            to: 1,
            next: "collapseHeight"
        },
        collapseHeight: {
            property: "height",
            from: 1,
            to: 0.5,
            next: "expandHeight"
        },
        start: ["expandWidth", "expandHeight"]//数组,用于指定要启动的一个或多个动画
    });
    dm.add(node);
    return node;
}

全总代码截至!

亚洲必赢官网 5

先来看下效果图

经过 splitView = new ht.widget.SplitView( leftView, rightView,
orientation, position
)开首化营造一个区划组件对象。leftView 左组件或上组件 
rightView 右组件或下组件 orientation 字符串类型,默许为 horizontal 或 h
代表左右划分,可设为 vertical 或 v 代表上下分割 position
分割地点,默认值为 0.5,假若设置值为 0~1 则按百分比分割,大于 1
代表左组件或上组件的绝对化宽或高,小于 1 代表右组件或下组件的断然宽或高。

总结

以此 Demo
花了自己二日时间达成,总以为有些不甘心啊,可是有时思维又转可是弯来,开销了很多的小时,可是总的来说收获照旧广大的,我从前一贯以为一旦经过
getPoints().push
来向多边形中添加点就足以了,求助了大神之后,发现原来那几个法子不仅绕弯路而且还会合世形形色色的难点,比如
getPoints 在此以前,一定要在多方形中已经有 points
才方可,不过在诸多气象下,初叶化的 points
并不佳设置,而且会招致代码很麻烦,间接通过 addPoint
方法,直接将点添加进多边形变量中,并且还会默许将点通过直线的格局连接,也不用设置
segments,多喜人的一个函数。

还有就是因为 ht 默许缩放大小是 20,而我那么些 Demo
的间隔又很小,导致缩放到最大大巴线路图突显也很小,所以我在 htconfig
中改变了 ht 的默许 zoom马克斯 属性,记住,更改那一个值一定要在有着的 ht
调用从前,因为在 htconfig 中安装的值在前面定义都是不行变更的。

简单来讲,那两日自己的脑细胞死了许多,也再也生长了好多,人都是在不断进步的呗~

1 赞 1 收藏
评论

亚洲必赢官网 6

动用弹力布局功用要求在引入
ht.js`核心库之后,再引入一个ht-forcelayout.js `的弹力布局插件库,因为还用到了
form 表单,所以要引入 ht-form.js 的表单插件库:

亚洲必赢官网 7

经过分割组件大家树组件和拓扑组件同时添加进 body
体中,需求的操作唯有如下几行:

<script src="../../guide/lib/core/ht.js"></script>
<script src="../../guide/lib/plugin/ht-forcelayout.js"></script>
<script src="../../guide/lib/plugin/ht-form.js"></script>

上图是华夏行政区域的数据树,总共得节点是3500+。

graphView = new ht.graph.GraphView();//拓扑组件
var treeView = new ht.widget.TreeView(graphView.dm());//树组件,参数为树组件绑定的数据模型,这里绑定的是 graphView 的数据模型,就可以进行数据共享
var splitView = new ht.widget.SplitView(treeView, graphView, 'h', 0.2);//分割组件 (leftView, rightView, orientation, position)
splitView.addToDOM();//将 splitView 添加进 body 中

ht.layout.Force3dLayout类提供 3D弹力布局,构造函数可传入 DataModel和 Graph3dView三种参数。
默许仅对未选中图元举办布局,即使构造函数参数为 Graph3dView时,则视图组件的 isMovable和 isVisible函数将震慑图元是还是不是可布局,
图元 style上的 layoutable质量也可设为 false阻止图元参与布局。

那么大家要动工了;

记住,原代码中的 graphView.addToDOM 语句得注释掉,否则前面添加到 body
体中的组件的根层 div 会覆盖住上一个添加进 body 体中的组件的平底
div,大家还记得呢? addToDOM
函数的定义,那里自己重新将函数的概念给大家显示一下,大家可以巩固一下:

介绍完
HT
封装的弹力布局的背景之后,接下去就是支持你们也能轻轻松松地达成这些意义。

1:第四个规定的节点Dom结构(即用什么样的HTML来营造节点)

addToDOM = function(){   
    var self = this,
        view = self.getView(),   //获取组件的底层 div
        style = view.style;
    document.body.appendChild(view); //将组件的底层 div 添加进 body 中           
    style.left = '0';// HT 的绝大部分组件都是绝对定位,所以需要设置位置
    style.right = '0';
    style.top = '0';
    style.bottom = '0';      
    window.addEventListener('resize', function () { self.iv(); }, false); //添加 resize 事件,iv 为延时刷新           
}

第一我们定义一个颜料数组变量,存储种种弹力球的颜色,还定义了一个随意函数,用来生成数随机的数组中的颜色:

  • 正如土的是table套table的(样式上好控制,然而大数据量,和层次较深的树,那种社团自然顶不住的)
  • 再有一种是相比独特的UL套LI的主意,那是现行游人如织书选择的法门如Jquery.treeview就是运用的那种格式,好处比较显明就是结构简单,
    并且在不辅助Js的浏览器上,同样也能呈现出树的模样(那种情景实际上我可以忽略),可是Jquery.treeview的节点在IE下,越发是IE6下不可以被中间因素撑开,(IE7,8当达到一定深度时不可以撑开),请奇怪的场景(我估摸是因为运用padding来做缩进,margin-left:负值来决定图标位置有关,可是修改起来难度也较大),在那种状态下书会变形(Jquery.treeview)就有那种题材,只能够通过设置节点的width来化解。

其他一些大家都不曾动,大家能够看看效果:

var colorList = ['#FFAFA4', '#B887C5', '#B9EA9C', '#CFD9E7', '#4590B8', '#FF9C30'], 
    colorLen = colorList.length;
var randomColor = function() {
    var ran = Math.random() * colorLen;
    return colorList[Math.floor(ran)];//随机6种颜色
};

亚洲必赢官网 8

亚洲必赢官网 9

跟着成立弹力球,简单生成一个
3D 节点,通过安装那几个节点的 style
样式属性来决定节点的突显方式,其上将“shape3d”设置为“sphere”即可将
ht.Node 六面体变成 3D
球体模型,再设置“shape3d”属性为眼前定义的轻易颜色,s3 是 HT 封装的装置
3D 节点大小的 setSize3d 函数的简写,最后将这些节点添加进数据模型
dataModel 中:

JQuery.treeview的节点结构

 

var createNode = function(dm) {//创建node节点 圆
    var node = new ht.Node();
    node.s({//设置样式为 setStyle 的简写
        'shape3d': 'sphere',
        'shape3d.color': randomColor()//设置随机颜色
    });
    node.s3(40, 40, 40);
    dm.add(node);
    return node;
};

亚洲必赢官网 10

 那样看着类似不太明确到底拓扑图上的哪一部分是树列表上的因素?不急,大家继续,给大家的富有节点都设置上“名称”,为了不混淆视听,我将事先的代码也粘出来,也有意无意复习一下(那里只展现其中一个节点的代码):

明天听从图上面世的还有各种弹力球之间的连线,这一个连线我们一看就觉着很不一般,也是通过结构一个一个节点,这几个节点是经过 HT
for Web
建模手册 setShape3dModel函数自定义的
ht.Default.createRingModel 依照 xy 平面的曲线,环绕一周形成的 3D
环形模型,将其命名为‘custom’:

Jquery.TreeView  IE6 下 展开第三级即出现错位

var server = new ht.Node();//服务器节点
graphView.dm().add(server);// 将服务器节点添加进拓扑图组件的数据容器中
server.setName('server');//设置名称 只添加了这一句
server.setPosition(300, 200);//设置服务器节点的位置
server.setImage('images/server.png');//设置服务器节点的显示图片
ht.Default.setShape3dModel(//创建模型 根据xy平面的曲线,环绕一周形成3D模型。
    'custom', ht.Default.createRingModel( [0.5, 0.5, -0.2, 0, 0.5, -0.5], [1, 3] )
);

亚洲必赢官网 11
IE8下举办到第5级

结果如下:

HT
将用户自定义的品质和 HT 默许的性质调用方法分为 node.a 和 node.s
那样就能将两边有效地区分开来(具体参照 HT for Web
入门手册 style
章节),大家在开创管线的时候就用了那种办法:

  • 再有一些是div套table的办法,CSDN的领航树就是那种,是种折中的方法(节点也不算太复杂,而且CSS也比较好写),如下图所示
    亚洲必赢官网 12

亚洲必赢官网 13

var updatePipeline = function(edge) {//重新设置edge的样式
    var pipeline = edge.a('pipeline');
    pipeline.s3(1, 1, 1);//设置大小
    pipeline.p3(0, 0, 0);//设置坐标

    var node1 = edge.getSourceAgent(),//获取图形上连接的起始节点
    node2 = edge.getTargetAgent();//获取图形上连接的目标节点
    pipeline.s('mat', createMatrix(node1.p3(), node2.p3(), 20));//3d整体图形矩阵变化
};

 

 

最神秘的是什么能做出让三个节点“若即若离”的机能?

 

 大家会发觉,拓扑图中的服务器节点以及客户端节点尾部也多了 setName
设置的名号!若是不想要在节点下面显示字的话,可以一直设置节点 style
属性:

我们领悟,矩阵能描述任意线性变换。线性变换保留了直线和平行线,线性变换保留直线的还要,其余的几何性质如长度、角度、面积和体积可能被更换改变了。一句话来说,线性变换可能“拉伸”坐标系,但不会“弯曲”或“卷折”坐标系。这些函数紧假诺将我们的连接线在拖动弹力球后被拖拉的连日线的展开一个“变化矩阵”的操作,变化矩阵也是
HT 封装的 ht.Default.createMatrix 函数,通过将节点的 style 属性 mat
设置为一个自定义的函数,就是将以此节点的坐标乘上在“mat”属性对应的值,也就是说如果当前那几个管线的团团转角为
[Math.PI/6, 0, 0],假如咱们在 createMatrix 函数中安装 r3 为
[Math.PI/3, 0, 0],那么那个节点会旋转 90
度。非常轻松地创设出转变矩阵:

 

server.s({//s 为 setStyle 的缩写,设置样式
    'label': ''// 将 label 属性设置为空
});
var createMatrix = function(p1, p2, width) {//createMatrix(array, matrix)将一组JSON描述的缩放、移动和旋转等操作转换成对应的变化矩阵
    var vec = [p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]],
        dist = ht.Default.getDistance(p1, p2);//获取两点之间距离,或向量长度
    return ht.Default.createMatrix({
        s3: [width, dist, width],
    r3: [Math.PI/2 - Math.asin(vec[1]/dist), Math.atan2(vec[0], vec[2]), 0],
    rotationMode: 'xyz',
    t3: [(p1[0]+p2[0])/2, (p1[1]+p2[1])/2, (p1[2]+p2[2])/2]
    });
};

而自我利用的也是第两种办法,然而缩进选用了补偿的主意,即缩进的岗位用空白的图片填充来防止Jquery.treeview的标题

诸如此类就不显得啦!不过为何如此设置能够啊?大家来探望 label
属性的定义,label 属性即为 GraphView.getLabel 函数的包裹:

基本功配件全体概念已毕,接着就是将“shape3d”属性设置为自定义的
3D 模型“custom”
,并将“layoutable”属性设置为“false”阻止图元加入布局,并将点时期的连线通过edge.a(‘pipeline’,
node)重新刷新,并添加进数据模型 dataModel 中:

亚洲必赢官网 14

getLabel: function (data) {
    var label = data.getStyle('label');//获取样式属性 label 的值
    return label === undefined ? data.getName() : label;        
}
var createEdge = function(dm, node1, node2) {//创建‘custom’模型的edge
    var node = new ht.Node();
    node.s({
        'shape3d': 'custom',
        'shape3d.color': '#ECE0D4',
        'layoutable': false
    });
    dm.add(node);

    var edge = new ht.Edge(node1, node2);
    edge.a('pipeline', node);
    edge.s('edge.color', 'rgba(0, 0, 0, 0)');
    dm.add(edge);
    return edge;
};

我的树节点结构

通过以上代码可知,style 上的 label 属性优先级高于 name 属性,可重载
GraphView.getLabel 函数改变文字获取逻辑。所以尽管大家设置了 name
属性,可是再设置 label 属性还可以将 name
属性设置的值给覆盖掉的,而树组件上赢得的只是节点的
name,所以两岸并不争辨。

插:大家还足以在工业上用
HeatMap 热图上做小说,效果仍旧很炫,具体地址http://hightopo.com/guide/guide/plugin/forcelayout/examples/example\_heatmap3d.html

确定了节点的HTML大家就可以来写CSS了。有了职能图,有个节点结构接着就编写CSS了

蓦地感觉树上的节点彰显图标为啥都平等。。。改图标!

亚洲必赢官网 15

下面是CSS的完好代码

treeView 树组件通过 getIcon(data) 重返 data 对象对应的 icon
图标,可重载自定义,默认再次回到的都是图元原始的图标,那里大家要自定义这几个函数,针对分裂的节点重回分化的
icon,前边大家设置的 name 属性派上用场了:

界面上的图样全部绘制落成,剩下的就唯有form 表单,首先将 form 表单添加进 HTML 页面,用的是 HT 封装的
ht.widget.FormPane 函数:

复制代码 代码如下:

treeView.getIcon = function(data){
    var self = this,
          edge_icon = data.getIcon();//获取对象的 icon
    if(data.getName() === 'server'){//如果是 name 为 server 的节点时
        return 'images/server.png';
    }else if(data.getName() === 'client'){//如果是 name 为 client 的节点时
        return 'images/node.png';
    }else if(data instanceof ht.Edge){//如果是 ht.Edge 类型的节点时
        return edge_icon
    }
}
var formPane = new ht.widget.FormPane();
formPane.setWidth(230);
formPane.setHeight(125);
formPane.addToDOM();

.ie .bbit-tree .bbit-tree-bwrap{
}
.bbit-tree ul,.bbit-tree li
{
list-style-type:none;
margin:0px;
padding:0px;
}
.bbit-tree-body
{
font-size:12px;
}
.bbit-tree-icon, .bbit-tree-ec-icon,
.bbit-tree-node-cb,.bbit-tree-elbow-line, .bbit-tree-elbow,
.bbit-tree-elbow-end, .bbit-tree-elbow-plus, .bbit-tree-elbow-minus,
.bbit-tree-elbow-end-plus, .bbit-tree-elbow-end-minus{
border: 0 none;
height: 18px;
margin: 0;
padding: 0;
vertical-align: top;
width: 16px;
background-repeat: no-repeat;
}
.bbit-tree-node-cb
{
height:16px;
}
.bbit-tree-node-collapsed .bbit-tree-node-icon, .bbit-tree-node-expanded
.bbit-tree-node-icon, .bbit-tree-node-leaf .bbit-tree-node-icon{
border: 0 none;
height: 18px;
margin: 0;
padding: 0;
vertical-align: top;
width: 16px;
background-position:center;
background-repeat: no-repeat;
}
.ie .bbit-tree-node-indent img, .ie .bbit-tree-node-icon, .ie
.bbit-tree-ec-icon {
vertical-align:middle !important;
}
.bbit-tree-noicon .bbit-tree-node-icon{
width:0; height:0;
}
/* No line styles 没有线的样式 */
.bbit-tree-no-lines .bbit-tree-elbow{
background:transparent;
}
.bbit-tree-no-lines .bbit-tree-elbow-end{
background:transparent;
}
.bbit-tree-no-lines .bbit-tree-elbow-line{
background:transparent;
}
/* Arrows Vista系统树的体制只有箭头*/
.bbit-tree-arrows .bbit-tree-elbow{
background:transparent;
}
.bbit-tree-arrows .bbit-tree-elbow-plus{
background:transparent no-repeat 0 0;
}
.bbit-tree-arrows .bbit-tree-elbow-minus{
background:transparent no-repeat -16px 0;
}
.bbit-tree-arrows .bbit-tree-elbow-end{
background:transparent;
}
.bbit-tree-arrows .bbit-tree-elbow-end-plus{
background:transparent no-repeat 0 0;
}
.bbit-tree-arrows .bbit-tree-elbow-end-minus{
background:transparent no-repeat -16px 0;
}
.bbit-tree-arrows .bbit-tree-elbow-line{
background:transparent;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-plus{
background-position:-32px 0;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-minus{
background-position:-48px 0;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-end-plus{
background-position:-32px 0;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-end-minus{
background-position:-48px 0;
}
.bbit-tree-elbow-plus, .bbit-tree-elbow-minus,
.bbit-tree-elbow-end-plus, .bbit-tree-elbow-end-minus{
cursor:pointer;
}
.ie ul.bbit-tree-node-ct{
font-size:0;
line-height:0;
zoom:1;
}
.bbit-tree-node{
white-space: nowrap;
}
.bbit-tree-node-el {
line-height:18px;
cursor:default;
/* cursor:pointer;*/
}
.bbit-tree-node a{
text-decoration:none;
-khtml-user-select:none;
-moz-user-select:none;
-webkit-user-select:ignore;
-kthml-user-focus:normal;
-moz-user-focus:normal;
-moz-outline: 0 none;
outline:0 none;
}
.bbit-tree-node a span{
text-decoration:none;
padding:1px 3px 1px 2px;
}
.bbit-tree-node .bbit-tree-node-disabled .bbit-tree-node-icon{
-moz-opacity: 0.5;
opacity:.5;
filter: alpha(opacity=50);
}
.bbit-tree-node .bbit-tree-node-inline-icon{
background:transparent;
}
.bbit-tree-node a:hover{
text-decoration:none;
}

当选树上的节点,拓扑图中的对应节点也会被入选,反过来,选中拓扑图中的节点,树上的节点也会被选中。

铭记,form
表单要安装宽高,不然不展现。

/* Fix for ie rootVisible:false issue,核查一个IEdebug */
.bbit-tree-root {
zoom:1;
}

说到底结出如下:

form
表单添加行是通过 addRow 函数,我们根本来说一下底下的几行,Color、Range
和 Intensity,那多个名字根本是用来支配“头灯”的。在 HT 中一贯通过
setHeadlightColor/setHeadlightRange/setHeadlightIntensity
多个函数来决定“头灯”的颜色、范围以及灯的强度,onValueChanged
属性,顾名思义属性值改变以后触发的事件:

/***********此间是图标了,可以在此处替换哦*****************/
.bbit-tree-node-expanded .bbit-tree-node-icon{
background-image:url(images/tree/folder-open.gif);
}
.bbit-tree-node-leaf .bbit-tree-node-icon{
background-image:url(images/tree/leaf.gif);
}
.bbit-tree-node-collapsed .bbit-tree-node-icon{
background-image:url(images/tree/folder.gif);
}
.bbit-tree-node-loading .bbit-tree-node-icon{
background-image:url(images/tree/loading.gif) !important;
}
.bbit-tree-node .bbit-tree-node-inline-icon {
background-image: none;
}
.bbit-tree-node-loading a span{
font-style: italic;
color:#444444;
}
.bbit-tree-lines .bbit-tree-elbow{
background-image:url(images/tree/elbow.gif);
}
.bbit-tree-lines .bbit-tree-elbow-plus{
background-image:url(images/tree/elbow-plus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-minus{
background-image:url(images/tree/elbow-minus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-end{
background-image:url(images/tree/elbow-end.gif);
}
.bbit-tree-lines .bbit-tree-elbow-end-plus{
background-image:url(images/tree/elbow-end-plus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-end-minus{
background-image:url(images/tree/elbow-end-minus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-line{
background-image:url(images/tree/elbow-line.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-plus{
background-image:url(images/tree/elbow-plus-nl.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-minus{
background-image:url(images/tree/elbow-minus-nl.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-end-plus{
background-image:url(images/tree/elbow-end-plus-nl.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-end-minus{
background-image:url(images/tree/elbow-end-minus-nl.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-plus{
background-image:url(images/tree/arrows.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-minus{
background-image:url(images/tree/arrows.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-end-plus{
background-image:url(images/tree/arrows.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-end-minus{
background-image:url(images/tree/arrows.gif);
}
/*TreeNode 选中的Disabled的部分颜料,字体样式*/
.bbit-tree-node{
color:#000;
font: normal 11px arial, tahoma, helvetica, sans-serif;
}
.bbit-tree-node a{
color:#000;
}
.bbit-tree-node a span{
color:#000;
}
.bbit-tree-node .bbit-tree-node-disabled a span{
color:gray !important;
}
.bbit-tree-node .bbit-tree-node-over {
background-color: #eee;
}
.bbit-tree-node .bbit-tree-selected {
background-color: #d9e8fb;
}

亚洲必赢官网 16

['Color', 'Range', 'Intensity'].forEach(function(name) {
    var obj = { id: name },
    func = function(oV, nV) {
        g3d['setHeadlight' + name](nV);// === g3d.setHeadlightColor(nV)/g3d.setHeadlightRange(nV)/g3d.setHeadlightIntensity(nV)
    };
    if (name === 'Color')
        obj.colorPicker = {//ht.widget.ColorPicker为颜色选择框 
        instant: true,
        value: g3d['getHeadlight' + name](),// === g3d.getHeadlightColor()
        onValueChanged: func
    };
    else 
        obj.slider = {//滑动条
            min: 0,
        max: name === 'Range' ? 20000 : 3,
        step: 0.1,
        value: g3d['getHeadlight' + name](),
        onValueChanged: func
        };
    formPane.addRow([ name, obj ], [ 70, 0.1 ]);
});

上面了树的主题样式外,定义了一个有+号带line的样式和+号不带line的样式

次回,大家将在万象中添加工具条!请持续跟踪哦~

slider
和 colorPicker 都是 HT 自定义的滑动条和颜料采取器,详情请参考 HT for
Web
表单手册。

亚洲必赢官网 17
这就是可怜+号带line的体制

 

如果还有不懂的请咨询我,或者可以一向上 HT for
Web 官网查阅手册。

css中所用到的有着图片

 

亚洲必赢官网 18
亚洲必赢官网 19
亚洲必赢官网 20
亚洲必赢官网 21
亚洲必赢官网 22
亚洲必赢官网 23
亚洲必赢官网 24
亚洲必赢官网 25
亚洲必赢官网 26
亚洲必赢官网 27
亚洲必赢官网 28
亚洲必赢官网 29
亚洲必赢官网 30
亚洲必赢官网 31
亚洲必赢官网 32
亚洲必赢官网 33

 

亚洲必赢官网 34
亚洲必赢官网 35
亚洲必赢官网 36

2:确定数据结构

复制代码 代码如下:

var menudata = [{
id: “0.1”,//唯一的ID即可
text: “Beyondbit UI Demo”,
hasChildren: true,
isexpand: true,
complete: true,
ChildNodes: [{
id: “0.1.1”,
text: “日期拔取”,
hasChildren: true,
isexpand: false,
complete: true,
ChildNodes: [{
id: “0.1.1.1”,
text: “控件演示”,
value: “Testpages/datepickerDemo.htm”,
hasChildren: false,
isexpand: false,
complete: true,
ChildNodes: null
},

]

那样的协会有个好处就多少我是带层次的,万分便宜遍历,在背后的级联关联中会看到
3: 面子做好了那就从头做里子了,编写脚本(Javascript)
本身是JQuery得拥护者,所以自然js的框架自然是运用Jquery了
先上个完全代码,再逐一解析

复制代码 代码如下:

/****************************************
author:[email protected]
page:
***************************************/
(function($) {
$.fn.swapClass = function(c1, c2) {
return this.removeClass(c1).addClass(c2);
}
$.fn.switchClass = function(c1, c2) {
if (this.hasClass(c1)) {
return this.swapClass(c1, c2);
}
else {
return this.swapClass(c2, c1);
}
}
$.fn.treeview = function(settings) {
var dfop =
{
method: “POST”,
datatype: “json”,
url: false,
cbiconpath: “/images/icons/”,
icons: [“checkbox_0.gif”, “checkbox_1.gif”, “checkbox_2.gif”],
showcheck: false, //是还是不是出示选用
oncheckboxclick: false,
//当checkstate状态变化时所接触的事件,不过不会触发因级联接纳而滋生的转移
onnodeclick: false,
cascadecheck: true,
data: null,
clicktoggle: true, //点击节点举行和裁减子节点
theme: “bbit-tree-arrows” //bbit-tree-lines
,bbit-tree-no-lines,bbit-tree-arrows
}
$.extend(dfop, settings);
var treenodes = dfop.data;
var me = $(this);
var id = me.attr(“id”);
if (id == null || id == “”) {
id = “bbtree” + new Date().getTime();
me.attr(“id”, id);
}
var html = [];
buildtree(dfop.data, html);
me.addClass(“bbit-tree”).html(html.join(“”));
InitEvent(me);
html = null;
//预加载图片
if (dfop.showcheck) {
for (var i = 0; i < 3; i++) {
var im = new Image(16,16);
im.src = dfop.cbiconpath + dfop.icons[i];
}
}
//region
function buildtree(data, ht) {
ht.push(“<div class=’bbit-tree-bwrap’>”); // Wrap ;
ht.push(“<div class=’bbit-tree-body’>”); // body ;
ht.push(“<ul class=’bbit-tree-root “, dfop.theme, “‘>”); //root
var l = data.length;
for (var i = 0; i < l; i++) {
buildnode(data[i], ht, 0, i, i == l – 1);
}
ht.push(“</ul>”); // root and;
ht.push(“</div>”); // body end;
ht.push(“</div>”); // Wrap end;
}
//endregion
function buildnode(nd, ht, deep, path, isend) {
ht.push(“<li class=’bbit-tree-node’>”);
ht.push(“<div id='”, id, “_”, nd.id, “‘ tpath='”, path, “‘
unselectable=’on'”);
var cs = [];
cs.push(“bbit-tree-node-el”);
if (nd.hasChildren) {
cs.push(nd.isexpand ? “bbit-tree-node-expanded” :
“bbit-tree-node-collapsed”);
}
else {
cs.push(“bbit-tree-node-leaf”);
}
if (nd.classes) { cs.push(nd.classes); }
ht.push(” class='”, cs.join(” “), “‘>”);
//span indent
ht.push(“<span class=’bbit-tree-node-indent’>”);
if (deep == 1) {
ht.push(“<img class=’bbit-tree-icon’
src=’../Themes/Shared/images/s.gif’/>”);
}
else if (deep > 1) {
ht.push(“<img class=’bbit-tree-icon’
src=’../Themes/Shared/images/s.gif’/>”);
for (var j = 1; j < deep; j++) {
ht.push(“<img class=’bbit-tree-elbow-line’
src=’../Themes/Shared/images/s.gif’/>”);
}
}
ht.push(“</span>”);
//img
cs.length = 0;
if (nd.hasChildren) {
if (nd.isexpand) {
cs.push(isend ? “bbit-tree-elbow-end-minus” :
“bbit-tree-elbow-minus”);
}
else {
cs.push(isend ? “bbit-tree-elbow-end-plus” : “bbit-tree-elbow-plus”);
}
}
else {
cs.push(isend ? “bbit-tree-elbow-end” : “bbit-tree-elbow”);
}
ht.push(“<img class=’bbit-tree-ec-icon “, cs.join(” “), “‘
src=’../Themes/Shared/images/s.gif’/>”);
ht.push(“<img class=’bbit-tree-node-icon’
src=’../Themes/Shared/images/s.gif’/>”);
//checkbox
if (dfop.showcheck && nd.showcheck) {
if (nd.checkstate == null || nd.checkstate == undefined) {
nd.checkstate = 0;
}
ht.push(“<img id='”, id, “_”, nd.id, “_cb’
class=’bbit-tree-node-cb’ src='”, dfop.cbiconpath,
dfop.icons[nd.checkstate], “‘/>”);
}
//a
ht.push(“<a hideFocus class=’bbit-tree-node-anchor’ tabIndex=1
href=’javascript:void(0);’>”);
ht.push(“<span unselectable=’on’>”, nd.text, “</span>”);
ht.push(“</a>”);
ht.push(“</div>”);
//Child
if (nd.hasChildren) {
if (nd.isexpand) {
ht.push(“<ul class=’bbit-tree-node-ct’ style=’z-index: 0; position:
static; visibility: visible; top: auto; left: auto;’>”);
if (nd.ChildNodes) {
var l = nd.ChildNodes.length;
for (var k = 0; k < l; k++) {
nd.ChildNodes[k].parent = nd;
buildnode(nd.ChildNodes[k], ht, deep + 1, path + “.” + k, k == l –
1);
}
}
ht.push(“</ul>”);
}
else {
ht.push(“<ul style=’display:none;’></ul>”);
}
}
ht.push(“</li>”);
nd.render = true;
}
function getItem(path) {
var ap = path.split(“.”);
var t = treenodes;
for (var i = 0; i < ap.length; i++) {
if (i == 0) {
t = t[ap[i]];
}
else {
t = t.ChildNodes[ap[i]];
}
}
return t;
}
function check(item, state, type) {
var pstate = item.checkstate;
if (type == 1) {
item.checkstate = state;
}
else {// 上溯
var cs = item.ChildNodes;
var l = cs.length;
var ch = true;
for (var i = 0; i < l; i++) {
if ((state == 1 && cs[i].checkstate != 1) || state == 0 &&
cs[i].checkstate != 0) {
ch = false;
break;
}
}
if (ch) {
item.checkstate = state;
}
else {
item.checkstate = 2;
}
}
//change show
if (item.render && pstate != item.checkstate) {
var et = $(“#” + id + “_” + item.id + “_cb”);
if (et.length == 1) {
et.attr(“src”, dfop.cbiconpath + dfop.icons[item.checkstate]);
}
}
}
//遍历子节点
function cascade(fn, item, args) {
if (fn(item, args, 1) != false) {
if (item.ChildNodes != null && item.ChildNodes.length > 0) {
var cs = item.ChildNodes;
for (var i = 0, len = cs.length; i < len; i++) {
cascade(fn, cs[i], args);
}
}
}
}
//冒泡的先人
function bubble(fn, item, args) {
var p = item.parent;
while (p) {
if (fn(p, args, 0) === false) {
break;
}
p = p.parent;
}
}
function nodeclick(e) {
var path = $(this).attr(“tpath”);
var et = e.target || e.srcElement;
var item = getItem(path);
//debugger;
if (et.tagName == “IMG”) {
// +号要求开展
if ($(et).hasClass(“bbit-tree-elbow-plus”) ||
$(et).hasClass(“bbit-tree-elbow-end-plus”)) {
var ul = $(this).next(); //”bbit-tree-node-ct”
if (ul.hasClass(“bbit-tree-node-ct”)) {
ul.show();
}
else {
var deep = path.split(“.”).length;
if (item.complete) {
item.ChildNodes != null && asnybuild(item.ChildNodes, deep, path, ul,
item);
}
else {
$(this).addClass(“bbit-tree-node-loading”);
asnyloadc(ul, item, function(data) {
item.complete = true;
item.ChildNodes = data;
asnybuild(data, deep, path, ul, item);
});
}
}
if ($(et).hasClass(“bbit-tree-elbow-plus”)) {
$(et).swapClass(“bbit-tree-elbow-plus”, “bbit-tree-elbow-minus”);
}
else {
$(et).swapClass(“bbit-tree-elbow-end-plus”,
“bbit-tree-elbow-end-minus”);
}
$(this).swapClass(“bbit-tree-node-collapsed”,
“bbit-tree-node-expanded”);
}
else if ($(et).hasClass(“bbit-tree-elbow-minus”) ||
$(et).hasClass(“bbit-tree-elbow-end-minus”)) { //- 号需求裁减
$(this).next().hide();
if ($(et).hasClass(“bbit-tree-elbow-minus”)) {
$(et).swapClass(“bbit-tree-elbow-minus”, “bbit-tree-elbow-plus”);
}
else {
$(et).swapClass(“bbit-tree-elbow-end-minus”,
“bbit-tree-elbow-end-plus”);
}
$(this).swapClass(“bbit-tree-node-expanded”,
“bbit-tree-node-collapsed”);
}
else if ($(et).hasClass(“bbit-tree-node-cb”)) // 点击了Checkbox
{
var s = item.checkstate != 1 ? 1 : 0;
var r = true;
if (dfop.oncheckboxclick) {
r = dfop.oncheckboxclick.call(et, item, s);
}
if (r != false) {
if (dfop.cascadecheck) {
//遍历
cascade(check, item, s);
//上溯
bubble(check, item, s);
}
else {
check(item, s, 1);
}
}
}
}
else {
if (dfop.citem) {
$(“#” + id + “_” + dfop.citem.id).removeClass(“bbit-tree-selected”);
}
dfop.citem = item;
$(this).addClass(“bbit-tree-selected”);
if (dfop.onnodeclick) {
dfop.onnodeclick.call(this, item);
}
}
}
function asnybuild(nodes, deep, path, ul, pnode) {
var l = nodes.length;
if (l > 0) {
var ht = [];
for (var i = 0; i < l; i++) {
nodes[i].parent = pnode;
buildnode(nodes[i], ht, deep, path + “.” + i, i == l – 1);
}
ul.html(ht.join(“”));
ht = null;
InitEvent(ul);
}
ul.addClass(“bbit-tree-node-ct”).css({ “z-index”: 0, position: “static”,
visibility: “visible”, top: “auto”, left: “auto”, display: “” });
ul.prev().removeClass(“bbit-tree-node-loading”);
}
function asnyloadc(pul, pnode, callback) {
if (dfop.url) {
var param = builparam(pnode);
$.ajax({
type: dfop.method,
url: dfop.url,
data: param,
dataType: dfop.datatype,
success: callback,
error: function(e) { alert(“error occur!”); }
});
}
}
function builparam(node) {
var p = [{ name: “id”, value: encodeURIComponent(node.id) }
, { name: “text”, value: encodeURIComponent(node.text) }
, { name: “value”, value: encodeURIComponent(node.value) }
, { name: “checkstate”, value: node.checkstate}];
return p;
}
function InitEvent(parent) {
var nodes = $(“li.bbit-tree-node>div”, parent);
nodes.each(function(e) {
$(this).hover(function() {
$(this).addClass(“bbit-tree-node-over”);
}, function() {
$(this).removeClass(“bbit-tree-node-over”);
})
.click(nodeclick)
.find(“img.bbit-tree-ec-icon”).each(function(e) {
if (!$(this).hasClass(“bbit-tree-elbow”)) {
$(this).hover(function() {
$(this).parent().addClass(“bbit-tree-ec-over”);
}, function() {
$(this).parent().removeClass(“bbit-tree-ec-over”);
});
}
});
});
}
function getck(items, c, fn) {
for (var i = 0, l = items.length; i < l; i++) {
items[i].checkstate == 1 && c.push(fn(items[i]));
if (items[i].ChildNodes != null && items[i].ChildNodes.length >
0) {
getck(items[i].ChildNodes, c, fn);
}
}
}
me[0].t = {
getSelectedNodes: function() {
var s = [];
getck(treenodes, s, function(item) { return item });
return s;
},
getSelectedValues: function() {
var s = [];
getck(treenodes, s, function(item) { return item.value });
return s;
},
getCurrentItem: function() {
return dfop.citem;
}
};
return me;
}
//获取具有入选的节点的Value数组
$.fn.getTSVs = function() {
if (this[0].t) {
return this[0].t.getSelectedValues();
}
return null;
}
//获取具有入选的节点的Item数组
$.fn.getTSNs = function() {
if (this[0].t) {
return this[0].t.getSelectedNodes();
}
return null;
}
$.fn.getTCT = function() {
if (this[0].t) {
return this[0].t.getCurrentItem();
}
return null;
}
})(jQuery);

首先步:自然是负有Jquery的控件的首先步都是搭那一个架子,兼容JQuery和$幸免闭包,幸免和其余类库争辨,接受一个参数(是个目标)

复制代码 代码如下:

;(function($) {
//也得以运用$.fn.extend(treeview:function(setting){})
$.fn.treeview = function(settings) {
}
})(jQuery);

那第二步:给控件加一些参数默许参数,同时能调用方法$.extend让最终调用时的参数覆盖默认的(如若没有则接纳默许)

复制代码 代码如下:

var dfop ={
method: “POST”,//默许使用POST提交数据
datatype: “json”,//数据类型是json
url: false,//异步请求的url
cbiconpath: “/images/icons/”,//checkbox icon的目录地点
icons: [“checkbox_0.gif”, “checkbox_1.gif”,
“checkbox_2.gif”],//checkbxo三态的图纸
showcheck: false, //是或不是出示checkbox
oncheckboxclick: false, //点击checkbox时接触的风云
onnodeclick: false,//点击node触发的岁月
cascadecheck: true,//是或不是启用级联
data: null,//早先化数据
theme: “bbit-tree-arrows” //二种风格备选bbit-tree-lines
,bbit-tree-no-lines,bbit-tree-arrows
}
//用传进来的参数覆盖默许,没传则保留
$.extend(dfop, settings);

其三步:生成默许数据的HTML(依照大家的分析节点的Dom结构,数据的数据结构,生成节点那是不行的差不离),,添加到当下容器中。最后是登记事件那里有一个老大主要的地方,即懒加载(没有进展的节点HTML是不扭转的),这就需求大家在树内部要敬重一套数据(费用很小),对于品质的晋级那是一对一的明明。其它一个最主要的地点,就是运用五回变动所有开展节点的HTML并透过innerHTML属性来生成Dom,而不是由此append操作,因为间接操作innerHTML比通过dom原生的章程要快上N倍(节点越多,N越大),切记切记!

复制代码 代码如下:

var treenodes = dfop.data; //内部的数目,其实平素用 dfop.data也可以
var me = $(this);
var id = me.attr(“id”);
if (id == null || id == “”) {
id = “bbtree” + new Date().getTime();
me.attr(“id”, id);
}//全局唯一的ID
var html = [];
buildtree(dfop.data, html);//生成开展节点的HTML,push到数组中
me.addClass(“bbit-tree”).html(html.join(“”));
Init伊芙nt(me);//伊始化事件
html = null;

在节点生成进程中,同时可生产节点的Path(节点路径),方便寻找

复制代码 代码如下:

if (nd.hasChildren) { //存在子节点
if (nd.isexpand) {//同时节点已经展开则输出子节点
ht.push(“<ul class=’bbit-tree-node-ct’ style=’z-index: 0; position:
static; visibility: visible; top: auto; left: auto;’>”);
if (nd.ChildNodes) {
var l = nd.ChildNodes.length;
for (var k = 0; k < l; k++) {//递归调用并生育节点的路径
nd.ChildNodes[k].parent = nd;
buildnode(nd.ChildNodes[k], ht, deep + 1, path + “.” + k, k == l –
1);
}
}
ht.push(“</ul>”);
}
else { //否则是待输出状态
ht.push(“<ul style=’display:none;’></ul>”);
}
}

挂号事件,接受参数parent,即从某一父节点开首增大事件(因为做了个hover效果,所以事件是在每个节点上,假使撤除该功用,事件可一贯附加Tree上经过伊夫nt的srcElement来散发可略进步质量)

复制代码 代码如下:

function InitEvent(parent) {
var nodes = $(“li.bbit-tree-node>div”, parent);
nodes.each(function(e) {
$(this).hover(function() {
$(this).addClass(“bbit-tree-node-over”); //鼠标浮动节点的体制变化
}, function() {
$(this).removeClass(“bbit-tree-node-over”);
})
.click(nodeclick)//node的onclick事件,那些是重点哦
.find(“img.bbit-tree-ec-icon”).each(function(e) {
//arrow的hover事件,为了已毕vista这个风格的
if (!$(this).hasClass(“bbit-tree-elbow”)) {
$(this).hover(function() {
$(this).parent().addClass(“bbit-tree-ec-over”);
}, function() {
$(this).parent().removeClass(“bbit-tree-ec-over”);
});
}
});
});
}

那里最根本的如故node的click事件,因为她要拍卖的事务很多,如树的开展裁减(若是实节点不存在,不过hasChildren为真,同时complete属性不为真则必要异步加载子节点,如子节点存在,不过尚未Render那么就要Render),点击checkbox要起身级联的事件和oncheckbox事件,点击任何则触发配置标准的nodeonclick事件,那整个都经过前边event的源元素的class来分别点击的靶子

复制代码 代码如下:

function nodeclick(e) {
var path = $(this).attr(“tpath”);//获取节点路径
var et = e.target || e.srcElement;//获取事件源
var item = getItem(path);//按照path获取节点的多寡
//debugger;
if (et.tagName == “IMG”) {
// +号需求展开,处理加减号
if ($(et).hasClass(“bbit-tree-elbow-plus”) ||
$(et).hasClass(“bbit-tree-elbow-end-plus”)) {
var ul = $(this).next(); //”bbit-tree-node-ct”
if (ul.hasClass(“bbit-tree-node-ct”)) {
ul.show();
}
else {
var deep = path.split(“.”).length;
if (item.complete) {
item.ChildNodes != null && asnybuild(item.ChildNodes, deep, path, ul,
item);
}
else {
$(this).addClass(“bbit-tree-node-loading”);
asnyloadc(ul, item, function(data) {
item.complete = true;
item.ChildNodes = data;
asnybuild(data, deep, path, ul, item);
});
}
}
if ($(et).hasClass(“bbit-tree-elbow-plus”)) {
$(et).swapClass(“bbit-tree-elbow-plus”, “bbit-tree-elbow-minus”);
}
else {
$(et).swapClass(“bbit-tree-elbow-end-plus”,
“bbit-tree-elbow-end-minus”);
}
$(this).swapClass(“bbit-tree-node-collapsed”,
“bbit-tree-node-expanded”);
}
else if ($(et).hasClass(“bbit-tree-elbow-minus”) ||
$(et).hasClass(“bbit-tree-elbow-end-minus”)) { //- 号须求减弱
$(this).next().hide();
if ($(et).hasClass(“bbit-tree-elbow-minus”)) {
$(et).swapClass(“bbit-tree-elbow-minus”, “bbit-tree-elbow-plus”);
}
else {
$(et).swapClass(“bbit-tree-elbow-end-minus”,
“bbit-tree-elbow-end-plus”);
}
$(this).swapClass(“bbit-tree-node-expanded”,
“bbit-tree-node-collapsed”);
}
else if ($(et).hasClass(“bbit-tree-node-cb”)) // 点击了Checkbox
{
var s = item.checkstate != 1 ? 1 : 0;
var r = true;
if (dfop.oncheckboxclick) { //触发配置的函数
r = dfop.oncheckboxclick.call(et, item, s);
}
if (r != false) {//假诺重回值不为false,即checkbxo变化使得
if (dfop.cascadecheck) {//允许触发级联
//遍历
cascade(check, item, s);//则向下关联
//上溯
bubble(check, item, s); //向上关联
}
else {
check(item, s, 1);//否则只管自己
}
}
}
}
else {//点击到了其他地点
if (dfop.citem) { //上一个脚下节点
$(“#” + id + “_” + dfop.citem.id).removeClass(“bbit-tree-selected”);
}
dfop.citem = item;//这一次的此时此刻节点
$(this).addClass(“bbit-tree-selected”);
if (dfop.onnodeclick) {
dfop.onnodeclick.call(this, item);
}
}
}

开展节点,异步请求的片段代码应该不是很复杂就不细诉了,关键来讲一下级联
级联有四个难题要处理,首个是遍历子节点,首个是上溯到祖节点,因为大家的数据结构那五个操作都呈现非凡简单

复制代码 代码如下:

//遍历子节点
function cascade(fn, item, args) {
if (fn(item, args, 1) != false) {
if (item.ChildNodes != null && item.ChildNodes.length > 0) {
var cs = item.ChildNodes;
for (var i = 0, len = cs.length; i < len; i++) {
cascade(fn, cs[i], args);
}
}
}
}
//冒泡的先世
function bubble(fn, item, args) {
var p = item.parent;
while (p) {
if (fn(p, args, 0) === false) {
break;
}
p = p.parent;
}
}

找到节点的同时都会触发check那么些回调函数,来判断当前节点的场所,详细请看上面代码中的注释部分应该是相比较清晰,描写了那一个进程

复制代码 代码如下:

function check(item, state, type) {
var pstate = item.checkstate; //当前气象
if (type == 1) {
item.checkstate = state; //如若是遍历子节点,父是什么子就是怎么
}
else {// 上溯 ,那一个就复杂一些了
var cs = item.ChildNodes; //获取当前节点的所有子节点
var l = cs.length;
var ch = true; //是不是不是中间状态 半选
for (var i = 0; i < l; i++) {
if ((state == 1 && cs[i].checkstate != 1) || state == 0 &&
cs[i].checkstate != 0) {
ch = false;
break;//他的子节点只要有一个没选中,那么她就是半选
}
}
if (ch) {
item.checkstate = state;//不是半选,则子节点是什么他就是如何
}
else {
item.checkstate = 2; //半选
}
}
//change show 假诺节点已出口,而其前后状态不平等,则变化checkbxo的显示
if (item.render && pstate != item.checkstate) {
var et = $(“#” + id + “_” + item.id + “_cb”);
if (et.length == 1) {
et.attr(“src”, dfop.cbiconpath + dfop.icons[item.checkstate]);
}
}
}

由来大家树的本位成效已经完全落到实处了。其余就是真心真意一些主意等,大家可详细代码,示例中公然了四个一个脚下选中的装有节点,其它一个当下的节点。 

世家可以因此以下网址查看文中的演示,selected拼错了,我们海涵! windows
azure布署仍旧麻烦懒得修改了3500+节点五遍加载,我们可以点击根节点的全选来探视速度

  

异步加载,按需加载的景色也是卓殊常用的,使用的是SQL
Azure服务器在美利坚同盟国ing,所以可能异步有点慢,本地数据源那是一下子的

FAQ:

1:怎么样设置每个节点差距的图标?

回答:

实在并非扩张,本身就支持,只是没有认证而已,大家来看一下这几个代码吧?在BuildNode方法中有那样一句?      
if (nd.classes) { cs.push(nd.classes); }

在节点的数据结构中得以设置属性classes ,该属性将作为节点特殊的Css Class
添加到节点上。那么利用那一点,就足以设置节点的图标了

亚洲必赢官网 37

然后就是编辑一个Style 即可

亚洲必赢官网 38

说到底来看下效果呢?

亚洲必赢官网 39

1:支持静态的树,即三次性将一切数据加载到客户端。
2:异步树,即四次只加载一流或若干…

网站地图xml地图