製作一箇中國地圖的力導向地圖,支持鼠標拖拽,省份作爲節點,連線用三角剖分生成。
訪問地址:http://106.14.147.72/Graphtest/forcemap.html
效果圖:
- 定義一個力導向佈局、投影和地理路徑生成器
創建一個力導向佈局,一個墨卡託投影和一個地理路徑生成器
var width = 1600;
var height = 1000;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(0,0)");
var force = d3.layout.force()
.size([width, height]);
var projection = d3.geo.mercator()
.center([107, 31])
.scale(850)
.translate([width/2, height/2]);
var path = d3.geo.path()
.projection(projection);
2.請求GeoJSON文件
文件名稱爲China.geojson,保存了中國各省份的地理信息通過d3.json讀入。
var color = d3.scale.category20();
d3.json("china.geojson", function(error, root) {
if (error)
return console.error(error);
console.log(root.features);
3.計算節點數組和連線數組
var nodes = [];
root.features.forEach(function(d, i) {
//計算省份的中心座標
var centroid = path.centroid(d);
//定義兩個變量x和y,保存中心座標
centroid.x = centroid[0];
centroid.y = centroid[1];
//將地理特徵保存在對象裏
centroid.feature = d;
//添加到節點數組中
nodes.push(centroid);
});
var voronoi = d3.geom.voronoi()
.x(function(d){
return d.x;
})
.y(function(d){
return d.y;
});
var links = voronoi.links(nodes);
console.log(nodes);
console.log(links);
4.設定力導向佈局的屬性
最重要的是兩節點之間的距離設置,使其節點之間保持適當的位置間隔。
force.gravity(0)
.charge(0)
.linkDistance(function(d){
var dx = d.source.x - d.target.x;
var dy = d.source.y - d.target.y;
return Math.sqrt( dx*dx + dy*dy );
})
.nodes(nodes)
.links(links)
.start();
5.繪製節點和連線
var nodeGroups = svg.selectAll("g")
.data(nodes)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + -d.x + "," + -d.y + ")"; })
.call(force.drag)
.append("path")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("stroke","#000")
.attr("stroke-width",1)
.attr("fill", function(d,i){
return color(i);
})
.attr("d", function(d){
return path(d.feature);
} );
var lines = svg.selectAll("line")
.data(links)
.enter()
.append("line")
.attr("class","link")
.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.運動更新
當鼠標進行拖拽時,力導向發生作用。
force.on("tick", function() {
lines.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; });
nodeGroups.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
});