遇到的问题
- 背景:uni-app开发小程序,使用map组件实现地图功能;用户拖拽时需要判断是否在本市内;原先使用本市内所有区域的覆盖物进行判断,拖拽过程取中心点,但如果区域之间存在空隙(江河-如下图),中心点在江中间时,我并没有画这个区域,会判断为不在本市内;所以最终改成直接查本市整体的覆盖物进行判断
- 解决:需要判断位置坐标点是否在多边形内–采用射线法判断
解决
-
实现代码
<!-- .vue页面文件 --> <template> <!-- map组件,此处省略了其他属性配置,核心是在regionchange事件上 --> <map id="map" style="..." :latitude="..." :longitude="..." subkey="你的地图key" :show-location="true" show-scale :markers="[]" :scale="scaleNum" :polyline="..." :circles="..." :polygons="..." @regionchange="regionchange"></map> ... </template> <script> export default { data(){ bordersOfShangHai: [[120.856125, 31.874025],[121.99159, 31.874025],[121.99159, 30.691927],[120.856125, 30.691927]] // 本市边界覆盖物 }, ... methods: { //regionchange:map组件内置函数--视野发生变化时触发 regionchange (e) { var self = this // 用户拖拽时-解析当前位置 if (e.type === 'end' && e.causedBy === 'drag'){ self.getUserPos(e.target.centerLocation) //调用判断是否在本市内的函数 } }, //封装判断是否在本市内的函数 getUserPos(centerLocation) { const self = this if(!centerLocation) return false self.isinSh = self.isInPolygon([centerLocation.longitude,centerLocation.latitude], self.bordersOfShangHai) //bordersOfShangHai四个点是本市最大最小的经纬度,判断是否在本市,经度是否在最大最小内,纬度是否在最大最小纬度内 }, //判断位置坐标是否在多边形内的函数提取--核心实现方法 //具体采用:判断一个点是否在多边形内--射线法 isInPolygon(dot, polygons) { let counter = 0 let i let yinters let p1, p2 let pointCount = polygons.length p1 = polygons[0] // 临界值控制-dot不在polygons中 if(polygons.some(it => it[0] == dot[0] && it[1] == dot[1])) return true for (i = 1; i <= pointCount; i++) { p2 = polygons[i % pointCount] if (dot[0] > Math.min(p1[0], p2[0]) && dot[0] <= Math.max(p1[0], p2[0])) { if (dot[1] <= Math.max(p1[1], p2[1])) { if (p1[0] != p2[0]) { yinters = (dot[0] - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1] if (p1[1] == p2[1] || dot[1] <= yinters) { counter++ } } } } p1 = p2 } return counter % 2 !== 0 } } }
-
射线法原理:一个点向一个方向发送射线,射线与多边形各个边相交的交点如果是奇数说明点在多边形范围内
(图片引自:https://blog.csdn.net/qq_27161673/article/details/52973866)