### 地图组件 ly-map

<hr>

### 1 坐标系说明

#### 默认坐标系

```
天地图为WGS84坐标系，如果当前使用的是百度坐标（BD09）、火星坐标（GCJ02）
则需要转化后使用，推荐使用coord-transform工具转换
```

#### 转换工具安装

```
// npm
npm install @isvend/coord-transform

// pnpm
pnpm add @isvend/coord-transform
```

#### 坐标转换

```javascript
import {
    transformWGS84ToBD09,
    transformBD09ToGCJ02,
    transformBD09ToWGS84,
    transformGCJ02ToWGS84,
    transformWGS84ToGCJ02,
} from "@isvend/coord-transform";

const lng = 116.404;
const lat = 39.915;

console.log("WGS84 to GCJ02", transformWGS84ToGCJ02(lng, lat));
console.log("GCJ02 to WGS84", transformGCJ02ToWGS84(lng, lat));

console.log("WGS84 to BD09", transformWGS84ToBD09(lng, lat));
console.log("BD09 to WGS84", transformBD09ToWGS84(lng, lat));

console.log("BD09 to GCJ02", transformBD09ToGCJ02(lng, lat));
console.log("GCJ02 to BD09", transformBD09ToGCJ02(lng, lat));
```

<hr>

### 2 初始化

默认填充父布局

```vue

<ly-map ref="map" map-key="天地图key"/>
```

<hr>

### 3 插件说明

##### 属性

| 参数                 |    类型     | 说明                                |
|:-------------------|:---------:|:----------------------------------|
| `mapKey`           | `String`  | 天地图官网申请的key,必填否则地图不能正确出来          |
| `lonlat`           |  `Array`  | 地图初始位置,默认值[111.668097, 40.825417] |
| `zoom`             | `Number`  | 地图初始缩放等级,默认值16                    |
| `showCenterIcon`   | `Boolean` | 是否在地图中间显示图标, 默认值 false不显示         |
| `centerIcon`       | `String`  | 修改默认中间显示图标                        |
| `showLocationIcon` | `Boolean` | 是否在地图右下角显示定位图标, 默认值 false不显示      |

##### 事件

| 事件												| 说明																			|
|:--------------------------------------			|:-------------------------------------------------------						|
| `onLoaded()   `									| 当地图加载完成时																	|
| `onLocation() `									| 点击右下角定位按钮时																|
| `onZoomEnd(lon:number, lat:number, zoom:number) `	| 缩放完成时,并返回中心位置以及当前缩放等级											|
| `onStartDrag(lon:number, lat:number)`				| 当地图开始拖拽时,并返回中心位置													|
| `onEndDrag(lon:number, lat:number) `				| 当地图结束拖拽时,并返回中心位置													|
| `onListen(event:object) `							| 覆盖物事件监听，需要覆盖物属性`click`为`true`可被触发，目前支持点击事件 `event`说明如下	|

##### 覆盖物事件 `Event` 格式说明

| key      |  value   | 说明                                            |
|:---------|:--------:|:----------------------------------------------|
| `type`   | `String` | 事件类型 支持 `click`                               |
| `target` | `Object` | 发生事件的覆盖物option，会原样返回覆盖物的配置格式`Over` 或 `Marker` |

##### 方法

