vue3引入百度地图绘制多边形

发布于:2025-04-17 ⋅ 阅读:(55) ⋅ 点赞:(0)

vue3引入百度地图绘制多边形,可判断点是否在多边形内,

废话不多说,有效全代码如下:

<template>
	<!--mapType="BMAP_SATELLITE_MAP"-->
	<baidu-map
		:center="initPoint"
		:dragging="dragging"
		:scroll-wheel-zoom="true"
		:zoom="20"
		ak="lO11fl3yVyFHrWwVhfCn7oSYRhkCYnOg"
		class="bm-view"
		type="API"
		v="3.0"
		@click="baiDuMapClickPoint"
		@rightclick="baiDuMapRightClick">
		<!-- 缩放 -->
		<bm-navigation :enableGeolocation="true" :showZoomInfo="true" anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
		<!-- 比例尺 -->
		<bm-scale anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-scale>
		<!-- 缩略图 -->
		<bm-overview-map :isOpen="true" anchor="BMAP_ANCHOR_BOTTOM_RIGHT"></bm-overview-map>
		<!-- 全景控件 -->
		<bm-panorama anchor="BMAP_ANCHOR_TOP_LEFT"></bm-panorama>
		<bm-local-search :auto-viewport="true" :keyword="keyword" :location="location"></bm-local-search>

		<bm-polygon :editing="true" :path="polygonPath" :stroke-opacity="0.5" :stroke-weight="2" fill-color="red" fill-opacity=0.3 stroke-color="blue" v @lineupdate="updatePolygonPath"/>
		<bm-polygon v-for="item in polygonPathList" :editing="false" :path="item" :stroke-opacity="0.5" :stroke-weight="2" fill-color="red" fill-opacity=0.3 stroke-color="blue" v @lineupdate="updatePolygonPath"/>

		<bm-marker :dragging="true" :position="markerPosition" animation="BMAP_ANIMATION_BOUNCE">
		</bm-marker>
	</baidu-map>
	<!--<label>关键词:<input v-model="keyword"></label>
	<label>地区:<input v-model="location"></label>-->
	<div class="buttonClass">
		<el-button type="primary" @click="baiDuMapClick">绘制多边形</el-button>
		<el-button type="warning" @click="baiDuMapClickCancel">取消绘制</el-button>
		<el-button type="danger" @click="baiDuMapDel">删除绘制</el-button>
		<el-button type="primary" @click="baiDuMapPoint">标记点</el-button>
		<el-button type="primary" @click="inPolygon">判断标记点是否在多边形内</el-button>
	</div>
</template>
<script setup>
import {ref} from 'vue';
import {
	BaiduMap, BmNavigation, BmScale, BmOverviewMap,
	BmPanorama, BmPolygon, BmLocalSearch, BmMarker, BmLabel,
} from 'vue-baidu-map-3x';

// 初始位置
const initPoint = ref({lng: 117.131236, lat: 36.684359});
const location = ref('济南');
const keyword = ref('天辰路三庆财富');

const polygonPath = ref([]);
const polygonPathList = ref([]);
const dragging = ref(true);
const clickFlag = ref(0);

const baiDuMapClickFlag = ref(false);

const updatePolygonPath = (e) => {
	polygonPath.value = e.target.getPath()
};

const baiDuMapClick = (e) => {
	baiDuMapClickFlag.value = true;
	dragging.value = true;
	polygonPath.value = [];
	clickFlag.value = 1;
}

const baiDuMapClickCancel = (e) => {
	dragging.value = false;
	polygonPathList.value.push(polygonPath.value);
	polygonPath.value = [];
	clickFlag.value = 0;
}

const baiDuMapRightClick = (e) => {
	// console.log(e);
	/*baiDuMapClickFlag.value = !baiDuMapClickFlag.value;
	if (baiDuMapClickFlag.value) {
		dragging.value = true;
		polygonPath.value = [];
		clickFlag.value = 1;
	} else {
		dragging.value = false;
		polygonPathList.value.push(polygonPath.value);
		polygonPath.value = [];
		clickFlag.value = 0;
	}*/
	dragging.value = false;
	polygonPathList.value.push(polygonPath.value);
	polygonPath.value = [];
	clickFlag.value = 0;
};

// 获取点击的点
const baiDuMapClickPoint = (e) => {
	if (clickFlag.value === 2) {
		baiDuMapDrawPoint(e);
	}
	if (clickFlag.value === 1) {
		if (!baiDuMapClickFlag.value) {
			return;
		}
		// console.log(e);
		const {lng, lat} = e.point;
		// console.log(lng, lat);
		polygonPath.value.push(e.point);
	}
};

// 标记点
const markerPosition = ref({});
const baiDuMapPoint = (e) => {
	clickFlag.value = 2;
}
const baiDuMapDrawPoint = (e) => {
	markerPosition.value = e.point;
}

// 删除多边形
const baiDuMapDel = () => {
	polygonPath.value = [];
	polygonPathList.value = [];
	clickFlag.value = 0;
	markerPosition.value = {};
}

const inPolygon = () => {
	isInPolygon(markerPosition.value, polygonPathList.value[0]);
}

// 判断点是否在多边形内(射线法)
const isInPolygon = (pointPath, polygonPath) => {
	const point = new BMap.Point(pointPath.lng, pointPath.lat); // 创建要检查的点
	const polygonPoints = polygonPath.map(pt => new BMap.Point(pt.lng, pt.lat)); // 多边形的顶点数组

	let intersectCount = 0; // 射线与多边形边的交点数

	// 遍历多边形的边
	for (let i = 0; i < polygonPoints.length; i++) {
		const p1 = polygonPoints[i];
		const p2 = polygonPoints[(i + 1) % polygonPoints.length]; // 获取下一个点,循环回到起点

		// 如果点与边的水平线有交点
		if (p1.lat !== p2.lat) {
			if (
				(point.lat > Math.min(p1.lat, p2.lat)) &&
				(point.lat <= Math.max(p1.lat, p2.lat)) &&
				(point.lng <= Math.max(p1.lng, p2.lng))
			) {
				const xInters = (point.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng;
				if (xInters > point.lng) {
					intersectCount++;
				}
			}
		}
	}

	// 如果交点数为奇数,则点在多边形内
	if (intersectCount % 2 === 1) {
		console.log("该点在多边形内");
	} else {
		console.log("该点不在多边形内");
	}
}
</script>
<style scoped>
/* 这里没有清除百度地图API水印 */
.bm-view {
	width: 87vw;
	height: calc(100vh - 61px);
	margin: auto;
}

/* 去掉百度地图logo--begin */

/* 去除水印 */
::v-deep(.BMap_cpyCtrl) {
	display: none;
}

::v-deep(.anchorBL) {
	display: none !important;
}

/* 去掉百度地图logo--end */

.buttonClass {
	position: fixed;
	top: 80px;
	left: 320px;
	z-index: 99999;
}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到