最近開發項目需要根據後臺數據動態畫出流程圖,因此瞭解折磨了一點點D3,官網資料和案例好像比較少說明,經過這些天的挖地三尺地找網上資料,終於折磨出了一點點東西。以下是本人這裏的一個小demo,希望對有需要的朋友有幫助吧。(例子有點粗糙,僅是爲了有個效果而已,實際中應根據數據來正確規範的顯示流程圖)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
g.type-current>rect {
fill: #1E9FFF;
}
g.type-success>rect {
fill: green;
}
g.type-fail>rect {
fill: red;
}
text {
font-weight: 300;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
font-size: 14px;
}
.node rect {
stroke: #999;
fill: #fff;
stroke-width: 1.5px;
}
.edgePath path {
stroke: #333;
stroke-width: 1.5px;
}
#tooltip {
position: absolute;
width: 150px;
height: auto;
padding: 5px;
background-color: white;
border: 1px solid #ccc;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
font-style: 12px;
-webkit-box-shadow: 4px 4px 10px rbga(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rbga(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rbga(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: sans-serif;
font-size: 16px;
line-height: 20px;
}
</style>
</head>
<!-- <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="http://cpettitt.github.io/project/dagre-d3/v0.3.0/dagre-d3.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script> -->
<!--V4版本支持鼠標放大縮小-->
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://cdn.bootcss.com/dagre-d3/0.6.3/dagre-d3.js"></script>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<body>
<div id="tooltip" class="hidden">
<p><strong>提示:</strong></p>
<p><span id="tooltip_value"></span></p>
</div>
<svg id="svg-canvas" width=1000></svg>
</body>
<script>
var dataFlow = [
{
id: 0,
label: '開始',
status: 'start',
target: 1,
back_target: null,
description: '',
x: 206,
y: 60
},
{
id: 1,
label: '事項受理',
status: 'success',
target: 2,
back_target: null,
description: 'title666',
x: 206,
y: 60
}, {
id: 2,
label: '初審',
status: 'success',
target: 3,
back_target: null,
description: 'tit677657',
lineTitle:'是',
x: 326,
y: 60
}, {
id: 3,
label: '初審回覆',
status: 'success',
target: 4,
back_target: null,
description: 'title22111',
lineTitle:'否',
x: 266,
y: 100
}, {
id: 4,
label: '事情打回',
status: 'fail',
target: 5,
back_target: 2,
description: 'title1111',
x: 200,
y: 100
}, {
id: 5,
label: '事項辦結',
status: 'current',
target: 7,
back_target: null,
description: 'title222',
x: 383,
y: 100
}, {
id: 6,
label: '候審補正',
status: 'done',
target: null,
back_target: null,
description: 'title33333',
x: 100,
y: 200
}, {
id: 7,
label: '結束',
status: 'end',
target: null,
back_target: null,
description: '',
x: 100,
y: 200
}
]
var g = new dagreD3.graphlib.Graph()
.setGraph({ rankdir: 'LR' })//流程圖方向:LR(左右),RL,TB(上下),BT
.setDefaultEdgeLabel(function () { return {}; });
var render = new dagreD3.render();
var svg = d3.select("svg"),
svgGroup = svg.append("g");
//添加鼠標滾輪放大縮小事件
var zoom = d3.zoom().on("zoom", function () {
svgGroup.attr("transform", d3.event.transform);
});
svg.call(zoom);
dataFlow && dataFlow.map((item, i) => {
let shape, fill;
if(item.back_target!=null){
shape = 'diamond';
}else if(item.status=='start'||item.status=='end'){
shape = 'ellipse';
}else{
shape = 'rect';
}
if(item.status=='success'){
fill = 'green';
}else if(item.status=='fail'){
fill = 'red';
}else if(item.status=='current'){
fill = '#1E9FFF';
}else{
fill = 'white';
}
g.setNode(item.id, {//畫節點
label: item.label,
// class: "type-" + item.status,
shape:shape,//形狀:circle,ellipse,cross,diamond,square,star,triangle,wye
style: "stroke-width:2px;fill: "+fill+";",//節點樣式
description: item.description,
rx: 5,//矩形節點圓角度
ry: 5,
// x: item.x,//座標無效???
// y: item.y,
// width: 20,
// height: 100,
// id: "status" + i
});
if (item.target && !item.back_target) {//畫線
g.setEdge(item.id, item.target, {
label:item.lineTitle?item.lineTitle:'',
style: "stroke: #0fb2cc; fill: none;",//線樣式
arrowheadStyle: "fill: #0fb2cc;stroke: #0fb2cc;",//箭頭樣式
arrowhead: 'vee' //箭頭形狀樣式
})
} else if (item.back_target) {
g.setEdge(item.id, item.target, {})
g.setEdge(item.id, item.back_target, {})
}
})
// g.nodes().forEach(function (v) {
// var node = g.node(v);
// node.rx = node.ry = 5;//控制節點圓角度
// node.style = "fill: #14ff00;width:100px";//節點顏色
// });
render(svgGroup, g);//繪製圖表
d3.select("body").style("background-color", "#ef9934");//整個頁面背景色
//鼠標懸停節點事件
svgGroup.selectAll("g.node").on('mouseover', function (v) {
//顯示提示信息方案一:更新提示條位置和值
d3.select("#tooltip")
.attr("style", "left:" + g.node(v).x + "px" + ";top:" + g.node(v).y + "px")
.select("#tooltip_value")
.text("規則描述:" + g.node(v).description);
//顯示提示條
d3.select("#tooltip").classed("hidden", false);
//顯示提示信息方案二:
// d3.select(this).attr("fill", "#f34848").append("title").text(function (d) {
// return "規則描述:" + g.node(v).description;
// }).attr("id", "tooltip");
});
svgGroup.selectAll("g.node").on('mouseout', function (v) {
//顯示提示信息方案一:隱藏提示條
d3.select("#tooltip").classed("hidden", true);
//顯示提示信息方案二:
// d3.select(this).attr("fill", "rgb(0,0," + (v * 10) + ")");
// d3.select("#tooltip").remove();
});
//節點文字超出寬度時,隱藏並顯示省略號,無效???
// svgGroup.selectAll("g.node").attr("style", "width:10px;height:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;");
//添加title屬性後,鼠標hover時無效???
// svgGroup.selectAll("g.node").attr("title", function (v) { return g.node(v).description })
// // .each(function (v) { $(this).tipsy({ gravity: "w", opacity: 1, html: true }); });
var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
svgGroup.attr("transform", "translate(" + xCenterOffset + ", 100)");//整個流程圖的位置在界面中,左右上下居中顯示
// var initialScale = 0.75;
// svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));
svg.attr("height", 400);
</script>
</html>
效果圖如下:
另外,本人最近還在折磨D3流程圖的座標位置、節點上的文字超出寬度時隱藏顯示省略號的問題,各網友要是有相關知識,有方法的,是否可以分享下呢?