| 方法                                              | 说明                                                                                                              |
|:------------------------------------------------|:----------------------------------------------------------------------------------------------------------------|
| `setCenter(lon:number, lat:number,zoom:Number)` | 将地图的中心点变换到指定的地理坐标，如果同时指定了缩放等级，则同时缩放到指定的等级<br/>参数说明:<br/> `lon`:地图的中心点经度<br/> `lat`:地图的中心点纬度<br/>`zoom`:地图的比例尺级别 |
| `setType(type:Number)  `                        | 设置地图显示类型<br/>参数说明:<br/> `type`:要设置的地图展示类型 0矢量地图 1卫星地图 其它显示矢量地图                                                  |
| `setMarkers(Array<Marker>)   `                  | 将标注添加到地图中，支持多个标注同时添加,标注`Marker`格式见下说明                                                                           |
| `setZoom(zoom:Number)    `                      | 将视图缩放到指定的缩放等级，中心点坐标不变  <br/>参数说明:<br/> `zoom`:地图的比例尺级别                                                          |
| `resize()         `                             | 重置地图展示区域尺寸                                                                                                      |
| `setOption(option:Object)  `                    | 同时设置多个属性，支持中心点、缩放、标注、覆盖物<br/>参数说明:<br/> `Object`格式见下说明                                                          |
| `addOvers(overs:Array<Over>)  `                 | 添加覆盖物，同时设置多个（会在现有的基础上添加）<br/>参数说明:<br/> `Over`格式见下说明                                                            |
| `setOvers(overs:Array<Over>)  `                 | 设置覆盖物，同时设置多个（清除现有同类型的，重新添加）<br/>参数说明:<br/> `Over`格式见下说明                                                         |
| `clearOvers(type:String)  `                     | 清除指定的覆盖物类型，不指定则清除所有<br/>参数说明:<br/> type=`circle` 或 `polyline` 或 `polygon` 或 `rect` 或 `label` 或 `infowindow`     |
| `removeOvers(prop, value)  `                    | 移除指定属性和值的覆盖物，匹配创建覆盖物时的prop和value <br/>参数说明:<br/> `prop`:覆盖物属性 <br/> `value`:覆盖物属性对应的值                                                         |
| `setEnable(option:Object)  `                    | 设置开启或者禁用的地图操作 支持拖拽、双击缩放、双指缩放、惯性拖拽  <br/> `Option`格式见下说明                                                         |


##### 标注 `Marker` 格式说明

| key		      |  value	   | 说明											                 |
|:-----------|:---------:|:------------------------------|
| `icon`	    | `String`	 | 标注显示图标的路径,支持网络图片					         |
| `width`	   | `Number`	 | 标注图标宽度，注意：不设置icon时无效				      |
| `height`	  | `Number`	 | 标注图标高度，注意：不设置icon时无效				      |
| `lon `	    | `Number`	 | 标注显示的位置经度								             |
| `lat `	    | `Number`	 | 标注显示的位置纬度								             |
| `offsetX`	 | `Number`	 | 标注图标相对左上角水平偏移	，注意：不设置icon时无效	 |
| `offsetY`	 | `Number`	 | 标注图标相对左上角垂直偏移	，注意：不设置icon时无效	 |

##### 覆盖物 `Over`格式说明

| key				|       value			| 说明																															|
|:---------------	|:------------------:	|:-------------------------------------------------------------------------														|
| `type`			|      `String`			| 覆盖物类型 支持 `circle` `polyline` `polygon` `rect` `label` `infowindow` `polylineArrow` `cardinalCurve` `cardinalCurveArrow`	|
| `color`			|      `String`			| 边线颜色																														|
| `weight`			|      `Number`			| 边线的宽度，以像素为单位																											|
| `opacity `		|      `Number`			| 边线的透明度（范围0-1 之间）																										|
| `fillColor `		|      `String`			| 填充颜色。当参数为空时，折线覆盖物将没有填充效果																						|
| `fillOpacity`		|      `Number`			| 填充的透明度（范围0-1 之间）。																										|
| `lineStyle`		|      `String`			| 边线的样式（`solid`或`dashed`）注意：当`polylineArrow` `cardinalCurve` `cardinalCurveArrow`时，不生效（天地图缺陷）																							|
| `rad`				|      `Number`			| `type=circle`时有效，圆的半径单位`m`																								|
| `lon `			|      `Number`			| `type=circle`时圆心经纬度坐标；`type=label`文本标注的地理位置；`type=infowindow`弹窗的显示地理位置坐标									|
| `lat `			|      `Number`			| `type=circle`时圆心经纬度坐标；`type=label`文本标注的地理位置；`type=infowindow`弹窗的显示地理位置坐标									|
| `points`			| `Array<[lon,lat]>`	| `type=polygon或polyline`时有效，坐标数组																							|
| `leftTop`			| `Array<[lon,lat]>`	| `type=rect`时有效， 矩形左上角坐标																								|
| `rightBottom`		| `Array<[lon,lat]>`	| `type=rect`时有效， 矩形右下角坐标																								|
| `text`			|      `String`			| `type=label`时有效，显示文本内容；																								|
| `offsetX`			|      `Number`			| `type=label`时有效，显示文本水平偏移；`type=infowindow`时有效，显示弹窗水平偏移														|
| `offsetY`			|      `Number`			| `type=label`时有效，显示文垂直平偏移；`type=infowindow`时有效，显示弹窗垂直偏移														|
| `minWidth`		|      `Number`			| `type=infowindow`时有效，弹出框的最小宽度																							|
| `maxWidth`		|      `Number`			| `type=infowindow`时有效，弹出框的最大宽度																							|
| `maxHeight`		|      `Number`			| `type=infowindow`时有效，设置后，如果内容超过弹出窗口的给定高度则产生一个可以滚动的容器													|
| `autoPan`			|     `Boolean`			| `type=infowindow`时有效，否开启信息窗口打开时地图自动移动（默认关闭）																	|
| `closeButton`		|     `Boolean`			| `type=infowindow`时有效，控制弹出窗口中出现的关闭按钮																				|
| `closeOnClick`	|     `Boolean`			| `type=infowindow`时有效，是否开启点击地图关闭信息窗口（默认关闭）																		|

