时空碰撞之当Leaflet遇到Echarts

前言

        在之前的博客中,有介绍如何进行Leaflet展示的,也有介绍Echarts如何进行高效图表展示的。针对一些时空类的场景,比如需要跟随GIS地图一起进行图表展示,如何在地图上集成图表插件。本文将以常用的Leaflet为例,重点讲解在Leaflet中如何集成Echarts进行模拟迁徙的地图展示,最后通过分析前端调用示例以代码的形式给出实例,希望对需要将两者进行集成的朋友有所帮助。

一、相关基础知识

1、leaflet-echarts插件

        基于leaflet 扩展echarts,使ECharts的地图可以加到leaflet上,根据百度地图echarts的扩展改写,在事件联动这个地方以及echarts的容器与地图容器在拖动和缩放中的适应上耗费了很长时间,为了兼容echarts的map其他类型的数据又下了不少功夫。leaflet-echarts3 github地址。有兴趣朋友可以独立下载。

时空碰撞之当Leaflet遇到Echarts_第1张图片

2、依赖插件说明

        在Leaflet-charts中,其依赖的组件包还是比较少的。主要的包如下:

序号 组件 备注
1 leaflet-echarts.js 集成插件
2 echarts.source.js echarts组件
3 jquery.js jquery组件

时空碰撞之当Leaflet遇到Echarts_第2张图片

        需要注意的是,当前提供的echarts版本跟Echarts官网提供的版本有一定差异,如果需要使用最新的一些图表及API,谨慎升级或者需要自己手动调试代码,改成兼容新版本的才可以,否则会报错。示例提供的echarts的版本是2.2.6。

时空碰撞之当Leaflet遇到Echarts_第3张图片

二、页面集成

1、新建html页面

        在个人电脑任意盘符中新建index3.html,关键代码如下:




    
    leaflet-echarts集成特效
    
    


2、leaflet地图初始化

        在上面的Script脚本中进行Leaflet地图的初始化操作,示例代码如下所示:

var map = L.map('map');
    var baseLayers = {
        "高德地图": L.tileLayer('http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
            subdomains: "1234"
        }),
        '高德影像': L.layerGroup([L.tileLayer('http://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {
            subdomains: "1234"
        }), L.tileLayer('http://t{s}.tianditu.cn/DataServer?T=cta_w&X={x}&Y={y}&L={z}', {
            subdomains: "1234"
        })]),
        "立体地图": L.tileLayer('https://a.tiles.mapbox.com/v3/examples.c7d2024a/{z}/{x}/{y}.png', {
            attribution: 'Map © Pacific Rim Coordination Center (PRCC).  Certain data © OpenStreetMap contributors, CC-BY-SA',
            key: 'BC9A493B41014CAABB98F0471D759707',
            styleId: 22677
        }),
        "Foursquare": L.tileLayer('https://a.tiles.mapbox.com/v3/foursquare.map-0y1jh28j/{z}/{x}/{y}.png', {
            attribution: 'Map © Pacific Rim Coordination Center (PRCC).  Certain data © OpenStreetMap contributors, CC-BY-SA',
            key: 'BC9A493B41014CAABB98F0471D759707',
            styleId: 22677
        }),
        'GeoQ灰色底图': L.tileLayer('http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}').addTo(map)
    };
    L.tileLayer('https://a.tiles.mapbox.com/v3/foursquare.map-0y1jh28j/{z}/{x}/{y}.png', {
        attribution: 'Map © Pacific Rim Coordination Center (PRCC).  Certain data © OpenStreetMap contributors, CC-BY-SA',
        key: 'BC9A493B41014CAABB98F0471D759707',
        styleId: 22677
    });
    var layercontrol = L.control.layers(baseLayers, {
        position: "topleft"
    }).addTo(map);
    map.setView(L.latLng(37.550339, 104.114129), 4);

    var overlay = new L.echartsLayer(map, echarts);

        这里地图引用了GeoQ的灰色底图、高德的影像和电子地图等在线地图,如需离线访问的需要下载相应的图源或者接入自己的离线地图资源。

