MAPZONE GIS SDK接入Openlayers3之五——图形编辑工具

图形编辑工具提供对要素图形进行增、删、改的功能,具体包括以下几种工具类型:

  • 浏览工具
  • 选择工具
  • 创建要素工具
  • 删除命令
  • 分割工具
  • 合并命令
  • 节点编辑工具
  • 修边工具
  • 撤销命令
  • 重做命令

工具的实现基本上是基于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)实现撤销重做原子操作组,像分割这样执行多次数据库增删改的工具,可以一次撤销、一次重做

原文地址:https://www.cnblogs.com/conorpai/p/6497478.html