D3力导向地图制作

制作一个中国地图的力导向地图,支持鼠标拖拽,省份作为节点,连线用三角剖分生成。

访问地址:http://106.14.147.72/Graphtest/forcemap.html

效果图:
这里写图片描述

  1. 定义一个力导向布局、投影和地理路径生成器
    创建一个力导向布局,一个墨卡托投影和一个地理路径生成器
   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 + ")";
            });
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值