在Leaflet地图上集成Echarts
需求背景:
现在我要在地图上加上Echarts的散点图还有线集,看起来就很牛B的那种。上效果图:
需求分析:
我先看了看Echarts官网上有提供加载地图的例子,主要包括三种方式:
1.加载js格式的地图文件;
2.加载json格式的地图文件;
3.通过配置项bmap,就是百度地图; 参考地址:https://blog.csdn.net/wml00000/article/details/84566180
上面的我是用不了的,我用的是Leaflet地图框架,找了找已经有人实现了扩展(Echarts-Leaflet扩展地址在这:https://github.com/gnijuohz/echarts-leaflet),他是模仿着Echarts里面的bmap扩展了一个配置项leaflet,给我的感觉是在Echarts上集成了Leaflet,当然用是没有问题的,就是觉得有点别扭,我想要的是Leaflet上集成Echarts,是以Leaflet为主,所以就放弃了这种方式。个人来讲,如果不是项目原因,还是比较推荐他的扩展的。
另外,还找到一个插件leaflet-echarts3(https://github.com/wandergis/leaflet-echarts3),这个是基于Leaflet进行扩展的,但是作者没有公布源代码,只有一个压缩后的js文件,里面同时包含了leaflet源码、Echarts源码以及扩展代码,这样我想进行版本升级都不行。所以我就悄悄地把他里面的核心代码抽了出来。
具体操作:
1.下载最新Echarts源代码,http://echarts.baidu.com/download.html 下最大的那个2.86MB;
2.通过 _theme进行定位,定位到function Echarts(){ }里面的 this._theme = theme$$1; 4.2.0版本大概在第26582行,添加一行代码: this._geo = Geo;
3.对Leaflet Layer 类进行扩展,新建js文件 leaflet-echarts.js, 加入下面代码:
L.OverlayEcharts = (L.version < "1.0" ? L.Class : L.Layer).extend({includes: L.version < "1.0" ? L.Mixin.Events : [],_echartsContainer: null,_map: null,_echart: null,_echartsOption: null,initialize: function(echartsOption) {this._echartsOption = echartsOption;},onAdd: function(map) {this._map = map;this._initEchartsContainer();map.on("moveend", this._redraw, this);//当地图中心改变后触发this._redraw();},onRemove: function(map) {this._echartsContainer && map.getPanes().overlayPane.removeChild(this._echartsContainer);this._echart.dispose();map.off("moveend", this._redraw, this);},// addTo: function(map) {// console.log(this);// return map.addLayer(this),// this// },_initEchartsContainer: function() {var size = this._map.getSize(),echartsContainer = document.createElement("div");console.log("=====>mapsize"+size);echartsContainer.style.position = "absolute";echartsContainer.style.height = size.y + "px";echartsContainer.style.width = size.x + "px";echartsContainer.style.zIndex = 999;this._echartsContainer = echartsContainer;this._map.getPanes().overlayPane.appendChild(this._echartsContainer);//在map容器的overlayPane上叠加Echarts容器},_resetCanvasPosition: function() {var bound = this._map.getBounds(),origin = this._map.latLngToLayerPoint(bound.getNorthWest());console.log(origin);//最开始为[0,0],缩放不会改变,平移会改变\L.DomUtil.setPosition(this._echartsContainer, origin);//设置Echarts容器的位置,以便与当前地图匹配},_redraw: function() {return this._resetCanvasPosition(),this._echartsContainer.innerHTML = "",this.initECharts(),this.setOption(this._echartsOption),this},clear: function() {this._echartsContainer.innerHTML = "",this.echartsOption = {}},redraw: function() {console.log("=======>redraw");this._redraw();},initECharts: function(){if(this._echart === null || this._echart === undefined){this._initECharts();}else {this._echart.dispose();this._initECharts();}},_initECharts: function() {if (this._echart = echarts.init(this._echartsContainer),"3.0" <= echarts.version) {var me = this;console.log(echarts.version);console.log(me._echart);me._echart._geo.prototype.dataToPoint = function(lnglat) {//重写Echarts内部方法,Ecahrts内部有一套将经纬度转为像素坐标的方法,这里要换成与Leaflet相匹配的var latlng = new L.latLng(lnglat[1],lnglat[0]), pixel = me._map.latLngToContainerPoint(latlng);return [pixel.x, pixel.y]; //给定地理坐标,返回相对于地图container容器的相应像素坐标。}}this._unbindEvent();//屏蔽Echarts相关事件},setOption: function(echartsOption) {if (echartsOption.series) {//var series = echartsOption.series || {};this._echart.setOption(echartsOption);}},_unbindEvent: function() {echarts.version < "3.0" ? (this._echart.getZrender().un("dragstart", function() {}),this._echart.getZrender().un("dragend", function() {}),this._echart.getZrender().un("mouseup", function() {}),this._echart.getZrender().un("mousedown", function() {}),this._echart.getZrender().un("mousewheel", function() {})) : (this._echart.getZr().off("dragstart", function() {}),this._echart.getZr().off("dragend", function() {}),this._echart.getZr().off("mouseup", function() {}),this._echart.getZr().off("mousedown", function() {}),this._echart.getZr().off("mousewheel", function() {}))}
}),L.overlayEcharts = function(options) {return new L.OverlayEcharts(options)
}
4. 新建html页面,代码太多,就不全放了,源文件下载地址:https://download.csdn.net/download/wml00000/10837134
<script src="lib/leaflet/leaflet.js"></script>
<script src="lib/echarts.js"></script>
<script src="lib/leaflet/leaflet-echarts.js"></script><div id="map"></div>
<script>var map = L.map('map'); L.tileLayer('http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}').addTo(map);map.setView(L.latLng(37.550339, 104.114129), 4); //设置缩放级别及中心点//Echarts相关options配置var option = {};//将Echarts加到地图上,可以简单理解为在地图上添加了Echarts图层L.overlayEcharts(option).addTo(map);
详细解读:
如果只是照着流程来一遍,我认为是没有灵魂的。说一说到底是如何把Echarts集成进去的。要想深入了解,需要知道Leaflet底层的一些东西,以下内容均为个人理解,请选择性阅读。
这是最开始加载Leaflet地图的一个DOM结构,我们只是创建了一个id为map的DIV,但是Leaflet内部在我们的DIV里面又创建了众多div,分为两部分:map-pane和control-container。主要看map-pane,在这个map-pane里面有tile-pane、overlay-pane等,通过这大概能看出Leaflet是通过DIV的设置实现图层、marker、覆盖物等之间的叠加,那么他又是如何根据地理坐标确定在屏幕上的位置关系的?
可以先参考一下Leaflet的介绍:https://leafletjs.com/examples/extending/extending-2-layers.html
核心内容:
- The
L.Map
container has “map panes”, which are<div>
s. L.Layer
s are HTML elements inside a map pane- The map transforms all
LatLng
s to coordinates in the map’s CRS, and from that into absolute “pixel coordinates” (the origin of the CRS is the same as the origin of the pixel coordinates) - When the
L.Map
is ready (has a centerLatLng
and a zoom level), the absolute pixel coordinates of the top-left corner become the “pixel origin” - Each
L.Layer
is offset from its map pane according to the pixel origin and the absolute pixel coordinates of the layer’sLatLng
s - The pixel origin is reset after each
zoomend
orviewreset
event on theL.Map
, and everyL.Layer
has to recalculate its position (if needed) - The pixel origin is not reset when panning the map around; instead, the whole panes are repositioned.
翻译一下:
- 地图容器里面有个map-pane,里面有很多的div
- 图层其实就是map-pane里面的html 元素
- 地图把经纬度转换成投影坐标系统下的坐标,再转成绝对像素坐标(投影坐标系统原点与像素坐标系原点重合)
- 当地图就绪时(中心点以及缩放级别都已经确定了),左上角的绝对像素坐标就是所谓的像素原点(注意这里加了引号,他的像素坐标不一定是0,0)
- 每个图层会根据像素原点以及图层上的经纬度坐标转换过来的绝对像素坐标在map-pane上进行偏移
- 每次缩放或视图重置坐标原点也会重置(可以简单理解为地图的重新加载,就是第4条),各个图层也得重新计算位置(因为一缩放,虽然地理坐标不变,实际上不同缩放级别地理坐标对应的像素坐标是不一样的)
- 当地图平移时像素原点不会重置(实际上当地图平移时,map-pane这个div样式中的transform变了,也就是说map-pane的左上角这个像素原点也走了,但是他的像素坐标不变,注意坐标不一定是0,0),这个map-pane上面的其他div也就跟着动了
对照着这个例子https://leafletjs.com/examples/extending/pixelorigin.html 应该能看个差不多。
再插两句:上面说到的绝对像素坐标是针对地图切片谈的,并不是针对设备坐标。每张地图切片的大小是256*256,当缩放级别为0时,就是用一张图片表示全球,绝对像素坐标原点(0,0)值位于图片左上角,换算成经纬度大约是(-180,85).另外一点,网络地图大都采用网络墨卡托投影,他并不是指投影坐标系,只是一种映射关系,是把球面地理坐标转为平面坐标的一个过程。附个地址:https://blog.csdn.net/wml00000/article/details/85014021
Echarts的散点图其实也是在一个Div上画的,只要把这个div给拿到map-pane里面的overlay-pane里面不就完事了。关于点的位置,因为Echarts内部自己有个把地理坐标转为像素坐标的方法,咱不能用他的,想办法给他重写了,用Leaflet 的latLngToContainerPoint( )代替。
关于Echarts的DIV容器怎么搞,有几点:
1.大小需要与map container匹配
2.每次平移,缩放,要重新加载Echarts(可以根据leaflet的moveend监听)
3.重写Echarts内部方法 dataToPoint
写的有点乱了
今天突然发现超图 supermap iclient 9d for Leaflet有Echarts的例子,可以看看:http://iclient.supermap.io/examples/leaflet/examples.html#viz-ECharts
在Leaflet地图上集成Echarts相关推荐
- 在Arcgis地图上绘制Echarts热力图(Heatmap)
在Arcgis地图上绘制Echarts热力图(Heatmap) 2018-08-30 10:18 [原创]本文地址:https://www.cnblogs.com/qiaoge0923/p/95623 ...
- Leaflet工作笔记-GIS地图上构造echarts的3D图
这里要实现的是这样的效果: 在地图上有一个柱子,3D的,直接显示,而不是使用什么label或者点击,在界面上显示. 原理如下: 1.使用leaflet的marker标签,插入一个html: 2.在这个 ...
- leaflet地图原理_使用Leaflet创建地图拓扑图
之前我们采用过 Openlayers+Qunee的方案,实现地图拓扑图,鉴于Openlayers是一个古老项目,略显臃肿,对于现代的前端地图应用,显得笨重,在客户的介绍下,我们找到了leaflet - ...
- Leaflet笔记-Leaflet与echarts结合使用(在地图上绘图表)
目录 基本概念 代码与实例 基本概念 在本地地图上绘制图表,图表经过响应弹出来. 想想真是令人兴奋的事情,到时候用Qt的Widget和QGraphicsView结合QWebEngine搞一层.来一个科 ...
- Echarts获取国家json文件(非洲国家地图,动态选中地图上国家)
前言 需求:使用echarts构建非洲地图并通过下拉框动态选中地图中得国家. 思路:网上没有现成的非洲国家地图json坐标数据,只有世界国家地图json坐标数据,所以首先找到非洲所有国家中英文名称,然 ...
- Leaflet中使用Leaflet.contextmenu插件实现地图上添加鼠标右键菜单
场景 Leaflet快速入门与加载OSM显示地图: Leaflet快速入门与加载OSM显示地图_BADAO_LIUMANG_QIZHI的博客-CSDN博客 在上面的基础上,怎样使用Leaflet.co ...
- java echarts 散点图,echarts在地图上绘制散点图(任意点)
项目需求:在省份地图上绘制散点图,散点位置不一定是哪个城市或哪个区县,即任意点 通过查询官网文档,找到一个与需求类似的Demo:https://www.echartsjs.com/gallery/ed ...
- echarts 地图上如何打点
这里介绍如何在地图上进行打点.首先我们想到的是 scatter (散点图).这里 echarts 设置地图外边框.地图背景渐变色和地图阴影,增加立体感以及在地图上打点 有详细介绍,请参考.这里我介绍另 ...
- echarts 地图和柱状图结合(在地图上显示柱状图)
如图,需求要做一个在地图上显示柱状图的echarts图,但是百度了半天,发现很少有人发这种例子.这个代码也是借鉴的别人的文章,但需求肯定不完全一致,那我会根据我的需求把代码和注意事项发出来并解释.(如 ...
最新文章
- Delegate,Action,Func,匿名方法,匿名委托,事件
- python socketpool:通用连接池
- citrix创建虚拟机服务器,在 ESXi 服务器上安装并配置 Citrix SD-WAN Center
- ansible service模块使用示例
- Dropout的前世与今生
- HDFS的块缓存和访问权限
- JavaScript中的“ this”关键字
- php数组转化js数组格式化,php数组转换成js数组
- Python中利用for循环的求和运算
- Not showing null elements
- 0ctf Babyheap 2017
- 行业“地震” 监管机构对新车「辅助驾驶系统」评级“下手”
- PostgreSQL 9.6源码解析之XLOG生成
- 如何拆笔记本--键盘拆卸
- linux(centos) 保存退出vi编辑
- 【解决方案】A session ended very soon after starting. Check that the command in profile “XXX” is correct.
- 同岗不同命,软件测试的薪资跨度到底有多大?
- [Go实战]写一个简单的概率算法(抽奖)
- 带进度的圆形进度条的实现
- 思科防火墙ASA配置案例
热门文章
- 鸟哥的Linux私房菜(服务器)- 第十二章、网络参数控管者: DHCP 服务器
- TLD(Tracking-Learning-Detection)学习与源码理解之(五)
- 深入解析阿里Android热修复技术原理
- 高并发架构系列:MQ消息队列的12点核心原理总结
- Golang 的Gin框架入门教学
- Genymotion出现unknown generic error和This may occur if you are using a proxy错误的解决方案
- Android新浪微博client(七)——ListView图片异步加载、高速缓存
- 天气预报开放API调用
- 黑盒測试(一)-----边界值測试
- Linux EXT3文件系统下成功恢复误删的文件