# MMap 地图

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/mobile/map/freepass)
- 平台：移动端
- 维护者：陈佳敏
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[MMap]

## 代码演示

### 基础用法 (详细demo见pc的Map组件)

```jsx
import React from 'react';
import { MMap, AnyObj, MapType } from '@weapp/ui';

export default class Demo extends React.PureComponent<{}> {

  onReady = (mapInstance: any, mapStore: any) => {
    console.log('onReady', mapInstance, mapStore)
  }

  onMapClick = (info: AnyObj, e: any) => {
    console.log('onMapClick', info, e)
  }

  onMapSwitch = (type: MapType, newValue: string, newInfo: AnyObj) => {
    console.log('onMapSwitch', type, newValue, newInfo)
  }

  onSearch = (place: string) => {
    console.log("搜索事件", place);
  }

  onSearchItemClick = (info: any) => { console.log(info) }

  render() {
    return (
      <MMap
        mapId="m_map_basic"
        defaultValue='121.5331491646771,31.086169774670942'
        defaultAddress='上海市闵行区泛微软件大厦' // 如果已经是有位置信息的情况,默认传入。避免经过逆地理位置解析拿到的信息和显示的有偏差
        mapHeight={window.innerHeight} // window.innerHeight：浏览器窗口的视口高度。具体业务根据具体情况传参
        showMaker
        showInfoWindow
        showMapSwitch
        showSearchInput
        showRouting
        onReady={this.onReady}
        onMapClick={this.onMapClick}
        onMapSwitch={this.onMapSwitch}
        onSearch={this.onSearch}
        onSearchItemClick={this.onSearchItemClick}
      />
    );
  }
}
```

### 切路由模式

```jsx
import React from 'react';
import { MMap, AnyObj, MapType, MButton } from '@weapp/ui';

export default class Demo extends React.PureComponent<{}> {

  onReady = (mapInstance: any, mapStore: any) => {
    console.log('onReady', mapInstance, mapStore)
  }

  onMapClick = (info: AnyObj, e: any) => {
    console.log('onMapClick', info, e)
  }

  onSure = (info: AnyObj) => {
    console.log('onSure', info)
  }

  onCancel = (info: AnyObj) => {
    console.log('onCancel', info)
  }

  onMapSwitch = (type: MapType, newValue: string, newInfo: AnyObj) => {
    console.log('onMapSwitch', type, newValue, newInfo)
  }

  render() {
    return (
      <MMap
        mapId="m_map_route"
        defaultValue='121.5331491646771,31.086169774670942'
        defaultAddress='上海市闵行区泛微软件大厦' // 如果已经是有位置信息的情况,默认传入。避免经过逆地理位置解析拿到的信息和显示的有偏差
        isRouteLayout
        showMaker
        showInfoWindow
        showMapSwitch
        showSearchInput
        onReady={this.onReady}
        onMapClick={this.onMapClick}
        onSure={this.onSure} //  点击确定按钮的回调
        onCancel={this.onCancel}  //  点击取消按钮的回调
        onMapSwitch={this.onMapSwitch}
      >
        <MButton>点击选择地址</MButton>
      </MMap>
    );
  }
}
```

## API

Tip

```
1、经纬度说明：
  高德、腾讯用一套经纬度，百度用一套经纬度

2: getCurrentPosition定位说明：
（1）由于Chrome、iOS10等已不再支持非安全域的浏览器定位请求,如果站点不是HTTPS。百度、高德的浏览器定位大概率会失败
（2）浏览器定位失败,会走IP城市定位,IP定位范围比较广,基本定位到当前城市
```

