openlayes 3 点选,圈选,多边形选实现


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014529917/article/details/77504779

   点选、圈选、多边形选择也是地图中比较基础的功能了,只是一直没有需求,最近两天把这个功能从页面到功能完整的做了一遍。我使用的方法是使用ol4的API加一些js算法,这里记录一下。

1、需求

点选:点击一个点,弹出模态框设置半径,设置完成后,在地图上绘制点和半径画的圆,选中圆内的设备,并在搜索结果框中展示这些设备。

圈选:直接绘制一个圈选,选中圆圈内的设备,并在搜索结果框中展示这些设备。

多边形选择:绘制一个多边形,选中多边形内的设备,并在搜索结果框中展示这些设备。

2、步骤(大致):

这里都通过绘制draw完成

点选:设置draw的type为Point,绘制结束后,获取绘制的点坐标,并结合模态框中输入的半径绘制圆,遍历要素图层,并根据算法pointInsideCircle(point, circle, r)判断要素是否在圆圈范围内,筛选出圈内的要素。

圈选:设置type为Circle,绘制结束后,获取绘制的圆,遍历要素图层,再根据算法pointInsideCircle(point, circle, r),筛选出圆内的要素。

多边形选择:设置type为Polygon,绘制结束后,获取绘制的多边形,遍历要素图层,再根据算法insidePolygon(points, testPoint),筛选出多边形范围内的要素。

框选:设置draw的type为Circle,并设置geometryFunctionol.interaction.Draw.createBox(),绘制结束后,获取绘制要素的feature.getExtent(),在根据API中的source.getFeaturesInExtent(extent),获取要素图层中在框内的要素。

注:如果图层内要素过多,可以先获取绘制要素的extent,再根据source.getFeaturesInExtent(extent),获取绘制要素的extent框内的要素,再根据自己的算法筛选出图形范围内的要素。

以圈选为例:

  1. var draw = new ol.interaction.Draw({
  2. source: drawSource,
  3. type:"Circle",
  4. style:drawStyle
  5. });
  6. map.addInteraction(draw);
  7. draw.on('drawend',function(evt){
  8. var polygon = evt.feature.getGeometry();
  9. setTimeout(function(){ //如果不设置延迟,范围内要素选中后自动取消选中,具体原因不知道
  10. var center = polygon.getCenter(),radius = polygon.getRadius(),extent = polygon.getExtent();
  11. var features = vectorLayer.getSource().getFeaturesInExtent(extent); //先缩小feature的范围
  12. var str = "";
  13. for(var i=0;i<features.length;i++){
  14. var newCoords = features[i].getGeometry().getCoordinates();
  15. if(pointInsideCircle(newCoords,center,radius)){
  16. selectedFeatures.push(features[i]);
  17. str += "<div class=\"selectedItem\" onclick='showDeviceOnMap(\""+features[i].getId()+"\");'>"+features[i].get("name")+"</div>";
  18. }
  19. }
  20. $("#selectedInfoContent").html(str);
  21. },300)
  22. })

3、算法:判断点是否在多边形范围内、点是否在圆范围内

  1. /**
  2. * 判断一个点是否在多边形内部
  3. * @param points 多边形坐标集合
  4. * @param testPoint 测试点坐标
  5. * 返回true为真,false为假
  6. * */
  7. function insidePolygon(points, testPoint){
  8. var x = testPoint[0], y = testPoint[1];
  9. var inside = false;
  10. for (var i = 0, j = points.length - 1; i < points.length; j = i++) {
  11. var xi = points[i][0], yi = points[i][1];
  12. var xj = points[j][0], yj = points[j][1];
  13. var intersect = ((yi > y) != (yj > y))
  14. && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
  15. if (intersect) inside = !inside;
  16. }
  17. return inside;
  18. }
  19. /**
  20. * 判断一个点是否在圆的内部
  21. * @param point 测试点坐标
  22. * @param circle 圆心坐标
  23. * @param r 圆半径
  24. * 返回true为真,false为假
  25. * */
  26. function pointInsideCircle(point, circle, r) {
  27. if (r===0) return false
  28. var dx = circle[0] - point[0]
  29. var dy = circle[1] - point[1]
  30. return dx * dx + dy * dy <= r * r
  31. }

4、最终结果

转载自:https://blog.csdn.net/weixin_40902527/article/details/83621965

You may also like...

退出移动版