首页 > 代码库 > 数据视化Echarts+百度地图API实现市县区级下钻

数据视化Echarts+百度地图API实现市县区级下钻

开始

  这两天公司有个页面需要做数据可视化的展示,数据视化采用的是Echarts+百度地图API做展示,需要用到县级区级下钻的一个联动效果发现网上关于Echarts做到县区级下钻的资料很少,有的话也不是很详细,对于刚接触Echarts的让人来说可能有些搞不明白,在这里我把Echarts下钻开发过程中总结的知识分享给大家,也能使自己加深印象,当然啦,对于一些在软件行业折腾了几年的老油条来说,这些都是一些非常基础的东西。但是还是希望能帮助到那些刚接触Echarts遇到类似问题需要帮助的人。如果哪里写的不对,或者有更好的方法,也欢迎大家吐槽留言,互相学习。

进入正题

  我这里用的是Echarts2.2.7,这是官网http://echarts.baidu.com/echarts2/;首先下载Echarts包引入Echarts.js

  然后再准备两个个DIV,配置路径,使用MAP,官网有说明http://echarts.baidu.com/echarts2/doc/start.html;

  这里就不细说了,讲下官网没有的。中国地图下钻到省级联动效果。

技术分享

第一步

加载中国地图都准备好了后再函数里定义一个option来设置中国地图的样式如下:

 1 function (ec) {
 2       // 基于准备好的dom,初始化echarts图表
 3       var myChart = ec.init(document.getElementById(main));
 4       var SubordinateMap = ec.init(document.getElementById(subordinate));
 5 
 6       option = {
 7           tooltip : {
 8               trigger: item, //提示框的触发类型。
 9               formatter: {b} //内容格式器可以支持异步回调函数。返回一个你想要提示的字符串就可以了
10           },
11           dataRange: { //值域选择
12               min: 0,
13               max: 100,
14               calculable: false,
15               show: false,
16               color: [#ff3333, orange, yellow, lime, aqua],
17               textStyle: {  //文字颜色
18                   color: #fff
19               }
20           },
21           series: [   //图表生成的数据内容数组
22               {
23                   name: 中国,
24                   type: map,   //图表类型为地图
25                   mapType: china,   //地图类型中国地图,
26                   selectedMode: single, //选中模式,可以设置多选模式和单选,不能选择则删除删除属性
27                   hoverable: false,   //悬浮是否高亮
28                   itemStyle:{
29                       normal: {        //地图样式
30                           borderColor: #71D1FF, //地图边界颜色
31                           color: #070C67  //地图颜色
32                       },
33                       emphasis: {   //地图选中时样式
34                           label: {
35                               show: true,
36                               textStyle: {
37                                   color: #fff //选中时区域名字颜色
38                               },
39                           },
40                           color: #71D1FF //选中时颜色
41                       }
42                   },
43                   data:[
44                       {name:广东,selected:true}   //广东默认别选中
45                   ],
46                   geoCoord: {   //每个城市对应的经纬度
47                       上海: [121.4648,31.2891] }...//类似数据省略

这个是全国地图,最后在使用setOption()方法加载地图:

1 myChart.setOption(option, true);

第二步通过on事件实现省级下钻

添加一个省级对象(类似第一步的option)设置样式数据等,Echarts2.2.7这里不需要下载省级地图,直接通过Data设置数据读取就可以了:

 1                 //省级
 2                 provinceO = {
 3                     title: { //标题
 4                         text: 全国34个省市自治区,
 5                         subtext: 省级
 6                     },
 7                     tooltip: {
 8                         trigger: item  //提示框的触发类型。
 9                     },
10                     legend: {   //图列
11                         orient: vertical, //图列显示的方式
12                         x: right,
13                         data: [随机数据]
14                     },
15                     series: [
16                         {
17                             name: 随机数据,
18                             type: map,
19                             mapType: 湖南,  //要显示的省份,下钻就是通过on事件来更改属性
20                             selectedMode: single, //选中模式,可以设置多选模式和单选,不能选择则删除删除属性
21                             itemStyle: {
22                                 normal: {
23                                     label: { show: true }, //是否显示城市名字
24                                     borderColor: #71D1FF,  //地图边界颜色
25                                     color: #070C67
26                                 },
27                                 emphasis: { label: { show: true } } //选中后样式
28 
29                             },
30                             data: [
31                                 { name: 重庆市, value: Math.round(Math.random() * 1000) }}....//类似数据省略


通过on来更改series下的mapType属性,然后通过setOption方法来给第二个DIV加载地图(当然也可以直接给第一个DIV重新加载),这样就实现下钻到省的联动效果了;

1               var ecConfig = require(echarts/config);
2                    myChart.on(ecConfig.EVENT.MAP_SELECTED, function (param) {
3                      var name = param.target;//获得选中的城市
4                      provinceO.series[0].mapType = name;//设置series的mapType属性为当前选中的城市
5                      SubordinateMap.setOption(provinceO, true);//给SubordinateMapDIV重现加载地图
6 
7                  });

第三步通实现市级下钻效果
通过一个数组绑定每个城市对应的文件名:

1 var cityMap = {
2                       "北京市": "110100", //每个城市对应的json文件名
3                       "天津市": "120100",
4                       "上海市": "310100",
5                       "重庆市": "500100"}//重复数据省略

技术分享

通过循环引入地图数据:

 1           var mapType = [];
 2                  var mapGeoData = http://www.mamicode.com/require(echarts/util/mapData/params);
 3                  //console.log(mapGeoData)
 4                  for (var city in cityMap) { //通过循环来引入数据
 5                      mapType.push(city);
 6                      // 自定义扩展图表类型
 7                      mapGeoData.params[city] = {
 8                          getGeoJson: (function (c) {
 9                              var geoJsonName = cityMap[c]; //通过cityMap数组得到JSON文件名
10                              return function (callback) {
11                                  $.getJSON(geoJson/ + geoJsonName + .json, callback);  //得到地图JSON文件数据,首先你本地路径下得有这个JSON文件
12                              }
13                          })(city)
14                      }
15                  }

添加一个市级对象设置样式数据,跟上面不同的是这里需要地图数据,因为Echarts没有带市级地图,需要自己去网上找地图数据:

 1           //市级
 2                 cityO = {
 3                     title: { //标题
 4                         text: 全国344个主要城市
 5                     },
 6                     tooltip: {
 7                         trigger: item,   //提示框的触发类型。
 8                         formatter: {b}  //内容格式器可以支持异步回调函数。返回一个你想要提示的字符串就可以了
 9                     },
10                     series: [  //图表生成的数据内容数组
11                         {
12                             name: 全国344个主要城市(县)地图,
13                             type: map,  //类型为地图,
14                             mapType: 北京市, //要显示的市,下钻就是通过on事件来更改属性
15                             selectedMode: single,//选中模式,可以设置多选模式和单选,不能选择则删除删除属性
16                             itemStyle: {
17                                 normal: {
18                                     label: { show: true }, //是否显示城市名字
19                                     borderColor: #71D1FF,  //地图边界颜色
20                                     color:#070C67
21                                 },
22                                 emphasis: { label: { show: true } } //选中后的样式
23                             },
24                             data: []
25                         }
26                     ]
27                 };

然后通过on来更改series下的mapType属性,在通过setOption方法来给第二个DIV重新加载地图就实现下钻到市级了。

1           SubordinateMap.on(ecConfig.EVENT.MAP_SELECTED, function (param) {
2                 var name = param.target;//获得选中的城市
3                 cityO.series[0].mapType = name;//设置series的mapType属性为当前选中的城市
4                 SubordinateMap.setOption(cityO, true);//给SubordinateMapDIV重现加载地图
5             });

如果你还需要下钻到更小范围比如区级,那就只能跟百度地图API结合了,PS:当然也可以用Ehcarts自定义地图实现但是每个县的区级地图JSON数据网上也没有,
并且Echarts生成也只能生成到县。

如何下钻到县区级:
实现效果:点击某个市的县后,在到百度地图上框出边界线,设置缩放级别调整视角。(如果想要更好的效果也可以把边除了框出来的城市外其他的城市不显示)

技术分享

引入百度地图API,在页面上添加一个DIV来加载百度地图,然后初始化百度地图:

 1   function (echarts, BMapExtension) {
 2                var BMapExt = new BMapExtension($(#main)[0], BMap, echarts, {
 3                    enableMapClick: false
 4                });
 5                map = BMapExt.getMap();
 6                var container = BMapExt.getEchartsContainer();
 7 
 8                var startPoint = { //经纬度
 9                    x: 104.114129,
10                    y: 37.550339
11                };
12                var point = new BMap.Point(startPoint.x, startPoint.y);
13                map.centerAndZoom(point, 5); //根据经纬度调整视角
14                map.enableScrollWheelZoom(true); //开启滚轮缩放
15                // 地图自定义样式
16                map.setMapStyle({
17                    styleJson: [
18                          {
19                              "featureType": "background",
20                              "elementType": "all",
21                              "stylers": {
22                                  "color": "#444444"
23                              }
24                          }
25                       ]
26                  })
27             }

通过Echarts加载的市级地图的on事件触发百度地图设置函数:

1        var myChart = echarts.init(document.getElementById(main));
2        var ecConfig = require(echarts/config);
3        myChart.on(ecConfig.EVENT.MAP_SELECTED, function (param) {
4                getBoundary(param.target);
5        });   

由于没个城市的大小,形状都不一样,在DIV里面显示的效果就不一样,有大的城市没有显示全,有些小的又放的太小了,并且视角也不是最佳视角,所以我这了定义的一个数组用来存放每个下钻城市
的视角位置,已经缩放级别,这样就跟根据自己设置的DIV大小来调整地图的大小了。

 1 //定义一个数组来存放每个城市的视角位置,和放大级别
 2        var PositionData = http://www.mamicode.com/[{ name: 济宁市, long: 116.782471, lat: 35.226815, zoom: 10 }, { name: 新乡市, long: 114.172514, lat: 35.216547, zoom: 10 }, { name: 甘孜藏族自治州, long: 99.935306, lat: 31.093953, zoom: 8 }]
 3        function getBoundary(city) {
 4            var ply;
 5            var bdary = new BMap.Boundary();
 6            bdary.get(city, function (rs) {       //获取行政区域
 7                //map.clearOverlays();        //清除地图覆盖物
 8                var count = rs.boundaries.length; //行政区域的点有多少个
 9                for (var i = 0; i < count; i++) {
10                    ply = new BMap.Polygon(rs.boundaries[i], { strokeWeight: 3, strokeColor: "#ffff00", fillColor: "none" }); //建立多边形覆盖物
11                    map.addOverlay(ply);  //添加覆盖物 ,这里要用到初始化时的map ,
12                    //map.setViewport(ply.getPath());    //调整视野
13                }
14                for (var i = 0; i < PositionData.length; i++)
15                {
16                    if (PositionData[i].name == city) {
17                        //通过经纬度指定视野的中心位置,以及放大级别
18                        map.centerAndZoom(new BMap.Point(PositionData[i].long, PositionData[i].lat), PositionData[i].zoom);
19                        break;
20                    }
21                    else {
22                        if (i == PositionData.length - 1) {
23                            //如果数组里没有该城市视角数据和放大级别数据时就设置默认的视角位置和放大级别
24                            map.centerAndZoom(city, 10);
25                        }
26                    }
27                }
28            });
29        }   

最后
如果想实现下钻到区级,原理一样,这里就不讲了,需要源码或地图数据的,可以联系我,如果有什么更好的方法,欢迎吐槽留言。

当然你也可以请我喝杯咖啡(学的,不发个二维码都没啥期待,哈哈哈)

技术分享

数据视化Echarts+百度地图API实现市县区级下钻