【d3.js教程14】可拖动的地图详解

最后更新于:2022-04-01 14:18:24

![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-23_5742b93ab2ac9.jpg) ~~~ <html> <head> <meta charset="utf-8"> <title>中国地图</title> </head> <style type="text/css"> *{ margin: 0; padding: 0; } .link { stroke: #ccc; stroke-width: 0.5; } </style> <body> <script src="js/d3.min.js" type="text/javascript" charset="utf-8"></script> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> var width = 2000; var height = 1000; var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(0,0)"); /*定义投影*/ var projection1 = d3.geo.mercator() //麦克托投影法 .center([107, 31]) //地图的经纬度(将制定的经纬度设定为地图的中心) .scale(850) //地图放大比例 .translate([width/2, height/2]); //位移 /*传入投影,并计算路径*/ var path = d3.geo.path() .projection(projection1); //将三维地图投影到二维坐标上。为了避免混淆,特意将projection改成projection1 var force = d3.layout.force().size([900, 900]); //size设定容器的中心 var color = d3.scale.category20(); d3.json("json/chinamap.json", function(error, root) { if (error) return console.error(error); /*定义两个数组存储节点和边*/ var nodes = []; var links = []; root.features.forEach(function(d, i) { var centroid = path.centroid(d); //计算出数据的中点 centroid.x = centroid[0]; //数组0元素中存着中点的横坐标 centroid.y = centroid[1]; //数组1元素中存着中点的纵坐标 centroid.feature = d; //把数据存到feature中 nodes.push(centroid); //将节点推进组数 }); var triangles = d3.geom.voronoi().triangles(nodes); //将节点进行三角剖分,将结果保存在triangles中 triangles.forEach(function(d,i){ //用循环,将每个三角的三个点两两相连,推进边数组中 links.push( edge( d[0] , d[1] ) ); //edge函数在后面 links.push( edge( d[1] , d[2] ) ); links.push( edge( d[2] , d[0] ) ); }); force.gravity(0) //从中心产生的重力 .charge(0) //吸引力和排斥力 .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) //不写这句不能拖动 .append("path") .attr("stroke","#000") .attr("stroke-width",1) .attr("fill", function(d,i){ //为地图填充颜色 return color(i); }) .attr("d", function(d){ return path(d.feature); } ); var link = 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; } ); force.on("tick", function() { //及时设定force的源头和末尾 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; }); node.attr("transform", function(d) { //也就是nodes的数据一直在变,及时将位移改变 return "translate(" + d.x + "," + d.y + ")"; }); }); }); /*edge函数,返回源头和目标以及距离*/ 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) }; } </script> </body> </html> ~~~
';