圖形編輯工具提供對要素圖形進行增、刪、改的功能,具體包括以下幾種工具類型:
- 瀏覽工具
- 選擇工具
- 創建要素工具
- 刪除命令
- 分割工具
- 合並命令
- 節點編輯工具
- 修邊工具
- 撤銷命令
- 重做命令
工具的實現基本上是基於ol.interation來實現的,只不過做了組合、結果處理等實現。分割工具效果圖如下:

實現思路:
1.通過工具管理器進行工具間切換等統一調度
2.每個工具通過SetActive方法實現該工具的啟動、卸載邏輯
3.每個工具維護自己的光標狀態、輔助工具欄和交互處理邏輯
線分割示例代碼:
'use strict'; var mzToolType = require('./mzToolEnum'); var ToolManager = require('./mzToolManager.js'); var mzFormat = require('./../Format'); var mzSpatialanylize = require('./../../MAPZONE JavaScript SDK/mzGeometry/mzSpatialanylize.js'); var mzOperationGroup = require('./../mzUndoRedo/mzOperationGroup.js'); var mzSelectManager = require('./mzSelectManager.js'); module.exports = mzSplitTool; function mzSplitTool(opt_options) { var options = opt_options || {}; if (undefined == options.map) return; this.type = mzToolType.mzToolType.MZ_SPLIT_TOOL; this.name = options.name !== undefined ? options.name : '線分割'; this.interaction = new ol.interaction.Draw({ type: 'LineString' }); options.map.addInteraction(this.interaction); this.interaction.setActive(false); //初始化輔助工具欄 this.mainbar = new ol.control.Bar(); this.initAssistantToolbar(); this.active = false; } mzSplitTool.prototype.drawendfuntion = function (e) { var manager = ToolManager.getToolManager(); var selectTool = manager.getTool('選擇'); var lineString = e.feature.getGeometry(); var SelectManager = mzSelectManager.getSelectManager(); var fts = SelectManager.getSelectFs(); if (fts.length < 1) { Materialize.toast("請至少選擇一個要素!", 2000); return; } var undoredoManager = selectTool.interaction.map_.undoredoManager; undoredoManager.beginTrans(new mzOperationGroup()); for (var i = 0; i < fts.length; i++) { var source = fts[i].vector; var nSrid = source.getSrid(); var polygon = mzFormat.olGeo2mzGeo(fts[i].feature.getGeometry()); polygon.setSRID(nSrid); var path = mzFormat.olGeo2mzGeo(lineString); path.setSRID(nSrid); var tolarence = polygon.getTolerance(); var geoSet = mzSpatialanylize.cut(polygon, path, tolarence); var nCount = geoSet.getGeometryCount(); for (var j = 0; j < nCount; j++) { var geo = geoSet.getGeometry(j); if (0 == j) { source.updateGeometry(fts[i].feature, mzFormat.mzGeo2olGeo(geo), undoredoManager); } else { var feature = new ol.Feature(); feature.setId(-1); feature.setProperties(fts[i].feature.getProperties()); feature.setGeometry(mzFormat.mzGeo2olGeo(geo)); source.addFeature(feature, undoredoManager); } } } undoredoManager.endTrans(); selectTool.clear(); selectTool.interaction.map_.customRefresh(); } mzSplitTool.prototype.setActive = function (active) { if (active == this.active) return; if (undefined == this.interaction) return; var manager = ToolManager.getToolManager(); var selectTool = manager.getTool('選擇'); var SelectManager = mzSelectManager.getSelectManager(); var fts = SelectManager.getSelectFs(); if (fts.length < 1 && active) { Materialize.toast("請至少選擇一個要素!", 2000); active = false; } if (active) { manager.unLoadTool({ tool: this }); this.setCursor(); } this.interaction.setActive(active); if (active) { this.interaction.on('drawend', this.drawendfuntion, this); //加載輔助工具欄 this.interaction.map_.addControl(this.mainbar); } else { this.interaction.un('drawend', this.drawendfuntion, this); //卸載輔助工具欄 this.interaction.map_.removeControl(this.mainbar); } this.active = active; } mzSplitTool.prototype.getActive = function () { return this.active; } mzSplitTool.prototype.setCursor = function (opt_options) { var options = opt_options || {}; var cursor = options.cursor; document.getElementById("map").style.cursor = cursor == undefined ? "crosshair" : cursor; } mzSplitTool.prototype.initAssistantToolbar = function () { // Edit control bar var editbar = new ol.control.Bar( { toggleOne: true, // one control active at the same time group: false // group controls together }); this.mainbar.addControl(editbar); //完成線分割 var finishDrawing = new ol.control.TextButton( { html: '<i class="fa fa-check"></i>', title: "完成", handleClick: function () { var ToolManager = require('../../mapzone-ol3-plugin/mzTool/mzToolManager.js'); var manager = ToolManager.getToolManager(this.map_); manager.getTool('線分割').interaction.finishDrawing(); } }); editbar.addControl(finishDrawing); //取消線分割 var cancleDrawing = new ol.control.TextButton( { html: '<i class="fa fa-times"></i>', title: "取消", handleClick: function () { var ToolManager = require('../../mapzone-ol3-plugin/mzTool/mzToolManager.js'); var manager = ToolManager.getToolManager(this.map_); manager.getTool('線分割').interaction.abortDrawing_(); } }); editbar.addControl(cancleDrawing); }
撤銷重做實現邏輯:
1)將撤銷重做內容抽象成原子操作,可以執行do、undo、redo方法
2)實現撤銷重做管理器,根據需要將原子操作執行入棧、出棧等邏輯
3)為數據庫的增、刪、改實現撤銷重做原子操作,例如增的do和redo實現就是將Feature保存到數據庫中,undo是將該Feature從數據庫中刪除
4)實現撤銷重做原子操作組,像分割這樣執行多次數據庫增刪改的工具,可以一次撤銷、一次重做
