基于force布局的map

来源:互联网 发布:凯立德自适应端口文件 编辑:程序博客网 时间:2024/06/05 22:34

基于布局的使用对数据的结构形式要求比较高,所以我们在学习的时候要注意每个布局所需要的结构,在进行与其他模块整合的时候就要注意数据的提取转换,比如说这这篇,1.构造node数据,初始数据是每个省的周边geo,我们通过path.centroid()—–》拿到中心结点坐标,这就是force布局中的node,同时也要将周边路径本身保存进去,因为我们在基于force绘制node时,要绘制出周边路径,不像circle一样。2.构造links,为了构造source,target数据,我们需要将每个结点两两连接,所以用了泰森多边形先处理数据,称为三角分割,得到一个数据,每个三角形为一级元素,每个三角形中有三个结点,我们通过将三个结点进行edge方法格式整理成source,target所需要的形式,这样就有了links。最后绑定nodes与links。

<script>    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([107, 31])                        .scale(850)                        .translate([width/2, height/2]);    /*路径生成器加载projection*/    var path = d3.geo.path()                    .projection(projection);    /*设置force导向图布局*/    var force = d3.layout.force().size([width, height]);    var color = d3.scale.category20();    d3.json("china_simplify.json", function(error, root) {        if (error)             return console.error(error);        console.log(root);        console.log(root.features);

这里写图片描述

        var nodes = [];        var links = [];        //数组的forEach方法来循环        root.features.forEach(function(d, i) {            var centroid = path.centroid(d);   //得到每个省的中心坐标            centroid.x = centroid[0];            centroid.y = centroid[1];            centroid.feature = d;            nodes.push(centroid);//将x,y,d本身保存在node中        });        console.log(nodes);

这里写图片描述

        /*为了得到links的数据,用泰森多边形三角分割处理nodes*/        var triangles = d3.geom.voronoi().triangles(nodes);        console.log(triangles)

这里写图片描述

        /*对泰森多边形处理后,返回一个多边形数组,每个一级元素中有三个点,就是一个三角形,有每个triangle顶点的坐标,我们再取出里边的数据进行转换成links的数据*/        triangles.forEach(function(d,i){            links.push( edge( d[0] , d[1] ) );    //每两两顶点都做一次连线,放到link是数据中            links.push( edge( d[1] , d[2] ) );            links.push( edge( d[2] , d[0] ) );        });        console.log(links);

这里写图片描述

        /*配置力导向图参数*/        force.gravity(0)            .charge(0)            .nodes(nodes)            .links(links)            .linkDistance(function(d){ return d.distance; })            .start();        /*绑定node数组*/        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("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 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() {                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) {                  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)        };    }</script>

这里写图片描述