Wechat: yu389741| Email: gisdqy@163.com

Shop:https://www.giserdqy.com/shop

d3.js leaflet.js OpenStreetMap的综合应用


                                        一个可视化的工作案例

效果图

代码的边捆绑算法借鉴了D3.JS官方案例的js库。 链接如下:点击打开链接

案例分析

本案例展示的上海市某一天12点出租车数据流量图,先将上海市进行区域划分,之后将出租车数据映射到相应的区域,并映射到osm地图上。最后用当D3标注出区域以及流量图。

一. 准备数据

对上海市出租车数据进行处理,处理后部分文件显示如下。data.json文件

{"node":[
{
"id":0,
"x":1211.85,
"y":311.25
},
{
"id":1,
"x":1212.0499,
"y":311.25
},
{
"id":2,
"x":1212.2499,
"y":311.25
},.....],
"edge":[
{
"id":0,
"source":1,
"target":138,
"num":1
},
{
"id":1,
"source":1,
"target":141,
"num":1
},.....],
"num":[
0,2,4,6,9,2,5,4,13,91,33,24,19,11,0,5,0,3,16,18,
2,2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,3,5,....]}

二.可视化展示

首先加载osm地图,之后访问json文件,最后显示效果。(注意,d3访问文件是要开本地服务器的,建议使用node.js开启本地服务器,安装node.js后,在相应文件夹中打开命令行,输入http-server,在浏览器打开即可)。

本处使用了一种边捆绑算法,减弱了边捆绑之间的相互遮挡的问题。

代码如下:
相关说明:本处使用的不是最新版的leaflet.js库,d3用的是d3.v3版本。
d3-ForceEdgeBundling.js可在图下的链接找到。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>FDEB Shanghai Example</title>

    <script type="text/javascript" src="js/jquery.js"></script>
    <script src="js/d3.v3.js" charset="utf-8"></script>
    <script type="text/javascript" src="js/leaflet.js"></script>
    <script type="text/javascript" src="d3-ForceEdgeBundling.js"></script>
    <link rel="stylesheet" type="text/css" href="css/leaflet.css">
    <style type="text/css">
        #map{
            height:800px;
            width: 1200px;
        }
    </style>
</head>

<body>
    <div id="map">
    </div>
    <script>
        $(function () {
                      var baseLayer = L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/dark-v9/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoiY29va2llcyIsImEiOiJjaW9sOGpwYjgwMGJtdmtqYmFieGYwcGR5In0.ot-rN7HEza9xJSijmrAOUQ', {
           maxZoom: 18,
           attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
            '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="http://mapbox.com">Mapbox</a>',
           id: 'mapbox.streets'
      });
    var mymap = new L.Map('map', {
     center: new L.LatLng(31.25, 121.58),
     zoom: 11,
     layers: [baseLayer]
   });
            // Initialize the SVG layer
           mymap._initPathRoot();

            d3.json("bundling_data/data-nodeNum.json", function (json) {
                //Transform the XML data into a proper format used by the algorithm
               
                var eedges = [];
                var edgeNum=[];
                var nnodes = {};
                var nodeNum=[];
                var min_x = Number.MAX_VALUE;
                var max_x = 0;
                var min_y = Number.MAX_VALUE;
                var max_y = 0;
                json.node.forEach(function(d){
                    var key=d.id;
                    var x = Math.abs(d.x);
                    var y = Math.abs(d.y);
                    nnodes[key] = {
                        'x': x,
                        'y': y
                    };
                    min_x = Math.min(min_x, x);
                    max_x = Math.max(max_x, x);
                    min_y = Math.min(min_y, y);
                    max_y = Math.max(max_y, y);

                });
             json.edge.forEach(function(d){
                 var key=d.id;
                    eedges.push({
                        'source':d.source,
                        'target': d.target
                    });
                    edgeNum[key]=d.num;
                });
             var length=json.num.length;
              for(var i=0;i<length;i++)
              {
                      nodeNum[i]=json.num[i];
              }
                var new_scale_x = d3.scale.linear().domain([min_x, max_x]).range([1000, 50]);
                var new_scale_x_decode = d3.scale.linear().domain([1000,50]).range([min_x, max_x]);

                var new_scale_y = d3.scale.linear().domain([min_y, max_y]).range([560,50]);
                var new_scale_y_decode = d3.scale.linear().domain([560,50]).range([min_y, max_y]);

                for (var i = 0; i < json.node.length; i++) {
                    nnodes[i].x = new_scale_x(nnodes[i].x);
                    nnodes[i].y = new_scale_y(nnodes[i].y);
                }
                // console.log('Nodes', nnodes);
                // console.log('Edges', eedges);

                //Run the FDEB algorithm using default values on the data
                var fbundling = d3.ForceEdgeBundling().nodes(nnodes).edges(eedges);
                var results = fbundling();
              
               // We pick up the SVG from the map object..........
            var m_svg = d3.select("#map").select("svg");
            var svg = m_svg.append("g");
               
                var d3line = d3.svg.line()
                    .x(function (d) {
                        var latlon=new L.LatLng(new_scale_y_decode(d.y)/10, new_scale_x_decode(d.x)/10);
                        //console.log(d.x);.
                        return mymap.latLngToLayerPoint(latlon).x;
                    })
                    .y(function (d) {
                          var latlon=new L.LatLng(new_scale_y_decode(d.y)/10, new_scale_x_decode(d.x)/10);
                        //console.log(d.x);.
                        return mymap.latLngToLayerPoint(latlon).y;
                        //return d.y;
                    })
                    .interpolate("linear");

                var maxNum=Math.max.apply(Math,edgeNum);//最大数值
                 var maxNodeNum=Math.max.apply(Math,nodeNum);
                 var avNum=0;
                
                 var allNum=0;
               
                 for(var i=0;i<edgeNum.length;i++){
                       allNum+=edgeNum[i];
                 }
                 avNum=Math.round(allNum/edgeNum.length);
                console.log(maxNum);
                 console.log(avNum);
                 console.log(results.length);
                 console.log(results[3]);
                 var r=0;
                 var color=null;
                //plot the data
                for (var i = 0; i < results.length; i++) {
                     r=Math.round(edgeNum[i]*125/avNum)+130;
                   color=d3.rgb(r,0,0);
                    svg.append("path").attr("d", d3line(results[i]))
                        .style("stroke-width", 1)
                        .style("stroke", color)
                        .style("fill", "none")
                        .style('stroke-opacity', 0.115);
                   //d3line(results[i]);
                }

                //draw nodes
                svg.selectAll('.node')
                    .data(d3.entries(nnodes))
                    .enter()
                    .append('circle')
                    .classed('node', true)
                    .attr('fill','#ffee00')
                    .attr('r',function(d,i){
                        if (nodeNum[i]==0) {
                            return 0;
                        }
                         return Math.round(nodeNum[i]*4.0/maxNodeNum)+2;
                    })
                    .attr("transform", function(d,i){
                         var latlon=new L.LatLng(new_scale_y_decode(nnodes[i].y)/10, new_scale_x_decode(nnodes[i].x)/10)
                        // console.log(latlon);
                         return "translate(" + mymap.latLngToLayerPoint(latlon).x + "," + mymap.latLngToLayerPoint(latlon).y + ")";
                   });
                    nodeNum=[];
                    nnodes=[];
            });
        })
    </script>
</body>

</html>

转载自:https://blog.csdn.net/lccla120712/article/details/69931442