本個例子技術點重點和難點:
1. 箭頭如何顯示在節點相連的直線上
2. 箭頭與節點圓之間的距離因爲縮放的動態緣由如何控制,使箭頭一直保持在圓外圍
3. 鼠標中間鍵滾動帶動圖像縮放(此點若知事件則較易)
4. 鼠標拖拽控制條實現圖像縮放。
5. 第3,4兩個控件結合交替使用實現縮放效果(關鍵是兩個事件的縮放數值倍數範圍和在圖中縮放距離範圍要保持一致。javascript
因爲這個模型是從我在作的項目中抽取的模型例子,因此,界面比較醜,旁邊的圖拽條的 「+」,「-"圖片我也沒加上去。html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>network </title> <script type="text/javascript" src="d3.v3.min.js"></script> </head> <body> <script type="text/javascript"> var h=500; var w=800; var scale_max = 2.3; var scale_min = 0.2; var current_scale = 1.1; var bar_len = 100; var border_len = 20 ; var colors = d3.scale.category20() //(1)定義節點和聯繫對象數組 var dataset = { nodes:[//節點 { name:"Peter",r:16}, { name:"Bob",r:21}, { name:"Tony",r:31}, { name:"Davir",r:25}, { name:"Edward",r:27}, { name:"Army",r:19}, { name:"Jonn",r:35}, { name:"Hannah",r:33}, { name:"Jack",r:29}, { name:"Jerry",r:32} ], edges:[//邊 { source:0,target:1,weight:1,color:1}, { source:0,target:2,weight:3,color:4}, { source:0,target:3,weight:4,color:6}, { source:0,target:4,weight:6,color:65}, { source:1,target:5,weight:3,color:76}, { source:2,target:5,weight:8,color:879}, { source:2,target:5,weight:7,color:989}, { source:3,target:4,weight:9,color:643}, { source:5,target:8,weight:1,color:54}, { source:5,target:9,weight:3,color:54}, { source:6,target:7,weight:4,color:45}, { source:7,target:8,weight:0,color:43}, { source:2,target:8,weight:8,color:243}, { source:3,target:8,weight:1,color:43}, { source:5,target:8,weight:5,color:13}, { source:6,target:8,weight:3,color:351}, { source:8,target:9,weight:1,color:1} ] }; //(2)轉化數據爲適合生成力導向圖的對象數組 var force=d3.layout.force() .nodes(dataset.nodes)//加載節點數據 .links(dataset.edges)//加載邊數據 .size([w,h])//設置有效空間的大小 .linkDistance(150)//連線的長度 .charge(-500) .start();//設置生效 var svg = d3.select("body") .append("svg") .attr("width",w) .attr("height",h) .attr("pointer-events","all") .call(d3.behavior.zoom().on("zoom",redraw))//redraw .on("mousedown.zoom",null) .append('svg:g') .attr("cursor","pointer"); var marker = d3.select("svg").append("svg:defs") .selectAll("marker") .data(dataset.nodes) //not edges .enter() .append("svg:marker"); marker.attr({ id:function(d){ return "marker-" + d.r; }, viewBox:"0 -5 10 10", refX:function(d){ console.log("d.r:" + d.r); return d.r ; }, markerWidth:10, markerHeight:10, orient: "auto" }) .append('svg:path') .attr('d',"M0,-5L10,0L0,5") .attr("fill",function(d){ return "black"; }); var dtb = d3.select("svg") .append("svg:g") .attr({ heigth: bar_len, width: 200 , x: 0, y: 0 }); dtb.append('rect')//top .attr({ width:border_len, height:border_len, x: 10, y: 10 }) .attr("fill",'black'); dtb.append("rect") //bottom .attr({ width:border_len, height:border_len, x:10, y:130 }) .attr("fill","black"); dtb.append("rect") .attr({ width:4, height:bar_len, x:19, y:30 }) .attr("fill","grey"); var bar = dtb.append('rect') .attr({ width:20, height:5, x: 10, y: 82, fill:"green", cursor:"pointer" }) .call(d3.behavior.drag().on("drag",dragmove));//dragmove //(3)建立做爲連線的svg直線 var edges = svg.append('g') .attr('cursor','pointer') .selectAll(".link") .data(dataset.edges) .enter() .append("line") .attr("class","link") .style("stroke",function(d){// 設置線的顏色 return colors(d.color); }) .style("stroke-width",function(d,i){//設置線的寬度 return 1.5; }) .attr("marker-end",function(d){ return "url(#marker-" + (d.target.r) + ")"; }); //(4) 建立做爲連線的svg圓形 var nodes = svg.selectAll(".node") .data(dataset.nodes) .enter().append('g') .attr('class','node') .call(force.drag);//能夠拖動 nodes.append("svg:circle") .attr("r",function(d){ return d.r;//the r of circle }) .style("fill",function(d){ return colors(d.r*d.r*d.r); }); nodes.append('text') .attr("text-anchor", "middle") .attr("font-size", "10px") .attr('stroke', 'black') .attr('stroke-width', function (d) { return 0; }) .text(function (d) { return d.name; }); nodes.append("title") .text(function (d) { return d.name; }); //(5)打點更新,沒有的話就顯示不出來了 force.on('tick',function(){ edges.attr("x1",function(d){ return d.source.x; }) .attr("y1",function(d){ return d.source.y; }) .attr("x2",function(d){ return d.target.x; }) .attr("y2",function(d){ return d.target.y; }); //(6)設置節點座標,節點先生成再肯定座標的 nodes.attr("cx",function(d){//節點有座標屬性 return d.x; }) .attr("cy",function(d){ return d.y; }).attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; }); }); var scale = 1.1; var currentY = 0; function redraw(){ //放大縮小 鼠標滑動 scale放大倍數,translate是轉變,轉換 scale = d3.event.scale; if(scale > scale_max || scale < scale_min){ return ; } currentY = scale/(scale_max-scale_min)*bar_len + 18; bar.attr("y",currentY); console.log("scale:" + scale +",currentY:" + currentY); svg.attr("transform","translate(" + d3.event.translate + ")" + "scale(" + scale + ")" ); } function dragmove(){ var x = 0; //not move in x axis var dy = d3.event.y; var diffY = dy ; //+currentY - 30 ; if(diffY > 130){//bar_len + border_len+ margin diffY = 125; return ; } if(diffY < 30){ //border_len+ margin diffY = 30; return ; } //console.log( "diffY:" + diffY + "dy:" + dy); scale = diffY /bar_len*(scale_max-scale_min); //console.log("scale:" + scale); bar.attr("y",diffY) svg.attr("transform","translate(" + [(w/3)-(w*current_scale/3),(h/2) - (h*current_scale/2)] +")" + "scale(" + scale + ")" ); } </script> </body> </html>