本来要直接用D3的tree来实现树结构的,后来添加了新需求,2个父节点指向同一个子节点,然后就换成了dagre-d3来设置,这里来记录一下
版本使用:d3用的4.13.0,dagre-d3用的0.6.3
效果图如下:
var nodes = [
{ id: 0, label: '根节点', },
{ id: 1, label: '一级节点1', },
{ id: 2, label: '一级节点2', },
{ id: 3, label: '一级节点3', },
{ id: 4, label: '一级节点4', },
{ id: 5, label: '二级节点1', },
{ id: 6, label: '二级节点2', },
{ id: 7, label: '三级节点1', },
{ id: 8, label: '三级节点2', },
];
var line = [
{ start: 0, end: 1, },
{ start: 0, end: 2, },
{ start: 0, end: 3, },
{ start: 0, end: 4, },
{ start: 1, end: 5, },
{ start: 1, end: 6, },
{ start: 6, end: 7, },
{ start: 1, end: 7, },
{ start: 2, end: 8, },
];
关键代码(在网上找的,不知道出处是哪里了):
var diagGraph = { //diag图数据操作
state: [],
edg: [],
statePoint: '',
g: '',
init: function (statePoint ,state, edg) {
this.statePoint = statePoint
this.state = state
this.edg = edg
this.createG();
this.renderG();
},
createG: function () {
this.g = new dagreD3.graphlib.Graph()
.setGraph({
rankdir: 'LR' //方向
})
.setDefaultEdgeLabel(function () { return {}; });
},
drawNode: function () {
for (let i in this.state) { //画点
let el = this.state[i]
let style = '';
this.g.setNode(el.id, {
id: el.id,
label: el.label,
class: el.class,
style: el.node_id,
node_id: el.node_id,
});
}
this.g.nodes().forEach((v) => { //画圆角
var node = this.g.node(v);
node.rx = node.ry = 10;
});
},
addNode:function(nodelist){ },
drawEdg: function () {
for (let i in this.edg) { // 画连线
let el = this.edg[i]
if (el.start === this.statePoint || el.end === this.statePoint) {
this.g.setEdge(el.start, el.end, {
style: "stroke: #0fb2cc; fill: none;",
arrowheadStyle: "fill: #0fb2cc;stroke: #0fb2cc;",
arrowhead: 'vee'
});
} else {
this.g.setEdge(el.start, el.end, {
arrowhead: 'vee'
});
}
}
},
renderG: function () {
var render = new dagreD3.render();
var svg = d3.select("#svgCanvas");
svg.select("g").remove(); //删除以前的节点
var svgGroup = svg.append("g");
var inner = svg.select("g");
var zoom = d3.zoom().on("zoom", function () { //放大
inner.attr("transform", d3.event.transform);
});
svg.call(zoom);
this.drawNode();
this.drawEdg();
render(d3.select("svg g"), this.g); //渲染节点
var max = svg._groups[0][0].clientWidth > svg._groups[0][0].clientHeight ? svg._groups[0][0].clientWidth : svg._groups[0][0].clientHeight;
// var initialScale = max / 779;
var initialScale =1;
var tWidth = (svg._groups[0][0].clientWidth - this.g.graph().width * initialScale) / 2;
var tHeight = (svg._groups[0][0].clientHeight - this.g.graph().height * initialScale) / 2;
var trans = d3.zoomIdentity.translate(tWidth, 50).scale(initialScale); //.scale(initialScale)
svg.call(zoom.transform,trans); //元素居中
},
changePoint: function (point) {
this.statePoint = point * 1.0
this.renderG()
},
}
var statePoint = 0; // 当前选中的点
diagGraph.init(statePoint, nodes, line); //创建关系图
实现右键效果
contextmenuclick(e){ //右键
if (e.target.tagName === 'rect' || e.target.tagName === 'text') {
var value=e.target.__data__;
//实现逻辑
} else {
this.menuflag=false;
}
}