3、Echarts与地图集成

        经过第二个步骤的初始化,已经完成Leaflet地图的定义,在这里进行Echarts地的集成。核心代码如下所示:

var chartsContainer=overlay.getEchartsContainer();
    var myChart=overlay.initECharts(chartsContainer);
    window.onresize = myChart.onresize;
    var option = {
    color: ['gold','aqua','lime'],
    title : {
        text: 'Leaflet和Echarts集成模拟迁徙',
        subtext:'数据纯属虚构',
        x:'center',
        textStyle : {
            color: '#fff'
        }
    },
    tooltip : {
        trigger: 'item',
        formatter: '{b}'
    },
    legend: {
        orient: 'vertical',
        x:'left',
        data:['北京 Top10', '上海 Top10', '广州 Top10'],
        selectedMode: 'single',
        selected:{
            '上海 Top10' : false,
            '广州 Top10' : false
        },
        textStyle : {
            color: '#fff'
        }
    },
    toolbox: {
        show : true,
        orient : 'vertical',
        x: 'right',
        y: 'center',
        feature : {
            mark : {show: true},
            dataView : {show: true, readOnly: false},
            restore : {show: true},
            saveAsImage : {show: true}
        }
    },
    dataRange: {
        min : 0,
        max : 100,
        calculable : true,
        color: ['#ff3333', 'orange', 'yellow','lime','aqua'],
        textStyle:{
            color:'#fff'
        }
    },
    series : [
        {
            name: '全国',
            type: 'map',
            roam: true,
            hoverable: false,
            mapType: 'none',
            itemStyle:{
                normal:{
                    borderColor:'rgba(100,149,237,1)',
                    borderWidth:0.5,
                    areaStyle:{
                        color: '#1b1b1b'
                    }
                }
            },
            data:[],
            markLine : {
                smooth:true,
                symbol: ['none', 'circle'],  
                symbolSize : 1,
                itemStyle : {
                    normal: {
                        color:'#fff',
                        borderWidth:1,
                        borderColor:'rgba(30,144,255,0.5)'
                    }
                },
                data : [
                    [{name:'北京'},{name:'包头'}],
                    [{name:'北京'},{name:'北海'}],
                    [{name:'北京'},{name:'广州'}],
                    [{name:'北京'},{name:'郑州'}],
                    [{name:'北京'},{name:'长春'}],
                    [{name:'北京'},{name:'长治'}],
                    [{name:'北京'},{name:'重庆'}],
                    [{name:'北京'},{name:'长沙'}],
                    [{name:'广州'},{name:'烟台'}],
                    [{name:'广州'},{name:'盐城'}]
                ],
            },
            geoCoord: {
                '上海': [121.4648,31.2891],
                '东莞': [113.8953,22.901],
                '东营': [118.7073,37.5513],
                '中山': [113.4229,22.478],
                '临汾': [111.4783,36.1615],
                '临沂': [118.3118,35.2936],
                '丹东': [124.541,40.4242],
                '丽水': [119.5642,28.1854],
                '乌鲁木齐': [87.9236,43.5883],
                '佛山': [112.8955,23.1097],
                '保定': [115.0488,39.0948],
                '兰州': [103.5901,36.3043],
                '包头': [110.3467,41.4899],
                '泉州': [118.3228,25.1147],
                '泰安': [117.0264,36.0516],
                '泰州': [120.0586,32.5525],
                '济南': [117.1582,36.8701],
                '济宁': [116.8286,35.3375],
                '海口': [110.3893,19.8516],
                '淄博': [118.0371,36.6064],
                '淮安': [118.927,33.4039],
                '深圳': [114.5435,22.5439],
                '清远': [112.9175,24.3292],
                '温州': [120.498,27.8119],
                '渭南': [109.7864,35.0299],
                '湖州': [119.8608,30.7782],
                '湘潭': [112.5439,27.7075],
                '铜川': [109.0393,35.1947],
                '银川': [106.3586,38.1775],
                '镇江': [119.4763,31.9702],
                '长春': [125.8154,44.2584],
                '长沙': [113.0823,28.2568],
                '长治': [112.8625,36.4746],
                '阳泉': [113.4778,38.0951],
                '青岛': [120.4651,36.3373],
                '韶关': [113.7964,24.7028]
            }
        },
        {
            name: '北京 Top10',
            type: 'map',
            mapType: 'none',
            data:[],
            markLine : {
                smooth:true,
                effect : {
                    show: true,
                    scaleSize: 1,
                    period: 30,
                    color: '#fff',
                    shadowBlur: 10
                },
                itemStyle : {
                    normal: {
                        borderWidth:1,
                        lineStyle: {
                            type: 'solid',
                            shadowBlur: 10
                        }
                    }
                },
                data : [
                    [{name:'北京'}, {name:'上海',value:95}],
                    [{name:'北京'}, {name:'广州',value:90}],
                    [{name:'北京'}, {name:'大连',value:80}],
                    [{name:'北京'}, {name:'南宁',value:70}],
                    [{name:'北京'}, {name:'南昌',value:60}],
                    [{name:'北京'}, {name:'拉萨',value:50}],
                    [{name:'北京'}, {name:'长春',value:40}],
                    [{name:'北京'}, {name:'包头',value:30}],
                    [{name:'北京'}, {name:'重庆',value:20}],
                    [{name:'北京'}, {name:'常州',value:10}]
                ]
            },
            markPoint : {
                symbol:'emptyCircle',
                symbolSize : function (v){
                    return 10 + v/10
                },
                effect : {
                    show: true,
                    shadowBlur : 0
                },
                itemStyle:{
                    normal:{
                        label:{show:false}
                    },
                    emphasis: {
                        label:{position:'top'}
                    }
                },
                data : [
                    {name:'上海',value:95},
                    {name:'广州',value:90},
                    {name:'大连',value:80},
                    {name:'南宁',value:70},
                    {name:'南昌',value:60},
                    {name:'拉萨',value:50},
                    {name:'长春',value:40},
                    {name:'包头',value:30},
                    {name:'重庆',value:20},
                    {name:'常州',value:10}
                ]
            }
        },
        {
            name: '上海 Top10',
            type: 'map',
            mapType: 'none',
            data:[],
            markLine : {
                smooth:true,
                effect : {
                    show: true,
                    scaleSize: 1,
                    period: 30,
                    color: '#fff',
                    shadowBlur: 10
                },
                itemStyle : {
                    normal: {
                        borderWidth:1,
                        lineStyle: {
                            type: 'solid',
                            shadowBlur: 10
                        }
                    }
                },
                data : [
                    [{name:'上海'},{name:'包头',value:95}],
                    [{name:'上海'},{name:'昆明',value:90}],
                    [{name:'上海'},{name:'广州',value:80}],
                    [{name:'上海'},{name:'郑州',value:70}],
                    [{name:'上海'},{name:'长春',value:60}],
                    [{name:'上海'},{name:'重庆',value:50}],
                    [{name:'上海'},{name:'长沙',value:40}],
                    [{name:'上海'},{name:'北京',value:30}],
                    [{name:'上海'},{name:'丹东',value:20}],
                    [{name:'上海'},{name:'大连',value:10}]
                ]
            },
            markPoint : {
                symbol:'emptyCircle',
                symbolSize : function (v){
                    return 10 + v/10
                },
                effect : {
                    show: true,
                    shadowBlur : 0
                },
                itemStyle:{
                    normal:{
                        label:{show:false}
                    },
                    emphasis: {
                        label:{position:'top'}
                    }
                },
                data : [
                    {name:'包头',value:95},
                    {name:'昆明',value:90},
                    {name:'广州',value:80},
                    {name:'郑州',value:70},
                    {name:'长春',value:60},
                    {name:'重庆',value:50},
                    {name:'长沙',value:40},
                    {name:'北京',value:30},
                    {name:'丹东',value:20},
                    {name:'大连',value:10}
                ]
            }
        },
        {
            name: '广州 Top10',
            type: 'map',
            mapType: 'none',
            data:[],
            markLine : {
                smooth:true,
                effect : {
                    show: true,
                    scaleSize: 1,
                    period: 30,
                    color: '#fff',
                    shadowBlur: 10
                },
                itemStyle : {
                    normal: {
                        borderWidth:1,
                        lineStyle: {
                            type: 'solid',
                            shadowBlur: 10
                        }
                    }
                },
                data : [
                    [{name:'广州'},{name:'福州',value:95}],
                    [{name:'广州'},{name:'太原',value:90}],
                    [{name:'广州'},{name:'长春',value:80}],
                    [{name:'广州'},{name:'重庆',value:70}],
                    [{name:'广州'},{name:'西安',value:60}],
                    [{name:'广州'},{name:'成都',value:50}],
                    [{name:'广州'},{name:'常州',value:40}],
                    [{name:'广州'},{name:'北京',value:30}],
                    [{name:'广州'},{name:'北海',value:20}],
                    [{name:'广州'},{name:'海口',value:10}]
                ]
            },
            markPoint : {
                symbol:'emptyCircle',
                symbolSize : function (v){
                    return 10 + v/10
                },
                effect : {
                    show: true,
                    shadowBlur : 0
                },
                itemStyle:{
                    normal:{
                        label:{show:false}
                    },
                    emphasis: {
                        label:{position:'top'}
                    }
                },
                data : [
                    {name:'福州',value:95},
                    {name:'太原',value:90},
                    {name:'长春',value:80},
                    {name:'重庆',value:70},
                    {name:'西安',value:60},
                    {name:'成都',value:50},
                    {name:'常州',value:40},
                    {name:'北京',value:30},
                    {name:'北海',value:20},
                    {name:'海口',value:10}
                ]
            }
        }
    ]
};                   
overlay.setOption(option);

