snowy/snowy-admin-web/src/components/Map/gaodeMap/index.vue

370 lines
8.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="gaodeMap" :style="{ height: `${height}px` }">
<div :id="`container-${mid}`" style="width: 100%; height: 100%">地图资源加载中...</div>
</div>
</template>
<!--AMap官网https://lbs.amap.com/api/javascript-api-v2/summary-->
<script setup name="GaodeMap">
import { onMounted, onUnmounted, shallowRef } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
const props = defineProps({
mid: {
type: Number,
default: new Date().getTime()
},
height: {
type: Number,
default: 800
},
apiKey: {
type: String,
required: true
},
center: {
type: Array
},
plugins: {
type: Array,
// eslint-disable-next-line vue/require-valid-default-prop
default: ['AMap.ToolBar', 'AMap.Scale', 'AMap.HawkEye', 'AMap.MapType', 'AMap.Geolocation', 'AMap.MarkerCluster']
},
viewMode: {
type: String,
default: '3D',
validator(value) {
return ['2D', '3D'].includes(value)
}
},
zoom: {
type: Number,
default: 12
},
pitch: {
type: Number,
default: 50
},
mapStyle: {
type: String,
default: 'normal',
validator(value) {
return ['normal', 'macaron', 'dark', 'fresh', 'grey'].includes(value)
}
},
markerCluster: {
type: Boolean,
default: true
}
})
const emits = defineEmits(['complete', 'markerClick'])
const gaodeMap = shallowRef(null)
const gaodeMapMarkerArr = ref([])
const gaodeMapInfoWindowObj = ref({})
const init = () => {
AMapLoader.load({
key: props.apiKey,
version: '2.0',
plugins: props.plugins,
AMapUI: {
version: '1.1',
plugins: ['overlay/SimpleMarker', 'overlay/AwesomeMarker']
}
})
.then(() => {
initMap()
})
.catch((e) => {
console.error(e)
})
}
// 初始化 地图
const initMap = () => {
gaodeMap.value = new AMap.Map(`container-${props.mid}`, {
viewMode: props.viewMode,
zoom: props.zoom,
// 地图俯仰角度
pitch: props.pitch,
mapStyle: `amap://styles/${props.mapStyle}`
})
// 中心点
if (props.center) {
gaodeMap.value.setCenter(props.center)
}
// 控件
props.plugins.length > 0 && initControlPlugin()
// 地图初始化完成
gaodeMap.value.on('complete', () => {
emits('complete')
})
}
// 初始化 控制控件
const initControlPlugin = () => {
// 工具条,控制地图的缩放、平移等
props.plugins.includes('AMap.ToolBar') && gaodeMap.value.addControl(new AMap.ToolBar({}))
// 比例尺
props.plugins.includes('AMap.Scale') && gaodeMap.value.addControl(new AMap.Scale())
// 鹰眼,显示缩略图
props.plugins.includes('AMap.HawkEye') && gaodeMap.value.addControl(new AMap.HawkEye({ isOpen: true }))
// 图层切换
props.plugins.includes('AMap.MapType') && gaodeMap.value.addControl(new AMap.MapType({}))
// 定位
props.plugins.includes('AMap.Geolocation') && gaodeMap.value.addControl(new AMap.Geolocation({}))
}
// 渲染 点标记
const renderMarker = (dataArr) => {
dataArr.forEach((d) => {
const marker = new AMap.Marker({
map: gaodeMap.value,
position: d.position,
// 鼠标滑过点标记时的文字提示
title: d.title,
// 显示内容content有效时icon属性将被覆盖
content: d.content,
// 图标
icon: d.icon ? d.icon : null,
// 文本标注
label: d.label
})
marker.on('click', () => {
emits('markerClick', d.position)
})
gaodeMapMarkerArr.value.push(marker)
})
setFitView()
}
// 渲染 圆点标记
const renderCircleMarker = (dataArr) => {
dataArr.forEach((d) => {
const marker = new AMap.CircleMarker({
map: gaodeMap.value,
// 圆心位置
center: d.position,
// 圆点半径
radius: d.radius ? d.radius : 20,
// 线条颜色
strokeColor: d.strokeColor ? d.strokeColor : '#006600',
// 轮廓线透明度
strokeOpacity: 0.5,
// 轮廓线宽度
strokeWeight: 2,
// 填充颜色
fillColor: d.fillColor ? d.fillColor : '#006600',
// 填充透明度
fillOpacity: 0.5,
cursor: 'pointer'
})
marker.on('click', () => {
emits('markerClick', d.position)
})
gaodeMapMarkerArr.value.push(marker)
})
setFitView()
}
// 渲染 简单点标记
const renderSimpleMarker = (dataArr, theme = 'default') => {
dataArr.forEach((d) => {
const marker = new AMapUI.SimpleMarker({
map: gaodeMap.value,
position: d.position,
// 前景文字
iconLabel: {
// 文本
innerHTML: d.label,
// 字体的样式,比如颜色,大小等
style: d.labelStyle
? d.labelStyle
: {
color: '#333',
fontSize: '12px'
}
},
// 图标主题defaultfreshnumv1numv2
iconTheme: theme,
// 背景图标样式
iconStyle: d.style
})
marker.on('click', () => {
emits('markerClick', d.position)
})
gaodeMapMarkerArr.value.push(marker)
})
setFitView()
}
// 渲染 字体点标记
const renderAwesomeMarker = (dataArr) => {
dataArr.forEach((d) => {
const marker = new AMapUI.AwesomeMarker({
map: gaodeMap.value,
position: d.position,
// 图标参见http://fontawesome.io/icons/
awesomeIcon: d.awesomeIcon,
// 字体的样式,比如颜色,大小等
iconLabel: {
style: d.labelStyle
? d.labelStyle
: {
color: '#333',
fontSize: '12px'
}
},
// 背景图标的样式
iconStyle: d.style
})
marker.on('click', () => {
emits('markerClick', d.position)
})
gaodeMapMarkerArr.value.push(marker)
})
setFitView()
}
// 设置 视图级别
const setFitView = () => {
// 点聚合
props.markerCluster && new AMap.MarkerCluster(gaodeMap.value, gaodeMapMarkerArr.value)
// 根据地图上添加的覆盖物分布情况,自动缩放地图到合适的视野级别
gaodeMap.value.setFitView(gaodeMapMarkerArr.value)
}
// 渲染 线
const renderPolyline = (dataArr, option = {}) => {
const path = []
dataArr.forEach((d) => {
path.push(new AMap.LngLat(d.position[0], d.position[1]))
})
const polyline = new AMap.Polyline({
path: path,
strokeColor: option.strokeColor || 'blue',
strokeWeight: option.strokeWeight || 2,
strokeOpacity: option.strokeOpacity || 0.5,
isOutline: option.isOutline || false,
borderWeight: option.borderWeight || 1,
// 折线拐点连接处样式
lineJoin: 'round'
})
gaodeMap.value.add(polyline)
gaodeMap.value.setFitView([polyline])
}
// 渲染 圆
const renderCircle = (position, radius, option) => {
const circle = new AMap.Circle({
center: new AMap.LngLat(position[0], position[1]),
radius: radius,
strokeColor: option.strokeColor || 'blue',
strokeWeight: option.strokeWeight || 2,
strokeOpacity: option.strokeOpacity || 0.5,
fillColor: option.fillColor || 'blue',
fillOpacity: option.fillOpacity || 0.5,
strokeStyle: 'solid'
})
gaodeMap.value.add(circle)
gaodeMap.value.setFitView([circle])
}
// 渲染 面
const renderPolygon = (dataArr, option = {}) => {
const path = []
dataArr.forEach((d) => {
path.push(new AMap.LngLat(d.position[0], d.position[1]))
})
const polygon = new AMap.Polygon({
path: path,
strokeColor: option.strokeColor || 'blue',
strokeWeight: option.strokeWeight || 2,
strokeOpacity: option.strokeOpacity || 0.5,
fillColor: option.fillColor || 'blue',
fillOpacity: option.fillOpacity || 0.5,
strokeStyle: 'solid'
})
gaodeMap.value.add(polygon)
gaodeMap.value.setFitView([polygon])
}
// 渲染 信息窗体
const renderInfoWindow = (dataArr) => {
dataArr.forEach((d) => {
gaodeMapInfoWindowObj.value[d.position] = new AMap.InfoWindow({
// 显示内容
content: d.content.join('<br>'),
// 位置偏移量
offset: new AMap.Pixel(0, -20),
// 点击地图后关闭信息窗体
closeWhenClickMap: true
})
})
}
// 打开 信息窗体
const openInfoWindow = (position) => {
const infoWindow = gaodeMapInfoWindowObj.value[position]
if (infoWindow) {
infoWindow.open(gaodeMap.value, position)
}
}
// 清理 覆盖物
const clearOverlay = () => {
gaodeMap.value.clearMap()
}
onMounted(() => {
init()
})
onUnmounted(() => {
gaodeMap.value && gaodeMap.value.destroy()
})
defineExpose({
renderMarker,
renderCircleMarker,
renderSimpleMarker,
renderAwesomeMarker,
renderPolyline,
renderCircle,
renderPolygon,
renderInfoWindow,
openInfoWindow,
clearOverlay
})
</script>
<style lang="less">
.gaodeMap {
padding: 0;
margin: 0;
width: 100%;
input[type='radio'] {
-webkit-appearance: radio;
}
input[type='checkbox'] {
-webkit-appearance: checkbox;
}
}
</style>