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

345 lines
8.3 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="baiduMap" :style="{ height: `${height}px` }">
<div :id="`container-${mid}`" class="xn-wh">地图资源加载中...</div>
</div>
</template>
<!--BMapGL官网https://lbsyun.baidu.com/index.php?title=jspopularGL-->
<script setup name="baiduMap">
import { onMounted, onUnmounted, shallowRef } from 'vue'
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: ['BMap.ScaleControl', 'BMap.ZoomControl', 'BMap.LocationControl', 'BMap.NavigationControl3D']
},
viewMode: {
type: String,
default: '3D',
validator(value) {
return ['2D', '3D'].includes(value)
}
},
rotationAngle: {
type: Number,
default: 60
},
tiltAngle: {
type: Number,
default: 70
},
zoom: {
type: Number,
default: 12
},
mapStyle: {
type: String
}
})
const emits = defineEmits(['complete', 'markerClick'])
const baiduMap = shallowRef(null)
const baiduMapPointArr = ref([])
const baiduMapInfoWindowObj = ref({})
const init = () => {
// 创建script脚本 引入api
const script = document.createElement('script')
script.src = `https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=${props.apiKey}&callback=initMap`
// 加入head 加载api
const head = document.getElementsByTagName('head')[0]
head.appendChild(script)
}
// 初始化 地图
window.initMap = () => {
baiduMap.value = new BMapGL.Map(`container-${props.mid}`)
// 滚轮放大缩小
baiduMap.value.enableScrollWheelZoom(true)
// 地图样式:个性化地图
if (props.mapStyle) {
baiduMap.value.setMapStyleV2(props.mapStyle)
}
// 控件
props.plugins.length > 0 && initControlPlugin()
// 中心点
if (props.center) {
setFitView(new BMapGL.Point(props.center[0], props.center[1]))
// 地图初始化完成
emits('complete')
} else {
// 浏览器定位
new BMapGL.Geolocation().getCurrentPosition((r) => {
if (r) {
setFitView(new BMapGL.Point(r.longitude, r.latitude))
} else {
setFitView()
}
// 地图初始化完成
emits('complete')
})
}
}
// 初始化 控制控件
const initControlPlugin = () => {
// 比例尺
props.plugins.includes('BMap.ScaleControl') && baiduMap.value.addControl(new BMapGL.ScaleControl())
// 缩放
props.plugins.includes('BMap.ZoomControl') && baiduMap.value.addControl(new BMapGL.ZoomControl())
// 定位
props.plugins.includes('BMap.LocationControl') && baiduMap.value.addControl(new BMapGL.LocationControl())
// 3D控件
props.plugins.includes('BMap.NavigationControl3D') && baiduMap.value.addControl(new BMapGL.NavigationControl3D())
}
// 渲染 点标记
const renderMarker = (dataArr) => {
dataArr.forEach((d) => {
const point = new BMapGL.Point(d.position[0], d.position[1])
const marker = new BMapGL.Marker(
// 坐标
point,
{
// 鼠标滑过点标记时的文字提示
title: d.title
}
)
marker.addEventListener('click', () => {
emits('markerClick', d.position)
})
baiduMap.value.addOverlay(marker)
baiduMapPointArr.value.push(point)
})
setFitView()
}
// 渲染 图标标记
const renderIconMarker = (dataArr) => {
dataArr.forEach((d) => {
const point = new BMapGL.Point(d.position[0], d.position[1])
const marker = new BMapGL.Marker(
// 坐标
point,
{
// 鼠标滑过点标记时的文字提示
title: d.title,
// 图标对象
icon: new BMapGL.Icon(d.img, new BMapGL.Size(d.imgWidth ? d.imgWidth : 40, d.imgHeight ? d.imgHeight : 40))
}
)
marker.addEventListener('click', () => {
emits('markerClick', d.position)
})
baiduMap.value.addOverlay(marker)
baiduMapPointArr.value.push(point)
})
setFitView()
}
// 渲染 3D圆点标记
const render3DCircleMarker = (dataArr) => {
dataArr.forEach((d) => {
const point = new BMapGL.Point(d.position[0], d.position[1])
const marker = new BMapGL.Marker3D(
// 坐标
point,
// 高度默认8000
d.height ? d.height : 8000,
// 自定义样式
{
// 大小默认50
size: d.size ? d.size : 50,
// 形状,默认圆形
shape: 'BMAP_SHAPE_CIRCLE',
// 填充颜色
fillColor: d.fillColor ? d.fillColor : '#006600',
// 填充透明度
fillOpacity: 0.5
}
)
marker.addEventListener('click', () => {
emits('markerClick', d.position)
})
baiduMap.value.addOverlay(marker)
baiduMapPointArr.value.push(point)
})
setFitView()
}
// 渲染 3D图标标记
const render3DIconMarker = (dataArr) => {
dataArr.forEach((d) => {
const point = new BMapGL.Point(d.position[0], d.position[1])
const marker = new BMapGL.Marker3D(
// 坐标
point,
// 高度默认8000
d.height ? d.height : 8000,
// 自定义样式
{
// 大小默认50
size: d.size ? d.size : 50,
// 图标对象
icon: new BMapGL.Icon(d.img, new BMapGL.Size(d.imgWidth ? d.imgWidth : 40, d.imgHeight ? d.imgHeight : 40))
}
)
marker.addEventListener('click', () => {
emits('markerClick', d.position)
})
baiduMap.value.addOverlay(marker)
baiduMapPointArr.value.push(point)
})
setFitView()
}
// 渲染 线
const renderPolyline = (dataArr, option = {}) => {
dataArr.forEach((d) => {
baiduMapPointArr.value.push(new BMapGL.Point(d.position[0], d.position[1]))
})
const polyline = new BMapGL.Polyline(baiduMapPointArr.value, {
stokeStyle: 'solid',
strokeColor: option.strokeColor || 'blue',
strokeWeight: option.strokeWeight || 2,
strokeOpacity: option.strokeOpacity || 0.5
})
baiduMap.value.addOverlay(polyline)
setFitView()
}
// 渲染 圆
const renderCircle = (position, radius, option = {}) => {
const point = new BMapGL.Point(position[0], position[1])
baiduMapPointArr.value.push(point)
const circle = new BMapGL.Circle(point, radius ? radius : 500, {
strokeColor: option.strokeColor || 'blue',
strokeWeight: option.strokeWeight || 2,
strokeOpacity: option.strokeOpacity || 0.5
})
baiduMap.value.addOverlay(circle)
setFitView()
}
// 渲染 面
const renderPolygon = (dataArr, option = {}) => {
dataArr.forEach((d) => {
baiduMapPointArr.value.push(new BMapGL.Point(d.position[0], d.position[1]))
})
const polygon = new BMapGL.Polygon(baiduMapPointArr.value, {
stokeStyle: 'solid',
strokeColor: option.strokeColor || 'blue',
strokeWeight: option.strokeWeight || 2,
strokeOpacity: option.strokeOpacity || 0.5,
fillColor: option.fillColor || 'blue',
fllOpacity: option.fllOpacity || 0.5
})
baiduMap.value.addOverlay(polygon)
setFitView()
}
// 设置 视图级别
const setFitView = (point) => {
if (!point) {
const viewPort = baiduMap.value.getViewport(baiduMapPointArr.value)
point = new BMapGL.Point(viewPort.center.lng, viewPort.center.lat)
}
baiduMap.value.centerAndZoom(point, props.zoom)
// 3D视图
if (props.viewMode === '3D') {
// 地图旋转角度
baiduMap.value.setHeading(props.rotationAngle)
// 地图倾斜角度
baiduMap.value.setTilt(props.tiltAngle)
}
}
// 渲染 信息窗体
const renderInfoWindow = (dataArr) => {
dataArr.forEach((d) => {
baiduMapInfoWindowObj.value[d.position] = new BMapGL.InfoWindow(d.content.join('<br>'), {
title: d.title,
width: d.width ? d.width : 250,
height: d.height ? d.height : 100
})
})
}
// 打开 信息窗体
const openInfoWindow = (position) => {
const infoWindow = baiduMapInfoWindowObj.value[position]
if (infoWindow) {
baiduMap.value.openInfoWindow(infoWindow, new BMapGL.Point(position[0], position[1]))
}
}
// 清理 覆盖物
const clearOverlay = () => {
baiduMap.value.clearOverlays()
}
onMounted(() => {
init()
})
onUnmounted(() => {
baiduMap.value && baiduMap.value.baseLayerAdded && baiduMap.value.destroy()
})
defineExpose({
renderMarker,
renderIconMarker,
render3DCircleMarker,
render3DIconMarker,
renderPolyline,
renderCircle,
renderPolygon,
renderInfoWindow,
openInfoWindow,
clearOverlay
})
</script>
<style lang="less">
.xn-wh {
width: 100%;
height: 100%
}
.baiduMap {
padding: 0;
margin: 0;
width: 100%;
}
</style>