├── .gitignore ├── .DS_Store ├── demo ├── .DS_Store ├── lib │ ├── .DS_Store │ ├── svg │ │ ├── mapboxgl-ctrl-compass.svg │ │ ├── mapboxgl-ctrl-zoom-out.svg │ │ ├── mapboxgl-ctrl-attrib.svg │ │ ├── mapboxgl-ctrl-zoom-in.svg │ │ └── mapboxgl-ctrl-geolocate.svg │ └── mapbox-gl.css ├── lines-airline.html ├── scatter-weibo.html ├── geo-line.html └── effectScatter-map.html ├── index.js ├── lib ├── GLMapModel.js ├── GLMap.js ├── EchartsLayer.js ├── GLMapCoordSys.js └── GLMapView.js ├── webpack.config.js ├── package.json ├── LICENSE ├── readme.md └── dist ├── EchartsLayer.min.js └── EchartsLayer.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzxue/echartsLayer/HEAD/.DS_Store -------------------------------------------------------------------------------- /demo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzxue/echartsLayer/HEAD/demo/.DS_Store -------------------------------------------------------------------------------- /demo/lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzxue/echartsLayer/HEAD/demo/lib/.DS_Store -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("./lib/GLMap.js") 2 | var EchartsLayer=require("./lib/EchartsLayer.js") 3 | module.exports=EchartsLayer; -------------------------------------------------------------------------------- /demo/lib/svg/mapboxgl-ctrl-compass.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo/lib/svg/mapboxgl-ctrl-zoom-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /demo/lib/svg/mapboxgl-ctrl-attrib.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/GLMapModel.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | 3 | return require('echarts').extendComponentModel({ 4 | type: 'GLMap', 5 | 6 | getBMap: function () { 7 | // __bmap is injected when creating BMapCoordSys 8 | return this.__GLMap; 9 | }, 10 | 11 | defaultOption: { 12 | roam: false 13 | } 14 | }); 15 | }); -------------------------------------------------------------------------------- /demo/lib/svg/mapboxgl-ctrl-zoom-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var PROD = process.argv.indexOf('-p') >= 0; 2 | 3 | module.exports = { 4 | entry: { 5 | 'EchartsLayer': __dirname + '/index.js', 6 | }, 7 | output: { 8 | libraryTarget: 'umd', 9 | library: ['[name]'], 10 | path: __dirname + '/dist/', 11 | filename: PROD ? '[name].min.js' : '[name].js' 12 | }, 13 | externals: { 14 | 'echarts': 'echarts' 15 | } 16 | }; -------------------------------------------------------------------------------- /lib/GLMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * GLMap component extension 3 | */ 4 | define(function (require) { 5 | require('echarts').registerCoordinateSystem( 6 | 'GLMap', require('./GLMapCoordSys') 7 | ) 8 | require('./GLMapModel') 9 | require('./GLMapView') 10 | 11 | // Action 12 | require('echarts').registerAction({ 13 | type: 'GLMapRoam', 14 | event: 'GLMapRoam', 15 | update: 'updateLayout' 16 | }, function (payload, ecModel) {}) 17 | 18 | return { 19 | version: '1.0.0' 20 | } 21 | }) 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/lib/svg/mapboxgl-ctrl-geolocate.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "echartslayer", 3 | "version": "0.1.6", 4 | "description": "echarts MapboxGL", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "lizhengxue", 10 | "license": "ISC", 11 | "dependencies": { 12 | "echarts": "^3.3.2" 13 | }, 14 | "devDependencies": {}, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/lzxue/echartsLayer.git" 18 | }, 19 | "keywords": [ 20 | "mapboxgl", 21 | "echarts" 22 | ], 23 | "homepage": "https://github.com/lzxue/echartsLayer#readme" 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 @thinkinggis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## mapboxGL echartslayer 2 | Add [echarts](https://github.com/ecomfe/echarts) charts to [mapboxGL](https://github.com/mapbox/mapbox-gl-js) as a layer 3 | 4 | In order to use this plugin, include the echartsjs andEchartsLayer.js on your page and use it as follow: 5 | 6 | ### demo 7 | 8 | [全球航线](https://lzxue.github.io/echartsLayer/demo/lines-airline.html) 9 | 10 | [全国空气质量](https://lzxue.github.io/echartsLayer/demo/effectScatter-map.html) 11 | 12 | [模拟迁徙](https://lzxue.github.io/echartsLayer/demo/geo-line.html) 13 | 14 | [微博签到](https://lzxue.github.io/echartsLayer/demo/scatter-weibo.html) 15 | 16 | 17 | ### import 18 | 19 | ```html 20 | 21 | 22 | ``` 23 | 24 | ### with webpack 25 | 26 | ```js 27 | npm install echartslayer 28 | ``` 29 | ```js 30 | require('echarts'); 31 | var EchartLayer=require('echartslayer'); 32 | 33 | var echartslayer = new EchartsLayer(map); 34 | echartslayer.chart.setOption(option); 35 | //移除 36 | echartslayer.remove(); 37 | 38 | ``` 39 | 40 | ### Usage 41 | 42 | set the charts attribute coordinateSystem:"GLMap" 43 | 44 | ```js 45 | option = { 46 | GLMap: { //Must 47 | 48 | }, 49 | series: [{ 50 | coordinateSystem: 'GLMap', 51 | }] 52 | } 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /lib/EchartsLayer.js: -------------------------------------------------------------------------------- 1 | function EchartsLayer(map) { 2 | const mapContainer = map.getCanvasContainer(); 3 | this._container = document.createElement('div'); 4 | this._container.style.width = map.getCanvas().style.width; 5 | this._container.style.height = map.getCanvas().style.height; 6 | this._container.setAttribute('id', 'echarts'); 7 | this._container.setAttribute('class', 'echartMap'); 8 | this._map = map; 9 | mapContainer.appendChild(this._container); 10 | this.chart = echarts.init(this._container); 11 | echarts.glMap = map; 12 | this.resize(); 13 | } 14 | EchartsLayer.prototype.remove = function() { 15 | var _this = this; 16 | this._map._listeners.move.forEach(function(element) { 17 | if (element.name === 'moveHandler') { 18 | _this._map.off('move', element); 19 | } 20 | }); 21 | this._map._listeners.move.forEach(function(element) { 22 | if (element.name === 'zoomEndHandler') { 23 | _this._map.off('zoomend', element); 24 | } 25 | }); 26 | 27 | // this._map.off('move', this._map._listeners.move[1]); 28 | // this._map.off('zoomend', this._map._listeners.moveend[1]); 29 | this.chart.clear(); 30 | if(this._container.parentNode) 31 | this._container.parentNode.removeChild(this._container); 32 | this._map = undefined; 33 | }; 34 | EchartsLayer.prototype.resize = function() { 35 | const me = this; 36 | window.onresize = function() { 37 | me._container.style.width = me._map.getCanvas().style.width; 38 | me._container.style.height = me._map.getCanvas().style.height; 39 | me.chart.resize(); 40 | }; 41 | }; 42 | module.exports = EchartsLayer; 43 | -------------------------------------------------------------------------------- /lib/GLMapCoordSys.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var echarts = require('echarts') 3 | 4 | function GLMapCoordSys (GLMap, api) { 5 | this._GLMap = GLMap 6 | this.dimensions = ['lng', 'lat'] 7 | this._mapOffset = [0, 0] 8 | 9 | this._api = api 10 | } 11 | 12 | GLMapCoordSys.prototype.dimensions = ['lng', 'lat'] 13 | 14 | GLMapCoordSys.prototype.setMapOffset = function (mapOffset) { 15 | this._mapOffset = mapOffset 16 | } 17 | 18 | GLMapCoordSys.prototype.getBMap = function () { 19 | return this._GLMap 20 | } 21 | 22 | GLMapCoordSys.prototype.dataToPoint = function (data) { 23 | var px = this._GLMap.project(data) 24 | 25 | var mapOffset = this._mapOffset 26 | 27 | return [px.x - mapOffset[0], px.y - mapOffset[1]] 28 | } 29 | 30 | GLMapCoordSys.prototype.pointToData = function (pt) { 31 | var mapOffset = this._mapOffset 32 | var pt = this._bmap.project( 33 | [ pt[0] + mapOffset[0], 34 | pt[1] + mapOffset[1]] 35 | ) 36 | return [pt.lng, pt.lat] 37 | } 38 | 39 | GLMapCoordSys.prototype.getViewRect = function () { 40 | var api = this._api 41 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()) 42 | } 43 | 44 | GLMapCoordSys.prototype.getRoamTransform = function () { 45 | return echarts.matrix.create() 46 | } 47 | 48 | 49 | // For deciding which dimensions to use when creating list data 50 | GLMapCoordSys.dimensions = GLMapCoordSys.prototype.dimensions 51 | 52 | GLMapCoordSys.create = function (ecModel, api) { 53 | var coordSys; 54 | 55 | ecModel.eachComponent('GLMap', function (GLMapModel) { 56 | var viewportRoot = api.getZr().painter.getViewportRoot() 57 | var GLMap = echarts.glMap; 58 | coordSys = new GLMapCoordSys(GLMap, api) 59 | coordSys.setMapOffset(GLMapModel.__mapOffset || [0, 0]) 60 | GLMapModel.coordinateSystem = coordSys 61 | }) 62 | 63 | ecModel.eachSeries(function (seriesModel) { 64 | if (seriesModel.get('coordinateSystem') === 'GLMap') { 65 | seriesModel.coordinateSystem = coordSys 66 | } 67 | }) 68 | } 69 | 70 | return GLMapCoordSys 71 | }) 72 | -------------------------------------------------------------------------------- /lib/GLMapView.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | return require('echarts').extendComponentView({ 3 | type: 'GLMap', 4 | 5 | render: function (GLMapModel, ecModel, api) { 6 | var rendering = true 7 | 8 | var glMap = echarts.glMap 9 | 10 | 11 | var viewportRoot = api.getZr().painter.getViewportRoot() 12 | var coordSys = GLMapModel.coordinateSystem 13 | var moveHandler = function (type, target) { 14 | if (rendering) { 15 | return 16 | } 17 | // var offsetEl = viewportRoot.parentNode.parentNode.parentNode 18 | var offsetEl = document.getElementsByClassName('mapboxgl-map')[0]; 19 | 20 | var mapOffset = [ 21 | -parseInt(offsetEl.style.left, 10) || 0, 22 | -parseInt(offsetEl.style.top, 10) || 0 23 | ] 24 | viewportRoot.style.left = mapOffset[0] + 'px' 25 | viewportRoot.style.top = mapOffset[1] + 'px' 26 | 27 | coordSys.setMapOffset(mapOffset) 28 | GLMapModel.__mapOffset = mapOffset 29 | 30 | api.dispatchAction({ 31 | type: 'GLMapRoam' 32 | }) 33 | } 34 | 35 | function zoomEndHandler () { 36 | if (rendering) { 37 | return 38 | } 39 | api.dispatchAction({ 40 | type: 'GLMapRoam' 41 | }) 42 | } 43 | 44 | glMap.off('move', this._oldMoveHandler) 45 | // FIXME 46 | // Moveend may be triggered by centerAndZoom method when creating coordSys next time 47 | // glMap.removeEventListener('moveend', this._oldMoveHandler) 48 | glMap.off('zoomend', this._oldZoomEndHandler) 49 | glMap.on('move', moveHandler) 50 | // glMap.addEventListener('moveend', moveHandler) 51 | glMap.on('zoomend', zoomEndHandler) 52 | 53 | this._oldMoveHandler = moveHandler 54 | this._oldZoomEndHandler = zoomEndHandler 55 | 56 | var roam = GLMapModel.get('roam') 57 | if (roam && roam !== 'scale') { 58 | // todo 允许拖拽 59 | }else { 60 | // todo 不允许拖拽 61 | } 62 | if (roam && roam !== 'move') { 63 | // todo 允许移动 64 | }else { 65 | // todo 不允许允许移动 66 | } 67 | 68 | 69 | 70 | rendering = false 71 | } 72 | }) 73 | }) 74 | -------------------------------------------------------------------------------- /dist/EchartsLayer.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("echarts")):"function"==typeof define&&define.amd?define(["echarts"],e):"object"==typeof exports?exports.EchartsLayer=e(require("echarts")):t.EchartsLayer=e(t.echarts)}(this,function(t){return function(t){function e(n){if(o[n])return o[n].exports;var i=o[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var o={};return e.m=t,e.c=o,e.p="",e(0)}([function(t,e,o){o(3);var n=o(2);t.exports=n},function(e,o){e.exports=t},function(t,e){function o(t){const e=t.getCanvasContainer();this._container=document.createElement("div"),this._container.style.width=t.getCanvas().style.width,this._container.style.height=t.getCanvas().style.height,this._container.setAttribute("id","echarts"),this._container.setAttribute("class","echartMap"),this._map=t,e.appendChild(this._container),this.chart=echarts.init(this._container),echarts.glMap=t,this.resize()}o.prototype.remove=function(){var t=this;this._map._listeners.move.forEach(function(e){"moveHandler"===e.name&&t._map.off("move",e)}),this._map._listeners.move.forEach(function(e){"zoomEndHandler"===e.name&&t._map.off("zoomend",e)}),this.chart.clear(),this._container.parentNode&&this._container.parentNode.removeChild(this._container),this._map=void 0},o.prototype.resize=function(){const t=this;window.onresize=function(){t._container.style.width=t._map.getCanvas().style.width,t._container.style.height=t._map.getCanvas().style.height,t.chart.resize()}},t.exports=o},function(t,e,o){var n;n=function(t){return o(1).registerCoordinateSystem("GLMap",o(4)),o(5),o(6),o(1).registerAction({type:"GLMapRoam",event:"GLMapRoam",update:"updateLayout"},function(t,e){}),{version:"1.0.0"}}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){function e(t,e){this._GLMap=t,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=e}var n=o(1);return e.prototype.dimensions=["lng","lat"],e.prototype.setMapOffset=function(t){this._mapOffset=t},e.prototype.getBMap=function(){return this._GLMap},e.prototype.dataToPoint=function(t){var e=this._GLMap.project(t),o=this._mapOffset;return[e.x-o[0],e.y-o[1]]},e.prototype.pointToData=function(t){var e=this._mapOffset,t=this._bmap.project([t[0]+e[0],t[1]+e[1]]);return[t.lng,t.lat]},e.prototype.getViewRect=function(){var t=this._api;return new n.graphic.BoundingRect(0,0,t.getWidth(),t.getHeight())},e.prototype.getRoamTransform=function(){return n.matrix.create()},e.dimensions=e.prototype.dimensions,e.create=function(t,o){var i;t.eachComponent("GLMap",function(t){var a=(o.getZr().painter.getViewportRoot(),n.glMap);i=new e(a,o),i.setMapOffset(t.__mapOffset||[0,0]),t.coordinateSystem=i}),t.eachSeries(function(t){"GLMap"===t.get("coordinateSystem")&&(t.coordinateSystem=i)})},e}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){return o(1).extendComponentModel({type:"GLMap",getBMap:function(){return this.__GLMap},defaultOption:{roam:!1}})}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){return o(1).extendComponentView({type:"GLMap",render:function(t,e,o){function n(){i||o.dispatchAction({type:"GLMapRoam"})}var i=!0,a=echarts.glMap,r=o.getZr().painter.getViewportRoot(),s=t.coordinateSystem,p=function(e,n){if(!i){var a=document.getElementsByClassName("mapboxgl-map")[0],p=[-parseInt(a.style.left,10)||0,-parseInt(a.style.top,10)||0];r.style.left=p[0]+"px",r.style.top=p[1]+"px",s.setMapOffset(p),t.__mapOffset=p,o.dispatchAction({type:"GLMapRoam"})}};a.off("move",this._oldMoveHandler),a.off("zoomend",this._oldZoomEndHandler),a.on("move",p),a.on("zoomend",n),this._oldMoveHandler=p,this._oldZoomEndHandler=n;t.get("roam");i=!1}})}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))}])}); -------------------------------------------------------------------------------- /demo/lines-airline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /demo/scatter-weibo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /demo/lib/mapbox-gl.css: -------------------------------------------------------------------------------- 1 | .mapboxgl-map { 2 | font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; 3 | overflow: hidden; 4 | position: relative; 5 | -webkit-tap-highlight-color: rgba(0,0,0,0); 6 | } 7 | 8 | .mapboxgl-canvas-container.mapboxgl-interactive, 9 | .mapboxgl-ctrl-nav-compass { 10 | cursor: -webkit-grab; 11 | cursor: -moz-grab; 12 | cursor: grab; 13 | } 14 | .mapboxgl-canvas-container.mapboxgl-interactive:active, 15 | .mapboxgl-ctrl-nav-compass:active { 16 | cursor: -webkit-grabbing; 17 | cursor: -moz-grabbing; 18 | cursor: grabbing; 19 | } 20 | 21 | .mapboxgl-ctrl-top-left, 22 | .mapboxgl-ctrl-top-right, 23 | .mapboxgl-ctrl-bottom-left, 24 | .mapboxgl-ctrl-bottom-right { position:absolute; pointer-events:none; z-index:2; } 25 | .mapboxgl-ctrl-top-left { top:0; left:0; } 26 | .mapboxgl-ctrl-top-right { top:0; right:0; } 27 | .mapboxgl-ctrl-bottom-left { bottom:0; left:0; } 28 | .mapboxgl-ctrl-bottom-right { right:0; bottom:0; } 29 | 30 | .mapboxgl-ctrl { clear:both; pointer-events:auto } 31 | .mapboxgl-ctrl-top-left .mapboxgl-ctrl { margin:10px 0 0 10px; float:left; } 32 | .mapboxgl-ctrl-top-right .mapboxgl-ctrl{ margin:10px 10px 0 0; float:right; } 33 | .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl { margin:0 0 10px 10px; float:left; } 34 | .mapboxgl-ctrl-bottom-right .mapboxgl-ctrl { margin:0 10px 10px 0; float:right; } 35 | 36 | .mapboxgl-ctrl-group { 37 | border-radius: 4px; 38 | -moz-box-shadow: 0px 0px 2px rgba(0,0,0,0.1); 39 | -webkit-box-shadow: 0px 0px 2px rgba(0,0,0,0.1); 40 | box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.1); 41 | overflow: hidden; 42 | background: #fff; 43 | } 44 | .mapboxgl-ctrl-group > button { 45 | width: 30px; 46 | height: 30px; 47 | display: block; 48 | padding: 0; 49 | outline: none; 50 | border: none; 51 | border-bottom: 1px solid #ddd; 52 | box-sizing: border-box; 53 | background-color: rgba(0,0,0,0); 54 | cursor: pointer; 55 | } 56 | /* https://bugzilla.mozilla.org/show_bug.cgi?id=140562 */ 57 | .mapboxgl-ctrl > button::-moz-focus-inner { 58 | border: 0; 59 | padding: 0; 60 | } 61 | .mapboxgl-ctrl > button:last-child { 62 | border-bottom: 0; 63 | } 64 | .mapboxgl-ctrl > button:hover { 65 | background-color: rgba(0,0,0,0.05); 66 | } 67 | .mapboxgl-ctrl-icon, 68 | .mapboxgl-ctrl-icon > span.arrow { 69 | speak: none; 70 | -webkit-font-smoothing: antialiased; 71 | -moz-osx-font-smoothing: grayscale; 72 | } 73 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out { 74 | padding: 5px; 75 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27m%207%2C9%20c%20-0.554%2C0%20-1%2C0.446%20-1%2C1%200%2C0.554%200.446%2C1%201%2C1%20l%206%2C0%20c%200.554%2C0%201%2C-0.446%201%2C-1%200%2C-0.554%20-0.446%2C-1%20-1%2C-1%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); 76 | } 77 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in { 78 | padding: 5px; 79 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); 80 | } 81 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate { 82 | padding: 5px; 83 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgdmVyc2lvbj0iMS4xIj48cGF0aCBkPSJNMTAgNEM5IDQgOSA1IDkgNUw5IDUuMUE1IDUgMCAwIDAgNS4xIDlMNSA5QzUgOSA0IDkgNCAxMCA0IDExIDUgMTEgNSAxMUw1LjEgMTFBNSA1IDAgMCAwIDkgMTQuOUw5IDE1QzkgMTUgOSAxNiAxMCAxNiAxMSAxNiAxMSAxNSAxMSAxNUwxMSAxNC45QTUgNSAwIDAgMCAxNC45IDExTDE1IDExQzE1IDExIDE2IDExIDE2IDEwIDE2IDkgMTUgOSAxNSA5TDE0LjkgOUE1IDUgMCAwIDAgMTEgNS4xTDExIDVDMTEgNSAxMSA0IDEwIDR6TTEwIDYuNUEzLjUgMy41IDAgMCAxIDEzLjUgMTAgMy41IDMuNSAwIDAgMSAxMCAxMy41IDMuNSAzLjUgMCAwIDEgNi41IDEwIDMuNSAzLjUgMCAwIDEgMTAgNi41ek0xMCA4LjNBMS44IDEuOCAwIDAgMCA4LjMgMTAgMS44IDEuOCAwIDAgMCAxMCAxMS44IDEuOCAxLjggMCAwIDAgMTEuOCAxMCAxLjggMS44IDAgMCAwIDEwIDguM3oiIGZpbGw9IiMzMzMiLz48L3N2Zz4="); 84 | } 85 | 86 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > span.arrow { 87 | width: 20px; 88 | height: 20px; 89 | margin: 5px; 90 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%0A%09%3Cpolygon%20fill%3D%27%23333333%27%20points%3D%276%2C9%2010%2C1%2014%2C9%27%2F%3E%0A%09%3Cpolygon%20fill%3D%27%23CCCCCC%27%20points%3D%276%2C11%2010%2C19%2014%2C11%20%27%2F%3E%0A%3C%2Fsvg%3E"); 91 | background-repeat: no-repeat; 92 | display: inline-block; 93 | } 94 | 95 | .mapboxgl-ctrl.mapboxgl-ctrl-attrib { 96 | padding: 0 5px; 97 | background-color: rgba(255,255,255,0.5); 98 | margin: 0; 99 | } 100 | .mapboxgl-ctrl-attrib a { 101 | color: rgba(0,0,0,0.75); 102 | text-decoration: none; 103 | } 104 | .mapboxgl-ctrl-attrib a:hover { 105 | color: inherit; 106 | text-decoration: underline; 107 | } 108 | .mapboxgl-ctrl-attrib .mapbox-improve-map { 109 | font-weight: bold; 110 | margin-left: 2px; 111 | } 112 | 113 | .mapboxgl-ctrl-scale { 114 | background-color: rgba(255,255,255,0.75); 115 | font-size: 10px; 116 | border-width: medium 2px 2px; 117 | border-style: none solid solid; 118 | border-color: #333; 119 | padding: 0 5px; 120 | color: #333; 121 | } 122 | 123 | .mapboxgl-popup { 124 | position: absolute; 125 | top: 0; 126 | left: 0; 127 | display: -webkit-flex; 128 | display: flex; 129 | will-change: transform; 130 | pointer-events: none; 131 | } 132 | .mapboxgl-popup-anchor-top, 133 | .mapboxgl-popup-anchor-top-left, 134 | .mapboxgl-popup-anchor-top-right { 135 | -webkit-flex-direction: column; 136 | flex-direction: column; 137 | } 138 | .mapboxgl-popup-anchor-bottom, 139 | .mapboxgl-popup-anchor-bottom-left, 140 | .mapboxgl-popup-anchor-bottom-right { 141 | -webkit-flex-direction: column-reverse; 142 | flex-direction: column-reverse; 143 | } 144 | .mapboxgl-popup-anchor-left { 145 | -webkit-flex-direction: row; 146 | flex-direction: row; 147 | } 148 | .mapboxgl-popup-anchor-right { 149 | -webkit-flex-direction: row-reverse; 150 | flex-direction: row-reverse; 151 | } 152 | .mapboxgl-popup-tip { 153 | width: 0; 154 | height: 0; 155 | border: 10px solid transparent; 156 | z-index: 1; 157 | } 158 | .mapboxgl-popup-anchor-top .mapboxgl-popup-tip { 159 | -webkit-align-self: center; 160 | align-self: center; 161 | border-top: none; 162 | border-bottom-color: #fff; 163 | } 164 | .mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip { 165 | -webkit-align-self: flex-start; 166 | align-self: flex-start; 167 | border-top: none; 168 | border-left: none; 169 | border-bottom-color: #fff; 170 | } 171 | .mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip { 172 | -webkit-align-self: flex-end; 173 | align-self: flex-end; 174 | border-top: none; 175 | border-right: none; 176 | border-bottom-color: #fff; 177 | } 178 | .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { 179 | -webkit-align-self: center; 180 | align-self: center; 181 | border-bottom: none; 182 | border-top-color: #fff; 183 | } 184 | .mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip { 185 | -webkit-align-self: flex-start; 186 | align-self: flex-start; 187 | border-bottom: none; 188 | border-left: none; 189 | border-top-color: #fff; 190 | } 191 | .mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip { 192 | -webkit-align-self: flex-end; 193 | align-self: flex-end; 194 | border-bottom: none; 195 | border-right: none; 196 | border-top-color: #fff; 197 | } 198 | .mapboxgl-popup-anchor-left .mapboxgl-popup-tip { 199 | -webkit-align-self: center; 200 | align-self: center; 201 | border-left: none; 202 | border-right-color: #fff; 203 | } 204 | .mapboxgl-popup-anchor-right .mapboxgl-popup-tip { 205 | -webkit-align-self: center; 206 | align-self: center; 207 | border-right: none; 208 | border-left-color: #fff; 209 | } 210 | .mapboxgl-popup-close-button { 211 | position: absolute; 212 | right: 0; 213 | top: 0; 214 | border: none; 215 | border-radius: 0 3px 0 0; 216 | cursor: pointer; 217 | background-color: rgba(0,0,0,0); 218 | } 219 | .mapboxgl-popup-close-button:hover { 220 | background-color: rgba(0,0,0,0.05); 221 | } 222 | .mapboxgl-popup-content { 223 | position: relative; 224 | background: #fff; 225 | border-radius: 3px; 226 | box-shadow: 0 1px 2px rgba(0,0,0,0.10); 227 | padding: 10px 10px 15px; 228 | pointer-events: auto; 229 | } 230 | .mapboxgl-popup-anchor-top-left .mapboxgl-popup-content { 231 | border-top-left-radius: 0; 232 | } 233 | .mapboxgl-popup-anchor-top-right .mapboxgl-popup-content { 234 | border-top-right-radius: 0; 235 | } 236 | .mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-content { 237 | border-bottom-left-radius: 0; 238 | } 239 | .mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-content { 240 | border-bottom-right-radius: 0; 241 | } 242 | 243 | .mapboxgl-marker { 244 | position: absolute; 245 | top: 0; 246 | left: 0; 247 | will-change: transform; 248 | } 249 | 250 | .mapboxgl-crosshair, 251 | .mapboxgl-crosshair .mapboxgl-interactive, 252 | .mapboxgl-crosshair .mapboxgl-interactive:active { 253 | cursor: crosshair; 254 | } 255 | .mapboxgl-boxzoom { 256 | position: absolute; 257 | top: 0; 258 | left: 0; 259 | width: 0; 260 | height: 0; 261 | background: #fff; 262 | border: 2px dotted #202020; 263 | opacity: 0.5; 264 | } 265 | @media print { 266 | .mapbox-improve-map { 267 | display:none; 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /dist/EchartsLayer.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(require("echarts")); 4 | else if(typeof define === 'function' && define.amd) 5 | define(["echarts"], factory); 6 | else if(typeof exports === 'object') 7 | exports["EchartsLayer"] = factory(require("echarts")); 8 | else 9 | root["EchartsLayer"] = factory(root["echarts"]); 10 | })(this, function(__WEBPACK_EXTERNAL_MODULE_2__) { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) 20 | /******/ return installedModules[moduleId].exports; 21 | 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ exports: {}, 25 | /******/ id: moduleId, 26 | /******/ loaded: false 27 | /******/ }; 28 | 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | 32 | /******/ // Flag the module as loaded 33 | /******/ module.loaded = true; 34 | 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | 39 | 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | 46 | /******/ // __webpack_public_path__ 47 | /******/ __webpack_require__.p = ""; 48 | 49 | /******/ // Load entry module and return exports 50 | /******/ return __webpack_require__(0); 51 | /******/ }) 52 | /************************************************************************/ 53 | /******/ ([ 54 | /* 0 */ 55 | /***/ function(module, exports, __webpack_require__) { 56 | 57 | __webpack_require__(1) 58 | var EchartsLayer=__webpack_require__(6) 59 | module.exports=EchartsLayer; 60 | 61 | /***/ }, 62 | /* 1 */ 63 | /***/ function(module, exports, __webpack_require__) { 64 | 65 | var __WEBPACK_AMD_DEFINE_RESULT__;/** 66 | * GLMap component extension 67 | */ 68 | !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { 69 | __webpack_require__(2).registerCoordinateSystem( 70 | 'GLMap', __webpack_require__(3) 71 | ) 72 | __webpack_require__(4) 73 | __webpack_require__(5) 74 | 75 | // Action 76 | __webpack_require__(2).registerAction({ 77 | type: 'GLMapRoam', 78 | event: 'GLMapRoam', 79 | update: 'updateLayout' 80 | }, function (payload, ecModel) {}) 81 | 82 | return { 83 | version: '1.0.0' 84 | } 85 | }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) 86 | 87 | 88 | 89 | 90 | /***/ }, 91 | /* 2 */ 92 | /***/ function(module, exports) { 93 | 94 | module.exports = __WEBPACK_EXTERNAL_MODULE_2__; 95 | 96 | /***/ }, 97 | /* 3 */ 98 | /***/ function(module, exports, __webpack_require__) { 99 | 100 | var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { 101 | var echarts = __webpack_require__(2) 102 | 103 | function GLMapCoordSys (GLMap, api) { 104 | this._GLMap = GLMap 105 | this.dimensions = ['lng', 'lat'] 106 | this._mapOffset = [0, 0] 107 | 108 | this._api = api 109 | } 110 | 111 | GLMapCoordSys.prototype.dimensions = ['lng', 'lat'] 112 | 113 | GLMapCoordSys.prototype.setMapOffset = function (mapOffset) { 114 | this._mapOffset = mapOffset 115 | } 116 | 117 | GLMapCoordSys.prototype.getBMap = function () { 118 | return this._GLMap 119 | } 120 | 121 | GLMapCoordSys.prototype.dataToPoint = function (data) { 122 | var px = this._GLMap.project(data) 123 | 124 | var mapOffset = this._mapOffset 125 | 126 | return [px.x - mapOffset[0], px.y - mapOffset[1]] 127 | } 128 | 129 | GLMapCoordSys.prototype.pointToData = function (pt) { 130 | var mapOffset = this._mapOffset 131 | var pt = this._bmap.project( 132 | [ pt[0] + mapOffset[0], 133 | pt[1] + mapOffset[1]] 134 | ) 135 | return [pt.lng, pt.lat] 136 | } 137 | 138 | GLMapCoordSys.prototype.getViewRect = function () { 139 | var api = this._api 140 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()) 141 | } 142 | 143 | GLMapCoordSys.prototype.getRoamTransform = function () { 144 | return echarts.matrix.create() 145 | } 146 | 147 | 148 | // For deciding which dimensions to use when creating list data 149 | GLMapCoordSys.dimensions = GLMapCoordSys.prototype.dimensions 150 | 151 | GLMapCoordSys.create = function (ecModel, api) { 152 | var coordSys; 153 | 154 | ecModel.eachComponent('GLMap', function (GLMapModel) { 155 | var viewportRoot = api.getZr().painter.getViewportRoot() 156 | var GLMap = echarts.glMap; 157 | coordSys = new GLMapCoordSys(GLMap, api) 158 | coordSys.setMapOffset(GLMapModel.__mapOffset || [0, 0]) 159 | GLMapModel.coordinateSystem = coordSys 160 | }) 161 | 162 | ecModel.eachSeries(function (seriesModel) { 163 | if (seriesModel.get('coordinateSystem') === 'GLMap') { 164 | seriesModel.coordinateSystem = coordSys 165 | } 166 | }) 167 | } 168 | 169 | return GLMapCoordSys 170 | }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) 171 | 172 | 173 | /***/ }, 174 | /* 4 */ 175 | /***/ function(module, exports, __webpack_require__) { 176 | 177 | var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { 178 | 179 | return __webpack_require__(2).extendComponentModel({ 180 | type: 'GLMap', 181 | 182 | getBMap: function () { 183 | // __bmap is injected when creating BMapCoordSys 184 | return this.__GLMap; 185 | }, 186 | 187 | defaultOption: { 188 | roam: false 189 | } 190 | }); 191 | }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 192 | 193 | /***/ }, 194 | /* 5 */ 195 | /***/ function(module, exports, __webpack_require__) { 196 | 197 | var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = function (require) { 198 | return __webpack_require__(2).extendComponentView({ 199 | type: 'GLMap', 200 | 201 | render: function (GLMapModel, ecModel, api) { 202 | var rendering = true 203 | 204 | var glMap = echarts.glMap 205 | 206 | 207 | var viewportRoot = api.getZr().painter.getViewportRoot() 208 | var coordSys = GLMapModel.coordinateSystem 209 | var moveHandler = function (type, target) { 210 | if (rendering) { 211 | return 212 | } 213 | // var offsetEl = viewportRoot.parentNode.parentNode.parentNode 214 | var offsetEl = document.getElementsByClassName('mapboxgl-map')[0]; 215 | 216 | var mapOffset = [ 217 | -parseInt(offsetEl.style.left, 10) || 0, 218 | -parseInt(offsetEl.style.top, 10) || 0 219 | ] 220 | viewportRoot.style.left = mapOffset[0] + 'px' 221 | viewportRoot.style.top = mapOffset[1] + 'px' 222 | 223 | coordSys.setMapOffset(mapOffset) 224 | GLMapModel.__mapOffset = mapOffset 225 | 226 | api.dispatchAction({ 227 | type: 'GLMapRoam' 228 | }) 229 | } 230 | 231 | function zoomEndHandler () { 232 | if (rendering) { 233 | return 234 | } 235 | api.dispatchAction({ 236 | type: 'GLMapRoam' 237 | }) 238 | } 239 | 240 | glMap.off('move', this._oldMoveHandler) 241 | // FIXME 242 | // Moveend may be triggered by centerAndZoom method when creating coordSys next time 243 | // glMap.removeEventListener('moveend', this._oldMoveHandler) 244 | glMap.off('zoomend', this._oldZoomEndHandler) 245 | glMap.on('move', moveHandler) 246 | // glMap.addEventListener('moveend', moveHandler) 247 | glMap.on('zoomend', zoomEndHandler) 248 | 249 | this._oldMoveHandler = moveHandler 250 | this._oldZoomEndHandler = zoomEndHandler 251 | 252 | var roam = GLMapModel.get('roam') 253 | if (roam && roam !== 'scale') { 254 | // todo 允许拖拽 255 | }else { 256 | // todo 不允许拖拽 257 | } 258 | if (roam && roam !== 'move') { 259 | // todo 允许移动 260 | }else { 261 | // todo 不允许允许移动 262 | } 263 | 264 | 265 | 266 | rendering = false 267 | } 268 | }) 269 | }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) 270 | 271 | 272 | /***/ }, 273 | /* 6 */ 274 | /***/ function(module, exports) { 275 | 276 | function EchartsLayer(map) { 277 | const mapContainer = map.getCanvasContainer(); 278 | this._container = document.createElement('div'); 279 | this._container.style.width = map.getCanvas().style.width; 280 | this._container.style.height = map.getCanvas().style.height; 281 | this._container.setAttribute('id', 'echarts'); 282 | this._container.setAttribute('class', 'echartMap'); 283 | this._map = map; 284 | mapContainer.appendChild(this._container); 285 | this.chart = echarts.init(this._container); 286 | echarts.glMap = map; 287 | this.resize(); 288 | } 289 | EchartsLayer.prototype.remove = function() { 290 | var _this = this; 291 | this._map._listeners.move.forEach(function(element) { 292 | if (element.name === 'moveHandler') { 293 | _this._map.off('move', element); 294 | } 295 | }); 296 | this._map._listeners.move.forEach(function(element) { 297 | if (element.name === 'zoomEndHandler') { 298 | _this._map.off('zoomend', element); 299 | } 300 | }); 301 | 302 | // this._map.off('move', this._map._listeners.move[1]); 303 | // this._map.off('zoomend', this._map._listeners.moveend[1]); 304 | this.chart.clear(); 305 | if(this._container.parentNode) 306 | this._container.parentNode.removeChild(this._container); 307 | this._map = undefined; 308 | }; 309 | EchartsLayer.prototype.resize = function() { 310 | const me = this; 311 | window.onresize = function() { 312 | me._container.style.width = me._map.getCanvas().style.width; 313 | me._container.style.height = me._map.getCanvas().style.height; 314 | me.chart.resize(); 315 | }; 316 | }; 317 | module.exports = EchartsLayer; 318 | 319 | 320 | /***/ } 321 | /******/ ]) 322 | }); 323 | ; -------------------------------------------------------------------------------- /demo/geo-line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 520 | 521 | 522 | -------------------------------------------------------------------------------- /demo/effectScatter-map.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 913 | 914 | 915 | --------------------------------------------------------------------------------