# 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)

### 如何运行例子
- 首先全局安装一个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
```
- 这样每次修改之后刷新浏览器即可看到最新的修改