# echarts-extension-bingmap **Repository Path**: sailimuhu/echarts-extension-bingmap ## Basic Information - **Project Name**: echarts-extension-bingmap - **Description**: 一个echarts地图的必应地图扩展,这样可以更好的支持多语言,且必应地图的授权比百度地图更友好一些,有一定的免费使用额度。 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-01-24 - **Last Updated**: 2022-03-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 一个ECharts扩展,使得可以在echarts中使用必应地图 This is a Bing Map extension for [ECharts](https://echarts.apache.org/en/index.html) which is used to display visualizations such as [Scatter](https://echarts.apache.org/en/option.html#series-scatter) ## 例子 Refer to [examples/index.html](https://gitee.com/sailimuhu/echarts-extension-bingmap/master/examples/index.html) ![Preview](https://gitee.com/sailimuhu/echarts-extension-bingmap/raw/master/img/bing-map.png) ### 如何运行例子 - 首先全局安装一个webserver ```shell npm install -g webserver ``` - 将项目代码下载到本地 ```shell git clone https://gitee.com/sailimuhu/echarts-extension-bingmap.git ``` - 进入到项目目录,找到examples/index.html,将文件内的bing地图的key替换为自己的key,可以在[这里](http://www.bingmap.cn/guide/db765008-dafe-11e8-a995-d46d6d978bfa?module=doc)注册账号,申请key; - 然后在项目目录下运行 ```shell webserver 3000 . ``` - 在浏览器中输入: http://localhost:3000/examples/index.html 即可看到上图所示界面。 ## 在npm项目中使用该扩展 ### 安装 ```shell npm install echarts-extension-bingmap --save ``` ### Import Import packaged distribution file `echarts-extension-bingmap.min.js` and add Bing Map API script and ECharts script. ```html ``` You can also import this extension by `require` or `import` if you are using `webpack`. ```js require('echarts'); require('echarts-extension-bingmap'); ``` ### Usage This extension can be configured simply like [geo](https://echarts.apache.org/en/option.html#geo). ```js var midnightMapStyle = { "version": "1.0", "settings": { "landColor": "#0B334D" }, "elements": { "mapElement": { "labelColor": "#FFFFFF", "labelOutlineColor": "#000000" }, "political": { "borderStrokeColor": "#144B53", "borderOutlineColor": "#00000000" }, "point": { "iconColor": "#0C4152", "fillColor": "#000000", "strokeColor": "#0C4152" }, "transportation": { "strokeColor": "#000000", "fillColor": "#000000" }, "highway": { "strokeColor": "#158399", "fillColor": "#000000" }, "controlledAccessHighway": { "strokeColor": "#158399", "fillColor": "#000000" }, "arterialRoad": { "strokeColor": "#157399", "fillColor": "#000000" }, "majorRoad": { "strokeColor": "#157399", "fillColor": "#000000" }, "railway": { "strokeColor": "#146474", "fillColor": "#000000" }, "structure": { "fillColor": "#115166" }, "water": { "fillColor": "#021019" }, "area": { "fillColor": "#115166" } } }; option = { // load bingmap component bingmap: { viewOption:{ // initial options of Bing Map // See http://www.bingmap.cn/guide/e0411686-dafe-11e8-aa18-d46d6d978bfa?module=doc for details // initial map center, accepts an array like [lng, lat] or an object like { lng, lat } center: {lng: 108.39, lat: 39.9}, // center: [108.39, 39.9], // initial map zoom zoom: 4, }, mapOption:{ // 地图的自定义样式,demo参考这里: http://www.bingmap.cn/demos/02b0b57e-a3c0-40e0-b8a4-6421d57df9d8?module=demo // 关于customMapStyle的说明参考这里:https://docs.microsoft.com/en-us/bingmaps/articles/custom-map-styles-in-bing-maps?redirectedfrom=MSDN customMapStyle: midnightMapStyle // More initial options... } }, series: [ { type: 'scatter', // use `bingmap` as the coordinate system coordinateSystem: 'bingmap', // data items [[lng, lat, value], [lng, lat, value], ...] data: [[120, 30, 8], [120.1, 30.2, 20]], encode: { // encode the third element of data item as the `value` dimension value: 2, lng: 0, lat: 1 } } ] }; function loadMapScenario() { console.log('loadMapScenario called') // initialize chart var chart = echarts.init(document.getElementById("echarts-bing-map")); chart.setOption(option); // Get the instance of Bing Map var bingmap = chart .getModel() .getComponent('bingmap') .getBingMap(); // Add some markers to map var pushpin = new Microsoft.Maps.Pushpin(bingmap.getCenter(), null); bingmap.entities.push(pushpin); } ``` ## 开发说明 该扩展是基于echarts的百度地图扩展修改而来的 ### 参考资料 - [echarts-extension-bmap](https://github.com/apache/echarts/tree/4.9.0/extension-src/bmap) - [echarts-extension-amap](https://www.npmjs.com/package/echarts-extension-amap) - [echarts-extension-gmap](https://www.npmjs.com/package/echarts-extension-gmap) - [bing map api说明](http://www.bingmap.cn/guide/e02d19c6-dafe-11e8-a0a2-d46d6d978bfa?module=doc),特别是[Microsoft.Maps.Map](http://www.bingmap.cn/guide/e02d19c6-dafe-11e8-a0a2-d46d6d978bfa?module=doc), [Microsoft.Maps.CustomOverlay](http://www.bingmap.cn/guide/deb7934c-dafe-11e8-893b-d46d6d978bfa?module=doc),[Microsoft.Maps.Events](http://www.bingmap.cn/guide/df075ca4-dafe-11e8-8fbe-d46d6d978bfa?module=doc)等几个类。 - [百度地图的api说明](https://mapopen-pub-jsapi.bj.bcebos.com/jsapi/reference/jsapi_webgl_1_0.html) - [zrender源码](https://github.com/ecomfe/zrender) ### 基本思路 通过阅读echarts-extension-bmap扩展,发现他的基本思路是这样的,主体还是echarts,通过这个扩展让地图成为整个echarts的底图,让echarts的chart作为地图的一个自定义覆盖层而存在,这个覆盖层中的chart元素可以根据地图的经纬度、缩放层级而产生联动。 ### 源码解读 百度地图扩展的思路是,在创建坐标系的时候,通过echarts的api可以获取到整个echarts的根元素,然后创建一个dom元素作为该echarts根元素的子节点,并使用该dom元素来创建地图,然后获取echart视图层的dom元素,基于该元素创建一个Overlay层,添加到地图的图层列表内,这样就实现了echarts与地图的关联。 至于echarts元素要跟随地图的缩放和拖拽而联动,则要依赖于坐标系内的`dataToPoint`和`pointToData`两个函数来实现经纬度与像素的互相转换。 ### 移植的步骤 - 首先把百度[地图扩展的源码](https://github.com/apache/echarts/tree/4.9.0/extension-src/bmap)复制过来 - 确定名字叫做BingMap,在echarts中的坐标系名称为`bingmap` - 修改文件名为 `BingMapCoordSys`, `BingMapModel`, `BingMapView` - 将文件内所有`BMap`改为`BingMap`,所有 `bmap`改为`bingmap` - 使用Bing地图的api替换百度地图的api,主要有几点: - 创建地图 `Microsoft.Maps.Map` - 经纬度 `Microsoft.Maps.Location` - 像素点 `Microsoft.Maps.Point` - 经纬度转换为像素,使用 `Microsoft.Maps.Map`类的 `tryLocationToPixel`方法,这里注意第二个参数要使用`Microsoft.Maps.PixelReference.control` - 像素转换为经纬度,使用 `Microsoft.Maps.Map`类的`tryPixelToLocation`方法; - 创建Overlay层,这里使用了BingMap的 `CustomOverlay`类,这里的思路是拿到echarts的viewPortRoot的dom元素,将他和CustomOverlay对象关联,创建了一个echarts的自定义层,然后添加到地图的layers列表内; - 这里有个插曲,就是添加的CustomOverlay,通过bingmap.layers.insert()添加到地图的图层之后,无法响应mousemove, mousedown之类的事件,而如果创建CustomOverlay时将`beneathLabels`参数设置为false,则又会导致地图无法响应鼠标事件,所以最终的解决方法是,还是把`beneathLabels`参数设置为true,让他在地图的label层的下方,然后捕捉地图的鼠标事件,在通过dom的dispatchEvent方法将他发送给echarts,这样echarts组件就可以响应相关的鼠标事件了,具体实现请查看`BingMapCoordSys.js`文件。 - 让该扩展支持设置地图参数,由于地图有支持mapOption和viewOption两种参数,所以我在扩展的参数中也提供了mapOption和viewOption两个参数; - 实现地图的自定义样式,Bing地图的mapOption支持了一个叫做 [CustomMapStyle](https://docs.microsoft.com/en-us/bingmaps/articles/custom-map-styles-in-bing-maps?redirectedfrom=MSDN)的参数,可以自定义样式,我只要在创建好地图之后,把用户传进来的mapOption通过setMapOption方法设置给地图即可。 ### 开发过程中的几个关键点 - 通过看zrender源码发现了painter.getViewportRoot()其实是一个dom元素; - 想通了Overlay的作用是吧echarts变成一个自定义层; - 学会了用dispatchEvent来转发事件; - 在用`tryLocationToPixel`是发现散点图位置不对,然后看文档发现有个`Microsoft.Maps.PixelReference.control`参数。 ## 如何调试 开两个cmd - 开一个webserver来实时查看 ```shell npm install -g webserver webserver run 3000 . ``` 然后在浏览器中打开 http://localhost:3000/examples/index.html - 开始调试 ```shell npm run watch ``` - 这样每次修改之后刷新浏览器即可看到最新的修改