本篇的重点内容是利用openlayers实现地图标绘功能,效果图如下:
实现思路:
- 标绘界面设计以及标绘面板控制
//标绘例 var plotFlag = false; $("#bPlot").click(function () { if(!plotFlag){ $("#map_toolbar_plot").show(); plotFlag = true; }else{ bmap.setCurrentMutexInteraction(null); if(bmap.dataClear){ bmap.dataClear.clear(); } $("#map_toolbar_plot").hide(); plotFlag = false; } });
- 标绘初始化以及核心代码实现
//标绘 var plottypes = ["freehandline","polyline","arc","curve","freehandpolygon","polygon", "rectangle","circle","assaultdirection","squadcombat","tailedsquadcombat","gatheringplace"]; for(var i = 0; i < plottypes.length; i++){ var selector = '#map_toolbar_plot li[plottype="' + plottypes[i] + '"]'; $(selector).on('click',function(){ var id = "10006";//标绘工具 var tool = bmap.getIndexInteraction(id); bmap.setCurrentMutexInteraction(tool); //标绘类型 var plottype = $(this).attr("plottype"); tool.setDrawType(plottype); }) }
/** * 获取带有索引的交互工具 * @param index {String} * @returns {ol.interaction.Interaction|null} */ bxmap.Map.prototype.getIndexInteraction = function(index){ var indexInteractions = this.get("bxmap_index_interactions") || {}; var interaction = indexInteractions[index]; if(interaction == null && this.getMap()){ var arr = this.getMap().getInteractions().getArray(); for(var i = 0; i < arr.length ; i++){ if(index == arr[i].get(bxmap.INDEX_INTERACTION_ID)){ interaction = arr[i]; indexInteractions[index] = interaction; break; } } } return interaction; }
/*----------标绘,依赖于GISpace动态标绘开源项目{bxmap.interaction.Plot}---------*/ /** * @classdesc 用于绘制军事图形,依赖于依赖于GISpace动态标绘开源项目 * @extends {ol.interaction.Interaction} * @param options {Object} * @param options.type {String} 默认为polygon */ bxmap.interaction.Plot = function (options) { ol.interaction.Interaction.call(this, { handleEvent: this._handleKeyboardEvent }); this.plotDraw = null; //绘制标绘 this.plotEdit = null; //编辑标绘 this.plotLayer = null; //标绘图层 this.editingFeatures = new ol.Collection();//当前选择的要素 var opt_options = options ? options : {}; var type = opt_options.type ? opt_options.type : "polygon"; this.setDrawType(type); } ol.inherits(bxmap.interaction.Plot, ol.interaction.Interaction); /** * @inheritdoc * @param {ol.CanvasMap} map */ bxmap.interaction.Plot.prototype.setMap = function (map) { ol.interaction.Interaction.prototype.setMap.call(this, map); if (map) { // 初始化标绘绘制工具,添加绘制结束事件响应 var plotDraw = this.plotDraw = new P.PlotDraw(map); plotDraw.on("draw_end", this._onDrawEnd, this); // 初始化标绘编辑工具 var plotEdit = this.plotEdit = new P.PlotEdit(map); var plotLayer = this.plotLayer = this.getLayer(); // 添加标绘图层 map.addLayer(plotLayer); map.on('click', function (e) { if (plotDraw.isDrawing()) return; var feature = map.forEachFeatureAtPixel(e.pixel, function (feature, layer) { return feature; },{ layerFilter: function (layer) { return layer == plotLayer; }, hitTolerance: 1 //1像素,仅在canvas render中有效 }); if (feature) { this.editingFeatures.push(feature); // 开始编辑 this._startEditingFeature(feature); } else { // 结束编辑 this._finishEditing(); } },this); } } /** * @description 设置绘制图形类型 * @param {String} drawType 类型 * @example 图形类型有效值 * arc - 弧线,curve - 曲线,polyline - 折线,freehandline - 自由线,circle - 圆, * ellipse - 椭圆,closedcurve - 曲线面,polygon - 多边形,rectangle - 矩形, * freehandpolygon - 自由面,gatheringplace - 聚集地,doublearrow - 钳击双箭头, * straightarrow - 直线箭头,finearrow - 细直箭头,assaultdirection - 直箭头, * attackarrow - 进攻箭头,tailedattackarrow - 燕尾进攻箭头,squadcombat - 斜箭头, * tailedsquadcombat - 燕尾斜箭头 */ bxmap.interaction.Plot.prototype.setDrawType = function(drawType){ var map = this.getMap(); this.setCursor("default"); this.set("draw_type", drawType); if (this.plotEdit && this.plotDraw) { this._finishEditing(); this.plotDraw.activate(drawType); } } /** * @description 获取绘制图形类型 * @returns {String} 绘制图形类型 */ bxmap.interaction.Plot.prototype.getDrawType = function(){ return this.get("draw_type"); } /** * @private * @description 更新状态 */ bxmap.interaction.Plot.prototype._updateState = function() { var map = this.getMap(); if(map == null) return; var active = this.getActive(); var plotDraw = this.plotDraw; var plotEdit = this.plotEdit; var layer = this.plotLayer; //使激活 if(active){ this._finishEditing(); if(plotDraw){ var type = this.getDrawType(); plotDraw.activate(type); } }else{ if(plotDraw){ plotDraw.deactivate(); } this._finishEditing(); } }; /** * @description 获取标绘图层 * @returns {ol.layer.Vector} */ bxmap.interaction.Plot.prototype.getLayer = function(){ if(this.plotLayer == null){ // 设置标绘符号显示的默认样式 var stroke = new ol.style.Stroke({color: '#FF0000', width: 2}); var fill = new ol.style.Fill({color: 'rgba(0,255,0,0.4)'}); var image = new ol.style.Circle({fill: fill, stroke: stroke, radius: 8}); drawStyle = new ol.style.Style({image: image, fill:fill, stroke:stroke}); // 绘制好的标绘符号,添加到FeatureOverlay显示。 var layer = this.plotLayer = new ol.layer.Vector({ source: new ol.source.Vector() }); layer.setStyle(drawStyle); layer.setZIndex(bxmap.CONFIG_LEVEL_MAX + 1);//保持不被其他图层覆盖 } return this.plotLayer; } /** * @private * @param mapBrowserEvent * @returns {Boolean} */ bxmap.interaction.Plot.prototype._handleKeyboardEvent = function(mapBrowserEvent) { var stopEvent = false; var map = this.getMap(); if(map == null) return; if (mapBrowserEvent.type == "keydown" || mapBrowserEvent.type == "keypress") { var keyEvent = mapBrowserEvent.originalEvent; var keyCode = keyEvent.keyCode; if (keyCode == 46) {//delete var plotLayer = this.plotLayer; this.editingFeatures.forEach(function (elem, index, array) { var close = elem.get("close_button"); if (close) { map.removeOverlay(close); } var source = plotLayer.getSource(); source.removeFeature(elem); }); this.plotEdit.deactivate(); this.editingFeatures.clear(); mapBrowserEvent.preventDefault(); stopEvent = true; } } return !stopEvent; } /** * @private * @description 绘制结束后,添加图层显示。 */ bxmap.interaction.Plot.prototype._onDrawEnd = function (event) { var feature = event.feature; if (feature) { //添加到编辑要素集合中 this.editingFeatures.push(feature); //添加到标绘图层 this.plotLayer.getSource().addFeature(feature); this._bindingCloseButton(feature); //开始编辑 this._startEditingFeature(feature); } } /** * @private * @description 开始编辑要素 */ bxmap.interaction.Plot.prototype._startEditingFeature = function (feature) { if (this.plotEdit == null || feature == null) return; this.plotEdit.activate(feature); var close = feature.get("close_button"); var map = this.getMap(); if (map && close) { var exists = map.getOverlayById(close.getId()); if(exists == null){ map.addOverlay(close); } var ctlPoints = this.plotEdit.getControlPoints(); var point = ctlPoints[ctlPoints.length - 1]; close.setPosition(point); } } /** * @private * @description 结束编辑要素 */ bxmap.interaction.Plot.prototype._finishEditing = function () { if (this.plotEdit) { this.plotEdit.deactivate(); } //移除删除按钮 var map = this.getMap(); if (map == null) return; this.editingFeatures.forEach(function (elem, index, array) { var close = elem.get("close_button"); if (map && close) { map.removeOverlay(close); } }); this.editingFeatures.clear(); } /** * @private * @description 获取删除按钮 * @returns {ol.Overlay} */ bxmap.interaction.Plot.prototype._bindingCloseButton = function (feature) { if (feature == null) return; var uid = bxmap.common.getCounterUid(feature); var closeTooltipElement = document.createElement('div'); closeTooltipElement.className = 'tooltip tooltip-close'; var closeOverlay = new ol.Overlay({ id: uid, element: closeTooltipElement, offset: [16, 0], positioning: 'bottom-center' }); closeTooltipElement.innerHTML = '✘'; feature.set("close_button", closeOverlay); //执行删除绘制 var plotLayer = this.plotLayer; var plotEdit = this.plotEdit; var map = this.getMap(); closeTooltipElement.addEventListener('click', function () { if (plotEdit && feature && plotLayer) { var close = feature.get("close_button"); if (close && map) { map.removeOverlay(close); } var source = plotLayer.getSource(); source.removeFeature(feature); plotEdit.deactivate(); } }); } /** * 清空绘制的数据 */ bxmap.interaction.Plot.prototype.clear = function(){ this._finishEditing(); if(this.plotLayer){ this.plotLayer.getSource().clear(); } }