腾讯的地图polygon.getBounds().contains
方法有BUG,点位不在区域内部也会返回true
,需要自定义一套算法,核心算法如下:
核心算法:
function isPointInsidePolygon(point, vertices) {
const x = point[0], y = point[1];
let inside = false;
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
const xi = vertices[i][0], yi = vertices[i][1];
const xj = vertices[j][0], yj = vertices[j][1];
const intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
console.log(inside)
return inside;
}
以上,定义了2个数组,第一个数组是单个点位坐标,第二个数组是区域坐标集合。
全部代码如下:有一些变量需要自行变更一下,
<script>
// 创建地图容器
var mapContainer = document.getElementById('mapContainer');
var emapdata = JSON.parse('[{"lat":26.07953876638003,"lng":119.37317170117186},{"lat":22.84004277988032,"lng":115.38782013867186},{"lat":22.799537101140757,"lng":110.47961701367186},{"lat":27.351970759039688,"lng":108.01867951367186},{"lat":29.34039231723766,"lng":112.06164826367186},{"lat":29.517413502747424,"lng":103.91357697460938},{"lat":34.16760239879295,"lng":101.56628693554687},{"lat":32.524920428780476,"lng":117.08655060742188},{"lat":30.8987961595119,"lng":120.30969513867186},{"lat":28.339548154213812,"lng":120.82336701367186}]'); // 地图
var jsonIconPath0 = emapdata[0];
console.log(emapdata);
var initCenter = new qq.maps.LatLng(jsonIconPath0.lat, jsonIconPath0.lng);
// 初始化地图
var map = new qq.maps.Map(mapContainer, {
center: initCenter,
zoom: 8
});
// 多边形
var polygon_emap = new qq.maps.Polygon({
editable: false, // 开启编辑模式
path: [ ],
map: map,
fillColor: qq.maps.Color.fromHex('#FF6600', 0.4),
strokeColor: qq.maps.Color.fromHex('#FF6600')
});
// 多边形的顶点
var pathNull = [];
for (var i = 0; i < emapdata.length; i++) {
pathNull.push(new qq.maps.LatLng(emapdata[i].lat, emapdata[i].lng));
}
polygon_emap.setPath(pathNull); // 设置多边形
// cut标记点
var marker = new qq.maps.Marker({
position: new qq.maps.LatLng(jsonIconPath0.lat, jsonIconPath0.lng), // 可能有多个标记点
draggable: true,//标注点是否可移动
map: map,
icon: 'http://mike888.top/images/recycle/static/others/emapcut100.png'
});
var polygon_cut = new qq.maps.Polygon({
editable: true, // 开启编辑模式
path: [
new qq.maps.LatLng(24.591394658762617, 118.92959870312498),
new qq.maps.LatLng(24.561421513697372, 117.23758210156248),
new qq.maps.LatLng(25.742271770221414, 117.46280182812498),
new qq.maps.LatLng(25.534274184809814, 118.65494049999998)
],
map: map,
fillColor: qq.maps.Color.fromHex('#0000FF', 0.4),
strokeColor: qq.maps.Color.fromHex('#0000FF')
});
function isPointInsidePolygon(point, vertices) {
const x = point[0], y = point[1];
let inside = false;
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
const xi = vertices[i][0], yi = vertices[i][1];
const xj = vertices[j][0], yj = vertices[j][1];
const intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
console.log(inside)
return inside;
}
// 标注点click事件
qq.maps.event.addListener(marker, 'click', function(event) {
latIcon = event.latLng.getLat(); //纬度
lngIcon = event.latLng.getLng(); //经度
jsonIcon = '{"lat":"' + latIcon + '", "lng":"' + lngIcon + '"}';
var jsonEmapData = polygon_cut.getPath().elems;
// 获取大区域的所有点位, push到数组中pointEmap
var pointEmp = [];
for (var c=0;c<polygon_emap.getPath().elems.length;c++) {
var arrPointEmap = [];
arrPointEmap.push(polygon_emap.getPath().elems[c].lat);
arrPointEmap.push(polygon_emap.getPath().elems[c].lng);
pointEmp.push(arrPointEmap);
}
// 小区域的单个点位,循环判断是否在大区域内部
for (var j=0;j<polygon_cut.getPath().elems.length;j++) {
var arrPoint = [];
arrPoint.push(polygon_cut.getPath().elems[j].lat);
arrPoint.push(polygon_cut.getPath().elems[j].lng);
isPointInsidePolygon(arrPoint, pointEmp)
}
document.getElementById('iconpath').value = jsonIcon;
document.getElementById('emapdata').value = jsonEmapData;
});
</script>