1. D3.js
D3类似于echarts和Highcharts,都是前端可视化插件,D3采用的是浏览器图形渲染技术SVG实现,echarts和Highcharts则是Canvas,相对于另外两个插件,D3更加灵活,更容易做出自己想要的效果。
2. 创建一个svg和g
scope.svg1 = d3.select("#tree_right")
.append("svg")
.attr("class", "all_tree")
.attr("id", "svg1");
.all_tree {
position: absolute;
top: 0px;
right: 0px;
width: 100%;
height: 100%;
}
var nodeEnter = node.enter().append("g")
.attr("class", "node") //attr设置html属性,style设置css属性
.attr("transform", function (d) {
return "translate(" + source.y + "," + source.x + ")";
});
可以为svg加入样式,设置其宽度、高度和边框等,也可以设置svg的id。svg是一个画图,里面可以放很多的元素,比如容器元素g和结构元素circle等。
g是 svg 中的一个属性,是 group 的意思,它表示一组什么东西,如一组 lines 、 rects 、circles ,其实坐标轴就是由这些东西构成的。
3. 设置节点的椭圆
nodeEnter.append("rect")
.attr("class", "rect_div")
.style("stroke-width", function (d) {
return "1"
.style("stroke", function (d) {
return "#fff";
.style("fill", function (d) {
return "#fff";
});
.rect_div {
y: -10px;
x: 2px;
width: 120px;
height: 40px;
rx: 20px;
}
x和y相对于节点位置的偏移量,rx则是把原本的方形节点变为椭圆(相当于border-radius),stroke-width设置椭圆的边框,stroke边框填充色,fill设置椭圆填充色。
4. 设置节点的文字和连接点
nodeEnter.append("text")
.text(function (d) {
return d.name;
}).on("click", function (d) {
//do something
}).on("mouseover", function (d) {
//do something
});
设置节点文字,加上点击事件和鼠标移入事件。
nodeEnter.append("circle")
.attr("r", function (d) {
return 8;
.style("stroke-width", function (d) {
return 0;
})
.style("fill", function (d) {
return "#12b36d";
})
.style("cy", function (d) {
return 10;
})
.style("cx", function (d) {
return 65;
});
r设置连接点的半径,cy和cx设置连接点相对于节点位置的偏移量。
5. 在节点加入DIV
nodeEnter.append("foreignObject")
.attr("class", "foreign_add")
.style("display", function (d) {
if (d.children == undefined && d._children == undefined) {
return "none";
}
})
.append("xhtml:div")
.attr("class", function (d) {
if (d._children == undefined) {
return "less_div";
}
return "add_div"
}).on("click", function (d) {
scope.click(svg, d, root, direction);
});
<foreignObject>SVG元素允许包含不同的XML命名空间。在浏览器的上下文中,很可能是XHTML / HTML。
6. 设置节点之间的连线
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function (d) {
var o = {
x: source.x0,
y: source.y0
};
return scope.diagonal({
source: o,
target: o
}); //diagonal - 生成一个二维贝塞尔连接器, 用于节点连接图.
})
.attr("stroke", function (d) {
if (d.depth == 1) {
return "#007568";
}
return "#12b36d";
})
.attr("stroke-width", function (d) {
if (d.depth == 1) {
return "2px";
}
return "1px";
})
.attr('marker-end', 'url(#arrow)');
scope.diagonal = d3.svg.diagonal()
.projection(function (d) {
return [d.y, d.x];
});
7. 计算节点的位置
需求
-
节点不允许出现重叠。
-
整体要长得像一棵树。
-
数据是树形的,而且每个节点的子节点数量是随机。
-
节点不允许越过边界。
-
子节点都是有顺序的,子节点按照逆时针排序。
难点
-
数据是不确定的,每个节点的子节点是随机的。
-
如何去确定每个节点的位置而且保证不会重叠。
-
如何去确定节点是否越过了边界。