```
三方文档API地址：
1、百度：https://lbsyun.baidu.com/index.php?title=jspopularGL
2、高德：https://lbs.amap.com/api/javascript-api/summary
3、腾讯：https://lbs.qq.com/webApi/javascriptV2
4、谷歌：https://developers.google.com/maps （需要翻墙）
```

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| mapId | 地图 id | string | 是 | '' |
| lngLatType | 经纬度类型 | mapType | 否 | baidu |
| defaultValue | 默认中心位置(lngLat: 精度在前,维度在后,','号分隔),没有则获取当前的位置作为中心位置 | string | 否 | '' |
| value | 默认中心位置受控(lngLat: 精度在前,维度在后,','号分隔),没有则获取当前的位置作为中心位置 | string | 否 | '' |
| defaultAddress | 默认中心位置信息 | string | 否 | '' |
| address | 中心位置信息受控 | string | 否 | '' |
| mapHeight | 地图高度 | number | 否 | 手机端切路由模式默认计算,其他情况默认为 500 |
| mapWidth | 地图宽度 |  | 否 | '' |
| readOnly | 是否只读 | boolean | 否 | false |
| clickToReposition | 点击地图是否重新设置中心位置 | boolean | 否 | true |
| loginFree | 是否是免登场景 | boolean | 否 | false |
| isRouteLayout | 是否为切路由模式 | boolean | 否 | false |
| initGetLocation | 初始化的时候,如果没有传入中心位置,组件内部是否默认获得当前位置 | boolean | 否 | true |
| initMapParams | 地图初始化的参数,例如 { room: 15 } | AnyObj | 否 | {} |
| showMaker | 是否默认显示中心位置的 marker 标记 | boolean | 否 | false |
| showInfoWindow | 是否默认显示中心位置的信息窗口 | boolean | 否 | false |
| showSearchInput | 是否显示关键词搜索框 | boolean | 否 | false |
| customInfoContent | 自定义信息窗口显示 | (info: anyObj) => any | 否 |  |
| buttons | 自定义弹层底部按钮 | MapDialogBtnItem[] | 否 |  |
| onReady | 地图初始化成功后的回调 | (mapInstance: any, mapStore: any) => voi | 否 |  |
| onReadyFaield | 地图初始化失败后的回调 | (msg: string) => voi | 否 |  |
| onMapClick | 地图点击回调 | (info: anyObj, e: any) => void | 否 |  |
| onMapSwitch | 切换地图的回调 | (type: mapType, newValue: string, newInfo: AnyObj) => void | 否 |  |
| onSure | 点击弹窗内确认按钮的回调 | (info: anyObj) => void | 否 |  |
| onCancel | 点击弹窗内取消或删除按钮的回调 | (info: anyObj) => void | 否 |  |
| onSearchItemClick | 关键字检索结果点击的回调 | (info: anyObj, e: any) => void | 否 |  |
| onSearch | 点击搜索按钮的回调 | (keywords: string) => void | 否 |  |
| dialogProps | 弹框参数,继承 Dialog 组件的所有属性 | MDialogProps | 否 |  |
| extraDialogContent | 弹框内额外的自定义 node | React.ReactNode | 否 |  |
| showRouting | 在信息窗口显示导航按钮 | boolean | false | 否 |
### 通过 ref 拿到组件的 store 可调用的方法