##### 地图操作禁用配置 `Option` 格式说明

| key               |   value   | 说明                             |
|:------------------|:---------:|:-------------------------------|
| `drag`            | `Boolean` | 地图拖拽 `true`允许 `fale`禁用，默认启用    |
| `doubleClickZoom` | `Boolean` | 地图双击放大`true`允许 `fale`禁用，默认启用   |
| `pinchToZoom`     | `Boolean` | 双指操作缩放  `true`允许 `fale`禁用，默认启用 |
| `inertia `        | `Boolean` | 地图惯性拖拽 `true`允许 `fale`禁用，默认启用  | |

##### 多属性 `Object` 配置说明

```javascript
const option = {
    // 中心点
    center: {lon: 116.391231, lat: 39.907334},
    // 多标注
    markers: [{
        icon: icon,
        width: 24,
        height: 27,
        lon: 116.389231,
        lat: 39.906034,
        offsetX: 12,
        offsetY: 27,
		click: true,  // 开启点击监听
    }],
    // 缩放
    zoom: 16,
    // 地图类型
    type: 1,
    // 覆盖物
    overs: [
        // 添加圆
        {
            type: "circle",
            rad: 100,
            lon: 111.667920,
            lat: 40.828050,
            color: "#0000FF",
            weight: 3,
            opacity: .5,
            fillColor: "#0000FF",
            fillOpacity: .2,
            lineStyle: "solid",
        },
        // 添加折线
        {
            type: "polyline",
            points: [[111.665750, 40.822830], [111.668190, 40.821800], [111.670310, 40.822790]],
            color: "#0000FF",
            weight: 3,
            opacity: .5,
            lineStyle: "solid",
        },
        // 添加多边形
        {
            type: "polygon",
            points: [[111.668160, 40.824850], [111.666640, 40.823950], [111.669570, 40.823990]],
            color: "#0000FF",
            weight: 3,
            opacity: .5,
            lineStyle: "solid",
        },
        // 添加矩形
        {
            type: "rect",
            leftTop: [111.665880, 40.826710],
            rightBottom: [111.670120, 40.825860],
            color: "#0000FF",
            weight: 3,
            opacity: .5,
            lineStyle: "solid",
        },
        // 添加文本
        {
            type: "label",
            lon: 111.668150,
            lat: 40.825330,
            text: "点我打开弹窗",
            offsetX: -60,
            offsetY: 10,
            click: true,
        },
    ],
}
```

```text
注意：目前所有覆盖物都支持click属性，当click=true时，则开启点击监听，默认不开启
```

<hr>

### 4 示例代码

