1. 程式人生 > >openlayes 3 點選,圈選,多邊形選實現

openlayes 3 點選,圈選,多邊形選實現

   點選、圈選、多邊形選擇也是地圖中比較基礎的功能了,只是一直沒有需求,最近兩天把這個功能從頁面到功能完整的做了一遍。我使用的方法是使用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、最終結果