图形编辑工具提供对要素图形进行增、删、改的功能,具体包括以下几种工具类型:
- 浏览工具
- 选择工具
- 创建要素工具
- 删除命令
- 分割工具
- 合并命令
- 节点编辑工具
- 修边工具
- 撤销命令
- 重做命令
工具的实现基本上是基于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)实现撤销重做原子操作组,像分割这样执行多次数据库增删改的工具,可以一次撤销、一次重做