```vue

<template>
	<view class="map-page-wrapper">
		<view class="map-box">
			<ly-map ref="map" :map-key="mapKey" :lonlat="lonlat" :zoom="zoom" :show-center-icon="showCenterIcon"
				:center-icon="centerIcon" :show-location-icon="showLocationIcon" :on-location="location"
				:on-loaded="loaded" :on-start-drag="startDrag" :on-zoom-end="zoomEnd" :on-end-drag="endDrag"
				:on-listen="listen" />
		</view>
		<view class="tool-box">
			<view class="tool" @tap="setType(0)">矢量地图</view>
			<view class="tool" @tap="setType(1)">卫星地图</view>
			<view class="tool" @tap="setMarkers()">设置标注</view>
			<view class="tool" @tap="clearMarkers()">清除标注</view>
			<view class="tool" @tap="setZoom(1)">缩放+</view>
			<view class="tool" @tap="setZoom(-1)">缩放-</view>
			<view class="tool" @tap="setCenter(116.391231,39.907334)">设置位置1</view>
			<view class="tool" @tap="setCenter(111.668097, 40.825417)">设置位置2</view>
			<view class="tool" @tap="setCenterIcon(true)">显示中心图标</view>
			<view class="tool" @tap="setCenterIcon(false)">隐藏中心图标</view>
			<view class="tool" @tap="setLocationIcon(true)">显示定位图标</view>
			<view class="tool" @tap="setLocationIcon(false)">隐藏定位图标</view>
			<view class="tool" @tap="setIcon()">修改中心图标</view>
			<view class="tool" @tap="setOption()">同时设置属性</view>
			<view class="tool" @tap="setOvers()">设置覆盖物</view>
			<view class="tool" @tap="addOvers()">添加覆盖物</view>
			<view class="tool" @tap="clearOvers('rect')">清除矩形覆盖物</view>
			<view class="tool" @tap="clearOvers()">清除所有覆盖物</view>
			<view class="tool" @tap="enable()">启用拖拽/缩放</view>
			<view class="tool" @tap="disable()">禁用拖拽/缩放</view>
			<view class="tool" @tap="openDialog()">打开弹窗</view>
			<view class="tool" @tap="removeOvers()">移除指定属性覆盖物</view>
		</view>
	</view>
</template>
<script>
	import icon1 from '@/static/icon1.png';

	export default {
		data() {
			return {
				// 天地图官网地址 https://oauth.tianditu.gov.cn/
				// key需要自行申请，以下使用测试key
				mapKey: "bcd1064810812bdc35d675d1dba3c23f",
				// 中心位置
				lonlat: [111.668097, 40.825417],
				// 缩放
				zoom: 16,
				// 地图展示类型
				type: 0,
				// 显示中心图标
				showCenterIcon: true,
				// 显示定位图标
				showLocationIcon: true,
				// 不设置使用默认图标
				centerIcon: "",
			};
		},
		onReady() {
			// 绑定组件
			this.map = this.$refs.map;
		},
		methods: {
			location() {
				console.log("点击定位按钮回调");
			},
			loaded() {
				console.log("地图创建完成");
			},
			zoomEnd(lon, lat) {
				console.log("地图缩放完成", lon, lat);
			},
			startDrag(lon, lat) {
				console.log("开始地图拖拽", lon, lat);
			},
			endDrag(lon, lat) {
				console.log("结束地图拖拽", lon, lat);
			},
			listen(e) {
				console.log("覆盖物点击事件", e);
				// 只有点击label可以显示弹窗
				if (e.target.type === "label") {
					this.map.setOvers([{
						type: "infowindow",
						lon: 111.668100,
						lat: 40.825420,
						content: "弹窗",
					}]);
				}
			},
			setZoom(zoom) {
				this.zoom += zoom;
				if (this.zoom <= 10) this.zoom = 10;
				if (this.zoom >= 20) this.zoom = 20;
				this.map.setZoom(this.zoom);
			},
			setType(type) {
				// type 0矢量地图 1卫星地图 其他矢量地图
				this.type = type;
				this.map.setType(this.type);
			},
			setCenter(lon, lat) {
				this.lonlat = [lon, lat];
				this.map.setCenter(lon, lat);
			},
			setMarkers() {
				this.map.setMarkers([{
						lon: 111.666020,
						lat: 40.82740
					},
					{
						lon: 111.667020,
						lat: 40.82740
					},
					{
						lon: 111.665020,
						lat: 40.82740
					},
					{
						lon: 111.669020,
						lat: 40.82740
					},
					{
						lon: 111.670020,
						lat: 40.82740
					},
				]);
			},
			removeOvers() {
				this.map.removeOvers("flag", "my-circle");
			},
			clearMarkers() {
				this.map.setMarkers([]);
			},
			setCenterIcon(show) {
				this.showCenterIcon = show;
			},
			setLocationIcon(show) {
				this.showLocationIcon = show;
			},
			setIcon() {
				// 默认图标和icon切换显示
				this.centerIcon = this.centerIcon ? "" : icon1;
			},
			setOption() {
				// 同时设置多个属性
				this.map.setOption({
					center: {
						lon: 116.391231,
						lat: 39.907334
					},
					markers: [{
							lon: 116.389231,
							lat: 39.906034
						},
						{
							lon: 116.390231,
							lat: 39.906034
						},
						{
							lon: 116.391231,
							lat: 39.906034
						},
						{
							lon: 116.392231,
							lat: 39.906034
						},
						{
							lon: 116.393231,
							lat: 39.906034
						},
					],
					zoom: 16,
					type: 1,
				});
			},
			setOvers() {
				const overs = [{
						type: "circle",
						rad: 100,
						lon: 111.667920,
						lat: 40.828050,
						color: "#0000FF",
						weight: 3,
						opacity: .5,
						fillColor: "#0000FF",
						fillOpacity: .2,
						lineStyle: "solid",
						click: true,
						flag: "my-circle",
					},
					{
						type: "polyline",
						points: [
							[111.665750, 40.822830],
							[111.668190, 40.821800],
							[111.670310, 40.822790]
						],
						color: "#0000FF",
						weight: 3,
						opacity: 1,
						lineStyle: "dashed",
					},
					{
						type: "polylineArrow",
						points: [
							[111.665750, 40.823030],
							[111.668190, 40.822000],
							[111.670310, 40.822990]
						],
						color: "#0000FF",
						weight: 3,
						opacity: 1,
						lineStyle: "dashed",
					},
					{
						type: "cardinalCurve",
						points: [
							[111.665750, 40.823430],
							[111.668190, 40.822400],
							[111.670310, 40.823390]
						],
						color: "#0000FF",
						weight: 3,
						opacity: 1,
						lineStyle: "dashed",
					},
					{
						type: "cardinalCurveArrow",
						points: [
							[111.665750, 40.823730],
							[111.668190, 40.822700],
							[111.670310, 40.823690]
						],
						color: "#0000FF",
						weight: 3,
						opacity: 1,
						lineStyle: "dashed",
					},
					{
						type: "polygon",
						points: [
							[111.668160, 40.824850],
							[111.666640, 40.823950],
							[111.669570, 40.823990]
						],
						color: "#0000FF",
						weight: 3,
						opacity: .5,
						lineStyle: "solid",
					},
					{
						type: "rect",
						leftTop: [111.665880, 40.826710],
						rightBottom: [111.670120, 40.825860],
						color: "#0000FF",
						weight: 3,
						opacity: .5,
						lineStyle: "solid",
					},
					{
						type: "label",
						lon: 111.668150,
						lat: 40.825330,
						text: "点我打开弹窗",
						offsetX: -60,
						offsetY: 10,
						click: true,
					},
				];
				this.map.setOvers(overs);
			},
			addOvers() {
				const overs = [{
					type: "circle",
					rad: 200,
					lon: 111.667920,
					lat: 40.828050,
					color: "#0000FF",
					weight: 3,
					opacity: .5,
					fillColor: "#0000FF",
					fillOpacity: .2,
					lineStyle: "solid",
				}, ];
				this.map.addOvers(overs);
			},
			clearOvers(type) {
				this.map.clearOvers(type);
			},
			enable() {
				this.map.setEnable({
					drag: true,
					doubleClickZoom: true,
					inertia: true,
					pinchToZoom: true,
				});
			},
			disable() {
				this.map.setEnable({
					drag: false,
					doubleClickZoom: false,
					inertia: false,
					pinchToZoom: false,
				});
			},
			openDialog() {
				const content =
					`
					<div style="display:flex; flex-direction: column;align-items: center; font-size:16px;z-index:999999999;">
						<img src='http://lbs.tianditu.gov.cn/images/logo.png' width='100' height='50'/>
						<div style='margin-top:8px;'>天地图组件</div>
						<div style='margin-top:8px;'>内蒙古灵越科技</div>
					</div>
				`;
				this.map.setOvers([{
					type: "infowindow",
					lon: 111.668100,
					lat: 40.825420,
					content: content,
				}]);
			}
		}
	};
</script>
<style lang="scss">
	page {
		height: 100%;
	}

	.map-page-wrapper {
		width: 100%;
		height: 100%;

		.map-box {
			width: 100%;
			height: 100%;
		}

		.tool-box {
			position: absolute;
			// 天地图默认z-index:400 需要大于400
			z-index: 999;
			top: 0;
			left: 0;
			width: 100%;
			border-radius: 8rpx;
			padding: 16rpx;
			display: flex;
			flex-wrap: wrap;
			gap: 16rpx;

			.tool {
				font-size: 28rpx;
				border-radius: 8rpx;
				padding: 12rpx 24rpx;
				background: #ffffff;
				box-shadow: 0 0 6rpx rgba(0, 0, 0, .15);
			}
		}
	}
</style>
```
<hr>

### 5 QA

#### 为什么自定义标注图标在APP上会失效？
```
标注图标支持网络图片以及base64格式图标
```

