【D3.js】Force-Directed Japan
「Force-Directed States of America」を参考に日本版を作ってみました。
コードはほぼ参考にしたサンプルそのままですが、一応載せておきます。
サンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
d3.json("../../_geodata/japan_light.geojson", function(error, json) { if (error) return console.error(error); draw(json); }) function draw(json){ var width = 1000; var height = 1000; var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(0,0)"); var projection = d3.geo.mercator() .center([139.0032936, 36.3219088]) .scale(2000) .translate([width/2, height/2]); var path = d3.geo.path().projection(projection); var nodes = []; var links = []; json.features.forEach(function(d, i) { //各領域の中心点取得 var centroid = path.centroid(d); centroid.x = centroid[0]; centroid.y = centroid[1]; centroid.feature = d; nodes.push(centroid); //ノードデータを生成 }); //ノードデータから、ドロネー三角分割データを生成 var triangles = d3.geom.voronoi().triangles(nodes); triangles.forEach(function(d,i){ //各三角形の頂点からソースポイント、ターゲットポイント、2点の距離をリンクデータとして保存 links.push( edge( d[0] , d[1] ) ); links.push( edge( d[1] , d[2] ) ); links.push( edge( d[2] , d[0] ) ); }); //console.log(nodes); //console.log(links); //力学グラフ生成 var force = d3.layout.force().size([width, height]); force.gravity(0.01) .charge(0.01) .nodes(nodes) .links(links) .linkDistance(function(d){ return d.distance; }) .start(); //ノード(地形)の描画 var node = svg.selectAll("g") .data(nodes) .enter() .append("g") .attr("transform", function(d) { return "translate(" + -d.x + "," + -d.y + ")"; }) .call(force.drag) //forceレイアウトのドラッグビヘイビアを設定 //地形描画 .append("path") .attr({ "transform": function(d) { return "translate(" + d.x + "," + d.y + ")"; }, "stroke": "#ccc", "stroke-width": 1, "fill": "green", "d": function(d){ return path(d.feature) } }); //ライン(地形を結ぶ線)の描画 var link = svg.selectAll("line") .data(links) .enter() .append("line") .attr({ "class": "link", "x1":function(d){ return d.source.x }, "y1":function(d){ return d.source.y }, "x2":function(d){ return d.target.x }, "y2":function(d){ return d.target.y }, }) //力学グラフのアップデート処理 force.on("tick", function() { link.attr({ "class": "link", "x1":function(d){ return d.source.x }, "y1":function(d){ return d.source.y }, "x2":function(d){ return d.target.x }, "y2":function(d){ return d.target.y }, }); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); }); function edge(a, b) { var dx = a[0] - b[0], dy = a[1] - b[1]; return { source: a, target: b, distance: Math.sqrt(dx * dx + dy * dy) }; } } |