zoukankan      html  css  js  c++  java
  • D3+Leaflet

    前言:虽然Leaflet提供了强大的画图工具,不过它的速度不是很尽人意,当数据量较大的时候,需要较长的渲染时间,交互好感度会降低。
    因此我们可以考虑使用D3,在leaflet的地图上蒙上一个svg,在svg上画图会加快一些速度,获得更好的交互体验。

    D3官网上有Leaflet+D3的相关介绍https://bost.ocks.org/mike/leaflet/,有一篇CSDN的博客翻译了这篇文章http://blog.csdn.net/zhang1244j/article/details/41440289
    文章中已经讲述的内容不再赘述,我具体讲一讲我在实现这部分代码与之不同之处,以及可能需要注意的地方。

    d3.json("us-states.json", function(error, collection) {
    if (error) throw error;
    
    // code here
    });

    认真阅读官网中的代码,能了解到它的数据源来自于json文件(如上),它将整个处理管程都包在了这个函数里,在本文中用到的数据来自数据库,虽然有尝试过将其转换成json格式的变量,但依旧throw error
    我的解决办法是:
    假如我要画圆,我需要点的x,y坐标,半径和颜色(d3画圆的方式详见博客“如何使用d3画基础图形”)
    用一个数组去保存圆的这些属性数据,注意保存的是经纬度的坐标数值,当在画图的时候再将数据转换成svg的坐标。之所以这样做,是因为,这个圆的地理位置(也就是latLng)是永远不变的,而它的svg坐标会随着“缩放”而改变,因此需要在‘zoomend’的事件回调函数中,使用该圆的经纬度坐标去更新它的svg坐标。具体函数的写法是
    //调整圆的大小,在onMapZoom中调用

    function adjustCircle(){
    d3.selectAll("circle")
    .attr('cx', o => mymap.latLngToLayerPoint([o.x_axis, o.y_axis]).x)
    .attr('cy', o => mymap.latLngToLayerPoint([o.x_axis, o.y_axis]).y);
    }

    注意,和上文提到的两篇博客不同,这种方法并不需要调整画布,只要初始化的时候定义一下画布大小即可

    //鼠标缩放操作
    function onMapZoom(){
    adjustSVG();
    adjustCircle();
    }

    整体的代码如下:

    <!DOCTYPE html>
    <html>
      <head>
        <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
        
        <meta charset="utf-8" />
    
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" ">
        
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.1.0/dist/leaflet.css" integrity="sha512-wcw6ts8Anuw10Mzh9Ytw4pylW8+NAD4ch3lqm9lzAsTxg0GFeJgoAtxuCLREZSC5lUXdVyo/7yfsqFjQ4S+aKw==" crossorigin=""/>
        <script src="https://unpkg.com/leaflet@1.1.0/dist/leaflet.js" integrity="sha512-mNqn2Wg7tSToJhvHcqfzLMU6J4mkOImSPTxVZAdo+lcPlk+GhZmYgACEe0x35K7YzW1zJ7XyJV/TT1MrdXvMcA==" crossorigin=""></script>
        
        <style>body { padding: 0; margin: 0; } html, body, #mapid { height: 500px;  960px; }</style>
      </head>
      <body>
      <script src="http://d3js.org/d3.v3.min.js"></script>
      <div id="mapid" ></div>
        <script>
            var mymap =  L.map('mapid').setView([51.505, -0.09], 13);
            L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
            maxZoom: 18,
            attribution: 'Map data &copy; <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'
            }).addTo(mymap);
    
        //加载SVG
        //The data for our line
     var lines = new Array();
    
                
    var circleData = [{"lat": "51.513336399623476", "lng": "-0.0885772705078125"},
    {"lat": "51.511092905004745",  "lng": "-0.09733200073242189"},
    {"lat": "51.50543026060531",  "lng": "-0.10145187377929689"},
    {"lat": "51.499980636437265",   "lng": "-0.09853363037109376"},
    {"lat": "51.497202145853784",  "lng": " -0.08806228637695314"},
    {"lat": "51.4978433510224",  "lng": "-0.08222579956054689"},
    {"lat": "51.50051494213075",  "lng": "-0.07570266723632814"},
    {"lat": "51.50564395807757",  "lng": "-0.07209777832031251"},
    {"lat": "51.51312273822952",  "lng": "-0.08050918579101564"},
    {"lat": "51.51002453540032", "lng": "-0.07535934448242189"}];
    //加载SVG
    var svg = d3.select(mymap.getPanes().overlayPane).append("svg").attr("class", "leaflet-zoom-hide"),  
        g = svg.append("g"); 
    var jsonCircles = new Array();
    function drawCircle(){
            circleData.forEach(function(d){
                console.log(d);
                jsonCircles.push({"x_axis":d.lat,"y_axis":d.lng,"radius":12,"color":"green"});
            });
            console.log("drawCircle");    
            console.log(jsonCircles);
            var t = svg.selectAll("circle")
                       .data(jsonCircles);                    
            var circleAttributes =
                 t
                .enter()
                .append("circle")
                .attr("cx",function(d){console.log(mymap.latLngToLayerPoint(L.latLng(d.x_axis,d.y_axis)));return mymap.latLngToLayerPoint(L.latLng(d.x_axis,d.y_axis)).x;})
                .attr("cy",function(d){return mymap.latLngToLayerPoint(L.latLng(d.x_axis,d.y_axis)).y;})
                .attr("r",function(d){return d.radius;})
                .style("fill",function(d){return d.color;});
            
    }
    //调整圆的大小,在onMapZoom中调用
    function adjustCircle(){
            console.log("draw");    
             d3.selectAll("circle")
            .attr('cx', o => mymap.latLngToLayerPoint([o.x_axis, o.y_axis]).x)
            .attr('cy', o => mymap.latLngToLayerPoint([o.x_axis, o.y_axis]).y);
    }
    //鼠标缩放操作
    function onMapZoom(){
        //adjustSVG();
        adjustCircle();
    }
    function initial(){
        svg.attr("width", 1500)
               .attr("height", 800);
        drawCircle();
    } 
    
    //初始化画图的函数
    initial();
    //事件响应
    mymap.on('zoom',onMapZoom);                         
    </script>
    
      </body>
    </html>


  • 相关阅读:
    Rabbitmq消息接收方通知发送方
    Rabbitmq接收方消息确认
    Rabbitmq的死信队列和延时队列
    Typora常用快捷键
    Docker安装Rabbitmq及其延时队列插件
    使用docker-compose单机发布多个服务
    Typora图片自动上传和文件备份
    在centos里安装Nginx
    MySQL 事务
    php5 中魔术方法函数有哪几个
  • 原文地址:https://www.cnblogs.com/starryxsky/p/7404375.html
Copyright © 2011-2022 走看看