D3的v3版本,很古老了。
拿來繪製力導向圖,畫布初始化的代碼如下:
//代碼不完整,僅作演示以說明問題
//節點數組
var nodes = [ { name: "sssss" ,phone:"18888888888"}, { name: "vvvv" ,phone:"199999999"},{ name: "ggggg" ,phone:"20000000"} ];
//連線數組
var edges = [ { source : 0 , target: 1 },{ source : 1 , target: 0 }];
//設置畫布
var width = 1000; //畫布的寬度
var height = 1000; //畫布的高度
var svg = d3.select("body") //選擇文檔中的body元素
.append("svg") //添加一個svg元素
.attr("width", width) //設定寬度
.attr("height", height); //設定高度
//定義力導向圖佈局
var force = d3.layout.force()
.nodes(nodes) //指定節點數組
.links(edges) //指定連線數組
.size([width,height]) //指定作用域範圍
.linkDistance(150) //指定連線長度
.charge([-400]); //相互之間的作用力
//力學作用生效
force.start(); //開始作用
//添加連線
var svg_edges = svg.selectAll("line")
.data(edges)
.enter()
.append("line")
.style("stroke","#ccc")
.style("stroke-width",1);
var color = d3.scale.category20();
後來我往節點數組nodes末尾push了一個新元素,再次重繪此力導向圖,代碼如下:
//添加新節點,重繪力導向圖的代碼
function reGraph(){
nodes.push({name: "ffffuuuuucccckkk" ,phone:"18888888888"});
edges.push({source : 0 , target: 3});
//添加節點
var svg_nodes = svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r",20)
.style("fill",function(d,i){ //設置填充顏色
return color(i);
})
.on("click", function(d,i){ //添加點擊事件
alert("這是"+d.name+",電話:"+d.phone);
})
.call(force.drag); //使得節點能夠拖動
//添加描述節點的文字
var svg_texts = svg.selectAll("text")
.data(nodes)
.enter()
.append("text")
.style("fill", "black")
.attr("dx", 20)
.attr("dy", 8)
.text(function(d){
return d.name;
});
force.on("tick", function(){ //對於每一個時間間隔
//更新連線座標
svg_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; });
//更新節點座標
svg_nodes.attr("cx",function(d){ return d.x; })
.attr("cy",function(d){ return d.y; });
//更新文字座標
svg_texts.attr("x", function(d){ return d.x; })
.attr("y", function(d){ return d.y; });
});
}
就報了幾千個錯:
<circle> attribute cx: Expected length, “NaN”
Error: <circle> attribute cx: Expected length, "NaN".
等諸多類似錯誤,都是告訴我屬性缺失。
研究了很久,最後發現問題所在:
指定的節點數組不能直接拿來用作繪圖數據。
需要通過force這個轉換器轉換之後才能作爲數據使用。
因此直接push新元素進數組然後刷新力導向圖是不可行的,新元素沒經過force的處理,缺失了很多屬性,故報上述錯誤。
因此解決辦法如下:
1.新建一個節點數組及連線數組,將之前數組的數據如name,phone等自己設定的屬性拷貝到新數組
2.新數組push你要添加的元素
3.重新初始化力導向圖,這段代碼尤其重要:
//定義力導向圖佈局
var force = d3.layout.force()
.nodes(nodes) //指定節點數組
.links(edges) //指定連線數組
.size([width,height]) //指定作用域範圍
.linkDistance(150) //指定連線長度
.charge([-400]); //相互之間的作用力
//力學作用生效
force.start(); //開始作用
因爲新增的元素一樣需要經過force的轉換處理才能作爲繪製節點的數據使用,具體見以下博主的這段話
如何理解佈局
從上面的圖可以看到,佈局的作用是:將不適合用於繪圖的數據轉換成了適合用於繪圖的數據。因此,爲了便於初學者理解,將佈局的作用解釋成:數據轉換。
佈局有哪些
D3 總共提供了 12 個佈局:餅狀圖(Pie)、力導向圖(Force)、弦圖(Chord)、樹狀圖(Tree)、集羣圖(Cluster)、捆圖(Bundle)、打包圖(Pack)、直方圖(Histogram)、分區圖(Partition)、堆棧圖(Stack)、矩陣樹圖(Treemap)、層級圖(Hierarchy)。
12 個佈局中,層級圖(Hierarchy)不能直接使用。集羣圖、打包圖、分區圖、樹狀圖、矩陣樹圖是由層級圖擴展來的。如此一來,能夠使用的佈局是 11 個(有 5 個是由層級圖擴展而來)。這些佈局的作用都是將某種數據轉換成另一種數據,而轉換後的數據是利於可視化的。
————————————————
版權聲明:本文爲CSDN博主「Lelliam」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_31052401/article/details/93786425
然後接上述重繪代碼即可。
總結:本次錯誤原因是節點數組、連線數組新增元素後,未做轉換處理直接拿來繪圖,而我們知道,未經轉換器處理的數據是無法用於繪圖的,會導致很多繪圖必須的屬性缺失,因此,需將數組拷貝後重新用轉換器如force(此處是力導向圖,僅用force說明問題)轉換後重繪,就不會導致屬性缺失了。
--------end------------