效果图
划过散点的时候出现每个三点位置的数据提示
点击具体散点获取展示信息弹框,并为其添加点击事件
注意点:
1 即使是用的vue,也不能使用@click为窗体添加点击事件,需要使用onclick,
(原因:这是因为你的弹窗内容是以字符串的形式插入到 DOM 中的。此时你给它添加的点击事件不会被 Vue 的事件监听系统所识别和处理,因为这是在 Vue 的作用范围之外的。但是,如果你把这个函数挂载到 window 对象上,那么无论在哪个地方调用这个函数,浏览器都能找到并且执行它)。
2 并且在定义了函数后,使用该函数还是会报函数未定义的错误,需要在window下添加该函数,点击时可以在原型链中找到该函数。
3 设置信息窗体,并为信息窗体里的函数添加点击事件。
处理过程:
1 给每一个 infowindow 加上一个类名,然后进行绑定事件,
2 高德地图 infowindow 不会马上就渲染出来,只有点击 marker 之后才会生成
3 所以需要在生成 infowindow 后才能绑定事件
代码实现
<template>
<div>
<div class="top-box">
<Title title="煤矿地理分布图" />
<seachIpt @clickSearch="clickSearch" />
</div>
<div class="map-box" v-loading="loading">
<div class="icon">
<span @click="postMine('container')" class="left-back">返回主地图</span>
<span class="iconfont icon-a-zujian28421" @click="handleFullScreen"></span>
</div>
<div ref="chinaMap" id="container" class="map-content"></div>
<leftMark />
</div>
</div>
<mapDialog v-model:value="show" />
</template>
<script lang="ts" setup>
import AMapLoader from '@amap/amap-jsapi-loader'
import LabelsData from './china'
import Title from '../title.vue'
import leftMark from './left-mark.vue'
import seachIpt from './seachIpt.vue'
import { ElMessage } from 'element-plus'
import { postMineInfo } from '@/api/dashboard/index'
import mapDialog from './mapDialog.vue'
import { useRouter } from 'vue-router'
let show = ref(false)
let infoWindow = ref(null)
const handleFullScreen = () => {
infoWindow.value?.close()
show.value = true
}
//搜索
const clickSearch = (v: string) => {
getMineInfo(v)
}
//获取该煤矿信息
let dataList = ref([])
const getMineInfo = (v: string) => {
infoWindow.value = null
postMineInfo({ mineName: v, region: 1 })
.then((res: any) => {
const { data, success } = res
if (success) {
if (data?.length > 0) {
//构建信息窗体中显示的内容
dataList.value = data[0]
var info = []
info.push(`<div style='font-size: 16px;'>
<div style=' display: flex;align-items: center;justify-content: space-between;margin-bottom:8px ;padding-bottom:4px; border-bottom: 1px solid #eeeeee;'>
<el-tooltip class="box-item" effect="dark" :content="${
data[0].mineName
}" placement="top">
<span class="left-title" style="color: #3076fe; cursor: pointer;" data-id="moreIds" onclick="more(event)">
${data[0].mineName}
</span>
</el-tooltip>
</div>
<div class="content">
<div style='display: flex;line-height: 30px;'>
<span style='text-align: right;width: 129px;color: #707070;'>所属片区: </span>
<span style='width: 206px;color: #262626;'>${
data[0].zmjArea || '--'
}</span>
</div>
<div style='display: flex;line-height: 30px;'>
<span style='text-align: right;width: 129px;color: #707070;'>煤矿位置: </span>
<span style='width: 206px;color: #262626;'>${
data[0].province ||
data[0].city ||
data[0].region ||
data[0].orgAddress
? (data[0].province ? data[0].province : '') +
(data[0].city ? data[0].city : '') +
(data[0].region ? data[0].region : '') +
(data[0].orgAddress ? data[0].orgAddress : '')
: '--'
}</span>
</div>
<div style='display: flex;line-height: 30px;'>
<span style='text-align: right;width: 129px;color: #707070;'>煤矿性质: </span>
<span style='width: 206px;color: #262626;'>${
data[0].mineProperty || '--'
}</span>
</div>
<div style='display: flex;line-height: 30px;'>
<span style='text-align: right;width: 129px;color: #707070;'>核定生产能力: </span>
<span style='width: 206px;color: #262626;'>${
data[0].actualProductCapacity || '--'
}${data[0].actualProductCapacity ? '万吨' : ''}</span>
</div>
<div style='display: flex;line-height: 30px;'>
<span style='text-align: right;width: 129px;color: #707070;'>是否ZMJ客户: </span>
<span style='width: 206px;color: #262626;'>${
data[0].customer === 1 ? '是' : '否'
}</span>
</div>
</div>
</div>`)
infoWindow.value = new AMaps.value.InfoWindow({
anchor: 'top-left',
content: info.join('') //使用默认信息窗体框样式,显示信息内容
})
let amplify = ref(0)
if (data[0].zmjArea !== '国际') {
amplify.value = 10
} else {
amplify.value = 5
}
infoWindow.value.open(map.value, [data[0].longitude, data[0].latitude])
map.value.setZoomAndCenter(amplify.value, [data[0].longitude, data[0].latitude])
} else ElMessage.error('暂未查到该煤矿信息')
} else {
ElMessage.error(res.message)
}
})
.catch((err) => {
console.log(err)
})
}
const chinaMap = ref()
let AMaps = ref(null)
let map = ref(null)
let normalMarker = ref(null)
let labelsLayer = ref(null)
let markers = ref([])
const imgList = ref([
new URL(`@/assets/home/blue-mark.png`, import.meta.url).href,
new URL(`@/assets/home/green-mark.png`, import.meta.url).href
])
onActivated(() => {
postMine('container')
})
const router = useRouter()
const toMineDetails = (val:any ) => {
router.push({
name: 'mineBasicInfoDetail',
params: { model: val?.mineName },
query: { id: val?.mineId, projectName: val?.mineName }
})
}
let loading = ref(false)
//获取煤矿地理坐标
const postMine = (dom: any) => {
loading.value = true
postMineInfo({ region: 1 })
.then((res: any) => {
const { data, success } = res
if (success) {
initMap(data, dom)
} else {
initMap([], dom)
}
})
.catch(() => {
initMap([], dom)
})
.finally(() => {
loading.value = false
})
}
//初始化地图加载
const initMap = (data: any, dom: any) => {
const AMapLoad = ref<any>(AMapLoader)
// map.value && map.value.destroy()
AMapLoad.value
.load({
key: '337c7e7dda33e11839f80aa219f2fc8a', // 申请好的Web端开发者Key,首次调用 load 时必填
// version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [
'AMap.DistrictSearch',
'AMap.DistrictLayer',
'AMap.Map',
'AMap.Polygon',
'AMap.LabelsLayer',
'AMap.LabelMarker',
'AMap.Marker'
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
//重点就是这个
version: '1.0',
plugins: ['misc/PathSimplifier', 'overlay/SimpleMarker'] //SimpleMarker设置自定义图标,PathSimplifier轨迹展示组件
}
})
.then((AMap: any) => {
AMaps.value = AMap
map.value = new AMap.Map(dom, {
layers: [
// disWorld,
],
// resizeEnable: true,
viewMode: '3D',
zIndex: 5,
zoom: 3,
zoomEnable: true, //地图是否可缩放
dragEnable: true, // 地图是否可通过鼠标拖拽平移
rotateEnable: false, // 地图是否可旋转
// mapStyle: 'amap://styles/10f9d1d306dec0990c6048597ab3bfcb',
zooms: [4.3, 20], // 缩放级别范围
center: [105.602725, 37.076636],
defaultCursor: 'pointer', // 地图默认鼠标样式
showLabel: true, // 是否展示地图文字和 POI 信息。
showIndoorMap: false, // 是否自动展示室内地图,默认是 false
features: ['bg', 'building', 'road', 'point']
})
const _window = window as any
nextTick(()=>{
_window.more = (event:any) => {
const e = event.currentTarget
const element = e.getAttribute('data-id')
toMineDetails(dataList.value)
}
})
// DistrictExplorer_fn(AMap) // 下钻
//地图加载完成事件
map.value.on('complete', () => {
var layer = new AMap.LabelsLayer({
// 开启标注避让,默认为开启,v1.4.15 新增属性
collision: false,
// 开启标注淡入动画,默认为开启,v1.4.15 新增属性
animation: false
})
for (var i = 0; i < LabelsData.length; i++) {
LabelsData[i].text.style = {
fillColor: '#777c82'
}
var labelsMarker = new AMap.LabelMarker(LabelsData[i])
layer.add(labelsMarker) // 省份文字
}
map.value.add(layer)
markers_fn(data, AMap) // 散点
})
map.value.on('click', (e: any) => {
map.value.clearInfoWindow()
})
})
.catch((e: any) => {
console.error(e) //加载错误提示
})
.finally(() => {
loading.value = false
})
}
//散点标记
const markers_fn = (data: any, AMap: any) => {
normalMarker.value = new AMap.Marker({
anchor: 'bottom-center',
offset: [0, 0]
})
labelsLayer.value = new AMap.LabelsLayer({
zooms: [4.3, 20],
zIndex: 200,
// 关闭标注淡入动画
collision: false,
// 设置 allowCollision:true,可以让标注避让用户的标注
allowCollision: false
})
map.value.add(labelsLayer.value)
let icon = {
type: 'image',
anchor: 'bottom-center'
}
markers.value = []
data.forEach((item: any, i: number) => {
let labelMarker = new AMap.LabelMarker({
title: `${item.mineName}-${item.mineId}`,
position: [item.longitude, item.latitude],
zIndex: item.customer === 1 ? 20 : 16,
icon: {
image: item.customer === 1 ? imgList.value[0] : imgList.value[1],
...icon
}
})
markers.value.push(labelMarker)
labelMarker.on('mouseover', function (e: any) {
let strArr = e.data.data.name.split('-')
let position = e.data.data && e.data.data.position
let pixel = e.pixel
normalMarker.value.setContent(
`<div class="amap-info-window" style="top:${pixel.y}px;left:${pixel.x}px;">
${strArr[0]}
<div class="amap-info-sharp"></div>
</div>`
)
normalMarker.value.setPosition(position)
map.value.add(normalMarker.value)
})
labelMarker.on('mouseout', function () {
map.value.remove(normalMarker.value)
})
labelMarker.on('click', function (e: any) {
let strArr = e.data.data.name.split('-')
getMineInfo(strArr[0])
})
})
labelsLayer.value.add(markers.value)
}
</script>
<style scoped lang="scss">
@import './map.scss';
</style>