三、功能展示

1、地图首页

        将完成的index3.html页面直接在浏览器中打开,即可看到将地图和图表进行完美融合的界面,支持地图的缩放,迁徙功能支持与地图无缝衔接。

 2、底图切换

        在右侧的在线地图中,可以支持不同的地图进行切换,比如可以实现GeoQ的灰色底图切换到高德的高线地图展示,如果您有离线的地图图源,也是可以接入进行展示的。

时空碰撞之当Leaflet遇到Echarts_第4张图片

 四、渲染分析

下面通过在浏览器中进行Debug断点调试,跟踪相关代码的执行流程。

        页面元素初始化,执行以下代码:

var overlay = new L.echartsLayer(map, echarts);
var chartsContainer=overlay.getEchartsContainer();

时空碰撞之当Leaflet遇到Echarts_第5张图片

charts初始化,与map进行元素绑定,将map的元素大小赋值给图表,保持两者一致。

initialize: function(map, ec) {
      this._map = map;
      var size = map.getSize();
      var div = this._echartsContainer = document.createElement('div');
      div.style.position = 'absolute';
      div.style.height = size.y + 'px';
      div.style.width = size.x + 'px';
      div.style.top = 0;
      div.style.left = 0;
      map.getPanes().overlayPane.appendChild(div);
      this._init(map, ec);
    },

时空碰撞之当Leaflet遇到Echarts_第6张图片

 事件绑定

时空碰撞之当Leaflet遇到Echarts_第7张图片

 setOption设置报表展示参数

时空碰撞之当Leaflet遇到Echarts_第8张图片

总结 

        以上就是本文的主要内容,本文将以常用的Leaflet为例,重点讲解在Leaflet中如何集成Echarts进行模拟迁徙的地图展示,最后通过分析前端调用示例以代码的形式给出实例,希望对需要将两者进行集成的朋友有所帮助。行文仓促,如有不当之处,欢迎朋友在评论区留言批评指正。

你可能感兴趣的:(leaflet,Leaflet+echarts,空间图表可视化)