參考http://wandergis.com/leaflet-echarts/src/leaflet-echarts.js
(function(root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['leaflet'], factory); } else if (typeof module === 'object' && module.exports) { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. module.exports = factory(require('leaflet')); } else if (typeof root !== 'undefined' && root.L) { // Browser globals (root is window) root.L.echartsLayer = factory(L); } }(this, function(L) { L.EchartsLayer = L.Class.extend({ includes: [L.Mixin.Events], _echartsContainer: null, _map: null, _ec: null, _option: null, _geoCoord: [], _mapOffset: [0, 0], _delta: 0, _startTime: null, _lastMousePos: null, initialize: function(map, ec) { this._map = map; map.scrollWheelZoom.disable(); 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); }, _init: function(map, ec) { var self = this; self._map = map; //初始化mapoverlay /** * 獲取echarts容器 * * @return {HTMLElement} * @public */ self.getEchartsContainer = function() { return self._echartsContainer; }; /** * 獲取map實例 * * @return {map.Map} * @public */ self.getMap = function() { return self._map; }; /** * 經緯度轉換為屏幕像素 * * @param {Array.<number>} geoCoord 經緯度 * @return {Array.<number>} * @public */ self.geoCoord2Pixel = function(geoCoord) { var point = new L.latLng(geoCoord[1], geoCoord[0]); var pos = self._map.latLngToContainerPoint(point); return [pos.x, pos.y]; }; /** * 屏幕像素轉換為經緯度 * * @param {Array.<number>} pixel 像素坐標 * @return {Array.<number>} * @public */ self.pixel2GeoCoord = function(pixel) { var point = self._map.containerPointToLatLng(L.point(pixel[0], pixel[1])); return [point.lng, point.lat]; }; /** * 初始化echarts實例 * * @return {ECharts} * @public */ self.initECharts = function() { self._ec = ec.init.apply(self, arguments); self._bindEvent(); self._addMarkWrap(); return self._ec; }; // addMark wrap for get position from baidu map by geo location // by kener at 2015.01.08 self._addMarkWrap = function() { function _addMark(seriesIdx, markData, markType) { var data; if (markType == 'markPoint') { var data = markData.data; if (data && data.length) { for (var k = 0, len = data.length; k < len; k++) { if (!(data[k].name && this._geoCoord.hasOwnProperty(data[k].name))) { data[k].name = k + 'markp'; self._geoCoord[data[k].name] = data[k].geoCoord; } self._AddPos(data[k]); } } } else { data = markData.data; if (data && data.length) { for (var k = 0, len = data.length; k < len; k++) { if (!(data[k][0].name && this._geoCoord.hasOwnProperty(data[k][0].name))) { data[k][0].name = k + 'startp'; self._geoCoord[data[k][0].name] = data[k][0].geoCoord; } if (!(data[k][1].name && this._geoCoord.hasOwnProperty(data[k][1].name))) { data[k][1].name = k + 'endp'; self._geoCoord[data[k][1].name] = data[k][1].geoCoord; } self._AddPos(data[k][0]); self._AddPos(data[k][1]); } } } self._ec._addMarkOri(seriesIdx, markData, markType); } self._ec._addMarkOri = self._ec._addMark; self._ec._addMark = _addMark; }; /** * 獲取ECharts實例 * * @return {ECharts} * @public */ self.getECharts = function() { return self._ec; }; /** * 獲取地圖的偏移量 * * @return {Array.<number>} * @public */ self.getMapOffset = function() { return self._mapOffset; }; /** * 對echarts的setOption加一次處理 * 用來為markPoint、markLine中添加x、y坐標,需要name與geoCoord對應 * * @public * @param option * @param notMerge */ self.setOption = function(option, notMerge) { self._option = option; var series = option.series || {}; // 記錄所有的geoCoord for (var i = 0, item; item = series[i++];) { var geoCoord = item.geoCoord; if (geoCoord) { for (var k in geoCoord) { self._geoCoord[k] = geoCoord[k]; } } } // 添加x、y for (var i = 0, item; item = series[i++];) { var markPoint = item.markPoint || {}; var markLine = item.markLine || {}; var data = markPoint.data; if (data && data.length) { for (var k = 0, len = data.length; k < len; k++) { if (!(data[k].name && this._geoCoord.hasOwnProperty(data[k].name))) { data[k].name = k + 'markp'; self._geoCoord[data[k].name] = data[k].geoCoord; } self._AddPos(data[k]); } } data = markLine.data; if (data && data.length) { for (var k = 0, len = data.length; k < len; k++) { if (!(data[k][0].name && this._geoCoord.hasOwnProperty(data[k][0].name))) { data[k][0].name = k + 'startp'; self._geoCoord[data[k][0].name] = data[k][0].geoCoord; } if (!(data[k][1].name && this._geoCoord.hasOwnProperty(data[k][1].name))) { data[k][1].name = k + 'endp'; self._geoCoord[data[k][1].name] = data[k][1].geoCoord; } self._AddPos(data[k][0]); self._AddPos(data[k][1]); } } } self._ec.setOption(option, notMerge); }; /** * 增加x、y坐標 * * @param {Object} obj markPoint、markLine data中的項,必須有name * @param {Object} geoCoord */ self._AddPos = function(obj) { var coord = self._geoCoord[obj.name]; var pos = self.geoCoord2Pixel(coord); obj.x = pos[0]; //- self._mapOffset[0]; obj.y = pos[1]; //- self._mapOffset[1]; }; /** * 綁定地圖事件的處理方法 * * @private */ self._bindEvent = function() { self._map.on('move', _moveHandler('moving')); self._map.on('moveend', _moveHandler('moveend')); self._map.on('zoomstart', function() { self._ec.clear(); }); self._map.on('zoomend', _zoomChangeHandler); self._ec.getZrender().on('dragstart', _dragZrenderHandler(true)); self._ec.getZrender().on('dragend', _dragZrenderHandler(false)); self._ec.getZrender().on('mouseup', function() { // self.setOption(self._option); //修改了echarts源碼解決了這個問題 }); self._ec.getZrender().on('mousedown', function() { // self._ec.clear(); //修改了echarts源碼解決了這個問題 }); self._ec.getZrender().on('mousewheel', function(e) { self._ec.clear(); //在mousewheel的時候清除echarts內容 self._lastMousePos = self._map.mouseEventToContainerPoint(e.event); var delta = L.DomEvent.getWheelDelta(e.event); var map = self._map, zoom = map.getZoom(); delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); delta = Math.max(Math.min(delta, 4), -4); delta = map._limitZoom(zoom + delta) - zoom; self._delta = 0; self._startTime = null; if (!delta) { return; } if (map.options.scrollWheelZoom === 'center') { map.setZoom(zoom + delta); } else { map.setZoomAround(self._lastMousePos, zoom + delta); } }); }; /** * 地圖縮放觸發事件 * * @private */ function _zoomChangeHandler() { self.setOption(self._option); } // function _zoomatartChangeHandler() { // self._ec.clear(); // } /** * 地圖移動、如拖拽觸發事件 * * @param {string} type moving | moveend 移動中|移動結束 * @return {Function} * @private */ function _moveHandler(type) { return function() { var domPosition = self._map._getMapPanePos(); // 記錄偏移量 self._mapOffset = [-parseInt(domPosition.x) || 0, -parseInt(domPosition.y) || 0]; self._echartsContainer.style.left = self._mapOffset[0] + 'px'; self._echartsContainer.style.top = self._mapOffset[1] + 'px'; //_fireEvent(type); if (type == 'moving') { self._ec.clear(); } if (type == 'moveend') { self.setOption(self._option); } } } /** * Zrender拖拽觸發事件 * * @param {boolean} isStart * @return {Function} * @private */ function _dragZrenderHandler(isStart) { return function() { var func = isStart ? 'disable' : 'enable'; if (isStart) { self._ec.clear(); } else { self.setOption(self._option); } self._map.dragging[func](); }; } } }); L.echartsLayer = function(map, ec) { return new L.EchartsLayer(map, ec); }; return L.echartsLayer; }));
看了這個源碼之后一直有個疑問就是echarts的地圖坐標和地圖本身的坐標怎么對應上,因為我們在使用echarts時是,傳入的坐標都是經緯度,這就說明它本身是有坐標系的,這個怎么和自己地圖的坐標系對應起來呢。
后來發現echarts里options參數的series里面有個mapType參數,mapType為undefined時參數坐標的值為經緯度,mapType為none時參數的坐標軸為屏幕像素;
搞明白了這個,就好理解上面的源碼了。參考這個源碼就可以實現arcgis或者openLayers的擴展。