| 方法 | 说明 | 类型 |
| --- | --- | --- |
| getInstance | 获取当前的实例 | () => any |
| setCenter | 更改中心位置 | (value: string) => void |
| setZoom | 更改地图级别 | (zoom: number) => void |
| setCenterAndZoom | 更改地图级中心位置和级别 | (value: string,zoom: number) => void |
| paintMarker | 画 marker | (pointList: MapPointType[], otherMaerkderConfig?: AnyObj) => any[] |
| paintPolyline | 画线 | (pointList: MapPointType[], polylineParams: AnyObj) => any |
| paintInfoWindow | 画信息窗口(注意：腾讯地图中如果需要把覆盖物绑定到某个 marker 上,需要 options 传入自己的 position,详见官方文档[https://lbs.qq.com/javascript_v2/doc/infowindowoptions.html]) | (info?: AnyObj, content?: string, options?: AnyObj)) => any |
| paintLabel | 画纯文本标注,按照设置的 marker 配置偏移量 | (position: MapPointType, text: string, marker: any, style?: anyObj, otherLabelConfig?: anyObj) => any |
| paintCircle | 画圆 | (position: MapPointType, radius: number, otherCircleConfig: anyObj) => any |
| removeMarker | 移除 marker | (markers?: any[]) => void |
| removeLabel | 移除 label | (labels?: any[]) => void |
| removeCircle | 移除圆 | (circle?: any) => void |
| removePolyline | 移除线 | (polyLine?: any) => void |
| removeInfoWindow | 移除信息窗口 | (infoWindow?: any) => void |
| removeAllOverlay | 移除所有覆盖物 | () => void |
| destroryMap | 销毁地图 | () => viod |
| addMarkersClickFunc | 给 markers 绑定点击事件 | (markers: any[], clickFunc: ((marker: any, lngLatObj: { lng: number, lat: number }, e: any) => void) => void |
### 通过 MapUtil 可调用的方法 (注意: 所有 MapUtil 中的方法, mapType 为地图类型,传 '' 表示直接读取地图默认配置中的设置; lngLatType 为经纬度类型)

| 方法 | 说明 | 类型 |
| --- | --- | --- |
| getDefaultMapConfig | 获取地图的默认配置(如果获取失败,组件内部会默认抛出错误的提示) | () => `Promise<any>` |
| getCurrentPosition | 获取当前的位置(详细参数说明见下方) | (params: GetPositionQueryParamsType) => `Promise<any>` |
| coordinateConversion | 地图之间的经纬度转换 | (from: mapType, to: mapType, convertList: MapPointType[]) => MapPointType[] |
| reverseGeolocation | 逆地理位置解析 | (mapType: any, location: string) => `Promise<any>` |
| geolocate | 地理位置解析 | (mapType: any, location: string)=> `Promise<any>` |
| getAround | 获取周边位置信息 | (mapType: any, location: string, radius?: number, query?: string, otherParams?: anyObj) => `Promise<any>` |
| getStaticMap | 获取静态地图地址 | (lngLatType: any, location: string, params?: anyObj) => `Promise<any>` |
| placeSearch | 地点联想搜索 | (mapType: any, place: string, city: string, instance: any) => `Promise<any>` |
| getCity | 获取当前城市 | (mapType?: MapType) => `Promise<any>` |
### MapUtil.getCurrentPostion 定位 API GetPositionQueryParamsType对象传参说明

| 参数 | 说明 | 类型 | 默认 |
| --- | --- | --- | --- |
| mapType | 当前地图类型,不知道可不传 | any | '' |
| noNeedAddress | 是否需要返回当前位置信息 | boolean | false |
| getMapLocationWhenSdkFail | 手机端 SDK 定位失败,是否通过地图的 api 定位 | boolean | false |
| showSdkTips | 手机端没有开启定位权限时是否弹出提示框引导用户设置开启定位权限,1:表示弹出提示,0:表示不弹出 | 0 |  |
| sdkReadyParams | weappSDK.customSDK.ready 方法传参 | object | - |
| loginFree | 是否为免登场景 | boolean | false |
| onSDKLocationChanged | 手机端定位 SDK 连续定位返回结果的回调 | (res: any) => void | - |
### MapUtil.getCurrentPostion 定位 API 返回结果说明

| 结果 | 说明 | 类型 |
| --- | --- | --- |
| mapType | 当前地图类型 (通过手机sdk对比和默认地图配置对比后,最终返回的保证有key地图类型) | string |
| location | 当前位置,当前地图类型,对应的经纬度数组 | [lng, lat] |
| baiduLocation | 当前经纬度,统一转换为百度地图坐标系后的经纬度数组（兼容ET老数据,方便业务统一存储数据使用） | [lng, lat] |
| address | 当前的位置 | string |
| city | 当前城市 | string |
| addressInfo | 当前的位置信息对象 | object |
| lng | 当前位置的精度（和最终的地图类型匹配） | string \| number |
| lat | 当前位置的的维度（和最终的地图类型匹配） | string \| number |
| type | 手机端定位sdk返回的地图类型(不一定为最终渲染的地图类型) | string |
```
MapUtil使用：
import { MapUtil } = from 'weapp/ui';
const getDefaultMapConfig = MapUtil.getDefaultMapConfig;
const getCurrentPosition = MapUtil.getCurrentPosition;

getCurrentPosition().then(res => {
  console.log('res',res)
}).catch(err => {
  console.log('err, err)
})

// 如果获取失败,组件内部会默认抛出错误的提示。业务只需要处理成功的情况
getDefaultMapConfig().then(defaultConfig => {
  console.log('defaultConfig', defaultConfig)
})
```

```
getDefaultMapConfig返回数据说明:
{
  isSwitchable: true, // 是否可切换地图
  defaultMap: { // 默认显示的地图
    mapType: 'gaode', // 地图类型
    mapName: 'gaodeMap', // 地图名称
    mapKey: '', // 当前地图的 js key
    mapIosKey: '' // 当前地图的 ios key
    mapAndroidKey: '' // 当前地图的 ios key
    mapServiceKey": '', // 当前地图的 web服务 key
  },
  switchableMaps: [ // 可切换的地图种类
    {
      mapType: 'gaode', // 地图类型
      mapName: 'gaodeMap', // 地图名称
      mapKey: '', // 当前地图的 js key
      mapIosKey: '' // 当前地图的 ios key
      mapAndroidKey: '' // 当前地图的 ios key
      mapServiceKey": '', // 当前地图的 web 服务 key
    },
    {
      mapType: 'baidu', // 地图类型
      mapName: 'baiduMap', // 地图名称
      mapKey: '', // 当前地图的 js key
      mapIosKey: '' // 当前地图的 ios key
      mapAndroidKey: '' // 当前地图的 ios key
      mapServiceKey": '', // 当前地图的 web 服务 key
    },
  ]
}
```
