325 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Markdown
		
	
	
	
		
		
			
		
	
	
			325 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Markdown
		
	
	
	
|  | --- | |||
|  | title: 在线编辑 | |||
|  | date: 2020-11-2 | |||
|  | author: ac | |||
|  | tags:  | |||
|  |   - OpenLayers | |||
|  |   - Draw | |||
|  |   - Modify | |||
|  | categories:  | |||
|  |  - GIS | |||
|  | --- | |||
|  | 
 | |||
|  | ## 1 Draw 对象
 | |||
|  | 
 | |||
|  | > `ol`在客户端(浏览器)可以通过`Draw`交互对象在map中绘制几何图形。
 | |||
|  | 
 | |||
|  | 初始化Draw对象时,在构造参数options中指定type参数和用于存储所绘制图形的数据源source即可,但type类型必须是`'Point'`, `'LineString'`, `'LinearRing'`, `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`, `'GeometryCollection'`, `'Circle'`中的类型。 | |||
|  | 
 | |||
|  | 当然在Draw中也提供了一些方法用于绘制自定义图形。 | |||
|  | 
 | |||
|  |  new Draw(options),options常用的构造参数 | |||
|  | 
 | |||
|  | | name                 | type                                                         | Description                                                  | | |||
|  | | -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | |||
|  | | type                 | [module:ol/geom/GeometryType](https://openlayers.org/en/latest/apidoc/module-ol_geom_GeometryType.html) | 指定要绘制的几何类型                                         | | |||
|  | | clickTolerance       | number                                                       | 绘制时鼠标点击的容差                                         | | |||
|  | | features             | [ol/Collection~Collection](https://openlayers.org/en/latest/apidoc/module-ol_Collection-Collection.html)<[ol/Feature]()> | 用于存储绘制图形的要素集合                                   | | |||
|  | | source               | [ol/source/Vector~VectorSource](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector-VectorSource.html) | 用于存储绘制图形的数据源                                     | | |||
|  | | dragVertexDelay      | number (defaults to 500)                                     | 当前顶点被拖动到其确切位置之前的延迟(毫秒)。                 | | |||
|  | | snapTolerance        | number(defaults to 12)                                       | 可拖放对象离目标对象的距离低于此像素值时开始靠拢             | | |||
|  | | stopClick            | boolean(defaults to false)                                   | 停止在绘图期间触发的单击、singleclick和doubleclick事件。     | | |||
|  | | finishCondition      | [ol/events/condition~Condition](https://openlayers.org/en/latest/apidoc/module-ol_events_condition.html#~Condition) | 绘制结束的条件函数                                           | | |||
|  | | style                | [ol/style/Style~StyleLike](https://openlayers.org/en/latest/apidoc/module-ol_style_Style.html#~StyleLike) | 绘制图形使用的渲染样式                                       | | |||
|  | | **geometryFunction** | [ol/interaction/Draw~GeometryFunction](https://openlayers.org/en/latest/apidoc/module-ol_interaction_Draw.html#~GeometryFunction) | 当绘制图形的坐标发生变化时,调用的函数。它接受一个坐标数组、一个可选的现有几何图形和一个投影作为参数,并返回一个几何图形。 | | |||
|  | | freehand             | boolean(defaults to false)                                   | 自由模式,自定义绘制图形                                     | | |||
|  | | maxPoints            | number                                                       | 绘制多边形或线的最多点数个数                                 | | |||
|  | | minPoints            | number                                                       | 绘制多边形或线的最少点数个数,线默认为2,多边形默认为3       | | |||
|  | 
 | |||
|  | 与`Draw`绘制对象对应的有一个`ol/interaction/Draw~DrawEvent`事件类来处理绘制交互过程中的事件,如: | |||
|  | 
 | |||
|  | - `drawstart`:开始绘制要素时触发 | |||
|  | - `drawend`:绘制结束后触发 | |||
|  | 
 | |||
|  | 示例: | |||
|  | 
 | |||
|  | <img src="./images/image1980.png" alt="image1980" style="zoom: 80%;" /> | |||
|  | 
 | |||
|  | ```html | |||
|  | <!doctype html> | |||
|  | <html> | |||
|  |   <head> | |||
|  |     <link rel="stylesheet" href="css/ol.css" type="text/css"> | |||
|  |     <style> | |||
|  |       .map { | |||
|  |         height: 400px; | |||
|  |         width: 100%; | |||
|  |       } | |||
|  |     </style> | |||
|  |     <script src="lib/ol.js"></script> | |||
|  |     <title>图形绘制</title> | |||
|  |     <meta charset="UTF-8"> | |||
|  |   </head> | |||
|  |   <body> | |||
|  |     <h2>Drawing--图形绘制</h2> | |||
|  |     <div id="map" class="map"></div> | |||
|  |     <div> | |||
|  |       <button onclick="addDrawInteraction('Point')">点</button> | |||
|  |       <button onclick="addDrawInteraction('LineString')">线</button> | |||
|  |       <button onclick="addDrawInteraction('Polygon')">面</button> | |||
|  |       <button onclick="addDrawInteraction('Circle')">圆</button> | |||
|  |       <button onclick="addDrawInteraction('Square')">正方形</button> | |||
|  |       <button onclick="addDrawInteraction('Box')">长方形</button> | |||
|  |       <button onclick="addDrawInteraction('None')">取消</button> | |||
|  |       <button onclick="addDrawInteraction('Clear')">清除</button> | |||
|  |     </div> | |||
|  |     <script type="text/javascript"> | |||
|  | 
 | |||
|  |       var shenzhen = [113.958334,22.535640]; | |||
|  |       var map = new ol.Map({ | |||
|  |         target: 'map', | |||
|  |         layers: [ | |||
|  |             //作为底图 | |||
|  |             new ol.layer.Tile({ | |||
|  |                 source: new ol.source.OSM() | |||
|  |             }) | |||
|  |         ], | |||
|  |         view: new ol.View({ | |||
|  |           center: ol.proj.fromLonLat(shenzhen), | |||
|  |           zoom: 10 | |||
|  |         }) | |||
|  |       }); | |||
|  | 
 | |||
|  |       //创建矢量数据源,用于存储在线绘制几何对象 | |||
|  |       var opterationSource = new ol.source.Vector(); | |||
|  |       var vecLayer = new ol.layer.Vector({ | |||
|  |           source: opterationSource | |||
|  |       }); | |||
|  |       map.addLayer(vecLayer); | |||
|  | 
 | |||
|  |       //创建Draw实例 | |||
|  |       var draw = null; | |||
|  |       function addDrawInteraction(drawType) { | |||
|  |           //移除原来的draw | |||
|  |           map.removeInteraction(draw); | |||
|  |           draw = null; | |||
|  | 
 | |||
|  |           switch (drawType){ | |||
|  |               case 'Point': | |||
|  |               case 'LineString': | |||
|  |               case 'Polygon': | |||
|  |               case 'Circle': | |||
|  |                   draw = new ol.interaction.Draw({ | |||
|  |                       source:opterationSource, | |||
|  |                       type:drawType, | |||
|  |                       // freehand: true //自由模式,自定义绘制 图形 | |||
|  |                   }); | |||
|  |                   map.addInteraction(draw); | |||
|  |                   break; | |||
|  |               case 'Square': | |||
|  |                   draw = new ol.interaction.Draw({ | |||
|  |                       source:opterationSource, | |||
|  |                       type:'Circle', | |||
|  |                       geometryFunction:ol.interaction.Draw.createRegularPolygon(4) | |||
|  |                   }); | |||
|  |                   map.addInteraction(draw); | |||
|  |                   break; | |||
|  |               case 'Box': | |||
|  |                   draw = new ol.interaction.Draw({ | |||
|  |                       source:opterationSource, | |||
|  |                       type:'LineString', | |||
|  |                       maxPoints:2,//绘制前多边形或线的最大点数 | |||
|  |                       //当几何坐标更新时调用 | |||
|  |                       geometryFunction:function (coordinates,geometry) { | |||
|  |                           if(!geometry){ | |||
|  |                               geometry = new ol.geom.Polygon(null);//多边形 | |||
|  |                           } | |||
|  |                           var start = coordinates[0]; | |||
|  |                           var end = coordinates[1]; | |||
|  |                           geometry.setCoordinates([ | |||
|  |                               [ | |||
|  |                                   start, | |||
|  |                                   [start[0],end[1]], | |||
|  |                                   end, | |||
|  |                                   [end[0],start[1]], | |||
|  |                                   start | |||
|  |                               ] | |||
|  |                           ]); | |||
|  |                           return geometry; | |||
|  |                       } | |||
|  |                   }); | |||
|  |                   map.addInteraction(draw); | |||
|  |                   break; | |||
|  |               case "Clear": | |||
|  |                   //清除数据源中存储的要素 | |||
|  |                   opterationSource.clear() ; | |||
|  |                   break; | |||
|  |           } | |||
|  |           if(draw){ | |||
|  |               bindDrawEvent(); | |||
|  |           } | |||
|  |       } | |||
|  |       function bindDrawEvent(){ | |||
|  |           draw.on("drawstart",function(e){ | |||
|  |               console.log("drawstart"); | |||
|  |           }); | |||
|  |           draw.on("drawend",function(e){ | |||
|  |               //从事件源中获取所绘制的几何图形 | |||
|  |               var geometry = e.feature.getGeometry(); | |||
|  |               console.log("drawend"); | |||
|  |           }); | |||
|  |       } | |||
|  |     </script> | |||
|  |   </body> | |||
|  | </html> | |||
|  | ``` | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | ## 2 Modify对象
 | |||
|  | 
 | |||
|  | 如果需要对客户端绘制的图层或要素服务提供的图层进行修改,我们可以使用`ol`中的modify交互对象完成这类需求。跟Draw对象类似,初始化Modify实例时,需要在构造参数中使用source或features指定数据源或要素集合。将Modify实例添加到map上后就可以修改指定的要素了。通常跟snap交互控件一起使用,方便捕捉几何图形的顶点进行修改。 | |||
|  | 
 | |||
|  | 示例: | |||
|  | 
 | |||
|  | <img src="./images/image-20201119180610414.png" alt="image-20201119180610414" style="zoom: 67%;" /> | |||
|  | 
 | |||
|  | ```html | |||
|  | <!doctype html> | |||
|  | <html> | |||
|  |   <head> | |||
|  |     <link rel="stylesheet" href="css/ol.css" type="text/css"> | |||
|  |     <style> | |||
|  |       .map { | |||
|  |         height: 85vh; | |||
|  |         width: 100%; | |||
|  |       } | |||
|  |     </style> | |||
|  |     <script src="lib/ol.js"></script> | |||
|  |     <script src="lib/jquery-3.1.1.js"></script> | |||
|  |     <title>图形修改</title> | |||
|  |     <meta charset="UTF-8"> | |||
|  |   </head> | |||
|  |   <body> | |||
|  |     <h2>Modify--图形修改</h2> | |||
|  |     <div id="map" class="map"></div> | |||
|  |     <div>图形绘制: | |||
|  |       <button onclick="addDrawInteraction('Point')">点</button> | |||
|  |       <button onclick="addDrawInteraction('LineString')">线</button> | |||
|  |       <button onclick="addDrawInteraction('Polygon')">面</button> | |||
|  |       <button onclick="addDrawInteraction('Circle')">圆</button> | |||
|  |       <button onclick="addDrawInteraction('Square')">正方形</button> | |||
|  |       <button onclick="addDrawInteraction('Box')">长方形</button> | |||
|  |       <button onclick="addDrawInteraction('None')">取消</button> | |||
|  |       <button onclick="addDrawInteraction('Clear')">清除</button> | |||
|  |     </div> | |||
|  |     <div>图形修改: | |||
|  |       <button onclick="addModify()">修改</button> | |||
|  |       <button onclick="cancelModify()">取消</button> | |||
|  |     </div> | |||
|  |     <script type="text/javascript"> | |||
|  | 
 | |||
|  |       var map = new ol.Map({ | |||
|  |         target: 'map', | |||
|  |         layers: [ | |||
|  |             new ol.layer.Tile({ | |||
|  |                 source: new ol.source.OSM() | |||
|  |             }) | |||
|  |         ], | |||
|  |         view: new ol.View({ | |||
|  |           center: ol.proj.fromLonLat([137.41, 23.82]), | |||
|  |           zoom: 4 | |||
|  |         }) | |||
|  |       }); | |||
|  | 
 | |||
|  | 
 | |||
|  |       //创建矢量数据源,用于存储在线绘制几何对象 | |||
|  |       var opterationSource = new ol.source.Vector(); | |||
|  |       var vecLayer = new ol.layer.Vector({ | |||
|  |           source: opterationSource | |||
|  |       }); | |||
|  |       map.addLayer(vecLayer); | |||
|  | 
 | |||
|  |       //创建Draw实例 | |||
|  |       var draw = null; | |||
|  |       function addDrawInteraction(drawType) { | |||
|  |           //移除原来的draw | |||
|  |           map.removeInteraction(draw); | |||
|  |           draw = null; | |||
|  |           switch (drawType){ | |||
|  |               case 'Point': | |||
|  |               case 'LineString': | |||
|  |               case 'Polygon': | |||
|  |               case 'Circle': | |||
|  |                   draw = new ol.interaction.Draw({ | |||
|  |                       source:opterationSource, | |||
|  |                       type:drawType, | |||
|  |                   }); | |||
|  |                   map.addInteraction(draw); | |||
|  |                   break; | |||
|  |               case 'Square': | |||
|  |                   draw = new ol.interaction.Draw({ | |||
|  |                       source:opterationSource, | |||
|  |                       type:'Circle', | |||
|  |                       geometryFunction:ol.interaction.Draw.createRegularPolygon(4) | |||
|  |                   }); | |||
|  |                   map.addInteraction(draw); | |||
|  |                   break; | |||
|  |               case 'Box': | |||
|  |                   draw = new ol.interaction.Draw({ | |||
|  |                       source:opterationSource, | |||
|  |                       type:'LineString', | |||
|  |                       maxPoints:2, | |||
|  |                       geometryFunction:function (coordinates,geometry) { | |||
|  |                           if(!geometry){ | |||
|  |                               geometry = new ol.geom.Polygon(null);//多边形 | |||
|  |                           } | |||
|  |                           var start = coordinates[0]; | |||
|  |                           var end = coordinates[1]; | |||
|  |                           geometry.setCoordinates([ | |||
|  |                               [ | |||
|  |                                   start, | |||
|  |                                   [start[0],end[1]], | |||
|  |                                   end, | |||
|  |                                   [end[0],start[1]], | |||
|  |                                   start | |||
|  |                               ] | |||
|  |                           ]); | |||
|  |                           return geometry; | |||
|  |                       } | |||
|  |                   }); | |||
|  |                   map.addInteraction(draw); | |||
|  |                   break; | |||
|  |               case "Clear": | |||
|  |                   opterationSource.clear() ; | |||
|  |                   break; | |||
|  |           } | |||
|  |       }; | |||
|  |       //创建modify实例 | |||
|  |       var modify = new ol.interaction.Modify({ | |||
|  |           source:opterationSource | |||
|  |       }); | |||
|  |       function addModify() { | |||
|  |           map.addInteraction(modify); | |||
|  |       }; | |||
|  |       function cancelModify() { | |||
|  |           map.removeInteraction(modify); | |||
|  |       }; | |||
|  |     </script> | |||
|  |   </body> | |||
|  | </html> | |||
|  | ``` | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | ## 参考文章
 | |||
|  | 
 | |||
|  | [1] TopoJSON https://www.jianshu.com/p/351fbc010412?from=singlemessage | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 |