类名 leaflet/sketchEditor/SketchEditor2D.js
import {
  Zondy,
  SketchEditorNew,
  defaultValue,
  SketchStyle,
  SketchDataType,
  Polygon,
  Log
} from '@mapgis/webclient-common'
/**
 * 二维场景草图编辑类<br/>
 * <br>[ES5引入方式]:<br/>
 * const { SketchEditor2D } = Zondy <br/>
 * [ES6引入方式]:<br/>
 * import { SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
 * @classdesc 二维草图编辑类
 * @class SketchEditor2D
 * @extends SketchEditorNew
 * @moduleEX SketchEditorModule
 * @fires SketchEditorNew#草图绘制完成事件
 * @fires SketchEditorNew#草图被选中事件
 * @param {Object} options 构造参数
 * @param {MapView}  [options.mapView]  地图视图对象
 * @param {GraphicsLayer}  [options.layer]  草图图层管对象
 * @param {SketchStyle}  [options.sketchStyle]  草图符号
 * @param {Object}  [options.snappingOption]  草图捕获配置项
 *
 * @summary <h5>支持如下方法:</h5>
 * <a href='#start'>[1、开始绘制草图]</a><br/>
 * <a href='#stop'>[2、停止绘制]</a><br/>
 * <a href='#remove'>[3、移除当前草图]</a><br/>
 * <a href='#addVertex'>[4、向草线或面草图中插入新的顶点]</a><br/>
 * <a href='#updateVertex'>[5、更新草图图形的某个顶点]</a><br/>
 * <a href='#removeVertex'>[6、移除草图图形的某个顶点]</a><br/>
 * <a href='#getSketchDataType'>[7、获取草图图形类型]</a><br/>
 * <a href='#setSketchStyle'>[8、设置草图样式]</a><br/>
 * <a href='#getSketchStyle'>[9、获取草图样式]</a><br/>
 * <a href='#getGeometry'>[10、获取草图几何对象]</a><br/>
 * <a href='#union'>[11、合并多个区几何]</a><br/>
 * <a href='#split'>[12、分割草图对象或区几何对象]</a><br/>
 * <a href='#undo'>[13、撤销当前编辑操作]</a><br/>
 * <a href='#redo'>[14、恢复被撤销的草图]</a><br/>
 *
 * @example <caption><h7 id='MapView'>初始化一个二维场景草图编辑类</h7></caption>
 * // [ES5引入方式]:
 * const { SketchEditor2D } = Zondy
 * [ES6引入方式]:
 * import { MapView, SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
 * import { SketchStyle, SimpleMarkerSymbol, Color, SketchDataType} from "@mapgis/webclient-common" <br/>
 * var map = new Map()
 * var mapView = new MapView({
 *   viewId: "mapgis-2d-viewer",
 *   map: this.map,
 * })
 * var simpleMarkerSymbol = new SimpleMarkerSymbol({
 *   color: new Color(24, 144, 255, 1),
 *   size: 10,
 * });
 * var sketchStyle = new SketchStyle({
 *   vertexStyle: simpleMarkerSymbol,
 *     lineStyle: undefined,
 *     fillStyle: undefined
 *   })
 * var sketchEditor2D = new SketchEditor2D({
 *   mapView: this.mapView,
 *   layer: new GraphicsLayer(),
 *   vertexStyle: vertexStyle
 * })
 * SketchEditor2D.start(SketchDataType.POINT) // 绘制点
 * SketchEditor2D.start(SketchDataType.POLYLINE) // 绘制线
 * SketchEditor2D.start(SketchDataType.POLYGON) // 绘制区
 * * */
class SketchEditor2D extends SketchEditorNew {
  constructor(options) {
    super(options)
    options = defaultValue(options, {})
    /**
     * 地图视图
     * @member {MapView|SecenView} SketchEditor.prototype._mapView
     */
    this._mapView = options.mapView
    /**
     * 草图图层
     * @member {GraphicsLayer} SketchEditor.prototype._layer
     */
    this._layer = defaultValue(options.layer, undefined)
    /**
     * 草图符号
     * @member {SketchStyle} SketchEditor.prototype._sketchStyle
     */
    this._sketchStyle = defaultValue(options.sketchStyle, new SketchStyle())
    /**
     * 草图捕获配置项
     * @member {Object} SketchEditor.prototype.snappingOption
     */
    const snappingOption = {
      showSelectBox: false,
      showSelectVertex: false,
      canEditFeature: false,
      canEditVertex: false
    }
    this.snappingOption = defaultValue(options.snappingOption, snappingOption)
    /**
     * 草图量算配置项
     * @member {Number} SketchEditor.prototype.measureOption
     */
    this.measureOption = defaultValue(options.measureOption, undefined)
    /**
     * 草图绘制工具
     * @member {Number} SketchEditor.prototype._drawTool
     */
    this._drawTool = null
    /**
     * 草图回撤管理器
     * @member {Number} SketchEditor.prototype._redoUndoManager
     */
    this._redoUndoManager = undefined
    /**
     * 草图绘制类型
     * @member {Number} SketchEditor.prototype._sketchDataType
     */
    this._sketchDataType = null
  }

  /**
   * 开始绘制草图<a id='start'></a>
   * @param {SketchDataType} dataType 草图编辑类型
   * @example <caption><h7 id='MapView'>初始化一个二维场景草图编辑类</h7></caption>
   * // [ES5引入方式]:
   * const { SketchEditor2D } = Zondy
   * [ES6引入方式]:
   * import { MapView, SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
   * import { SketchStyle, SimpleMarkerSymbol, Color, SketchDataType} from "@mapgis/webclient-common" <br/>
   * var map = new Map()
   * var mapView = new MapView({
   *   viewId: "mapgis-2d-viewer",
   *   map: this.map,
   * })
   * var simpleMarkerSymbol = new SimpleMarkerSymbol({
   *   color: new Color(24, 144, 255, 1),
   *   size: 10,
   * });
   * var sketchStyle = new SketchStyle({
   *   vertexStyle: simpleMarkerSymbol,
   *     lineStyle: undefined,
   *     fillStyle: undefined
   *   })
   * var sketchEditor2D = new SketchEditor2D({
   *   mapView: this.mapView,
   *   layer: new GraphicsLayer(),
   *   vertexStyle: vertexStyle
   * })
   * SketchEditor2D.start(SketchDataType.POINT) // 绘制点
   * SketchEditor2D.start(SketchDataType.POLYLINE) // 绘制线
   * SketchEditor2D.start(SketchDataType.POLYGON) // 绘制区
   */
  start(dataType) {
    super.start(dataType)
  }

  /**
   * 停止绘制<a id='stop'></a>
   */
  stop() {
    super.stop()
  }

  /**
   * 移除当前草图<a id='remove'></a>
   */
  remove() {
    super.remove()
  }

  /**
   * 更新当前选中的草图
   * @private
   */
  update(data, featureId) {
    super.updateFeature(data, featureId)
  }

  /**
   * 向当前线或区草图中插入新的顶点<a id='addVertex'></a>
   * @param {Point} point 新增/插入顶点
   * @param {Number} index 新增/新增点的序号
   */
  addVertex(point, index) {
    super.addVertex(point, index)
  }

  /**
   * 更新当前草图图形的某个顶点<a id='updateVertex'></a>
   * @param {Point} point 新的顶点
   * @param {Number} index 需更新的顶点的序号
   */
  updateVertex(point, index) {
    super.updateVertex(point, index)
  }

  /**
   * 移除草图图形的某个顶点<a id='removeVertex'></a>
   * @param {Number} index 需更新的顶点的序号
   */
  removeVertex(index) {
    super.removeVertex(index)
  }

  /**
   * 获取草图图形类型<a id='getSketchDataType'></a>
   * @private
   */
  getSketchDataType() {
    super.getSketchDataType()
  }

  /**
   * 设置草图样式<a id='setSketchStyle'></a>
   * @param {SketchStyle} sketchStyle
   * @example
   * // ES5引入方式
   * const { SimpleFillSymbol, SimpleLineSymbol } = Zondy.Symbol
   * const { Color, SketchStyle } = Zondy
   * // ES6引入方式
   * import { SimpleFillSymbol, SimpleLineSymbol, Color, SketchStyle } from "@mapgis/webclient-common"
   * // 新建一个填充样式
   * const fillStyle = new SimpleFillSymbol({
   *   color: new Color(0, 255, 255, 1),
   *   outline: new SimpleLineSymbol({
   *     color: new Color(255, 0, 0, 1),
   *     width: 2
   *   })
   * })
   * // 新建一个草图样式
   * const sketchStyle = new SketchStyle({
   *   // 传入填充样式给区注记使用
   *   fillStyle: fillStyle,
   *   // 绘制线注记时显示分段长度
   *   isShowSegmentLength: true,
   *   // 绘制区注记时显示面积
   *   isShowArea: true
   * })
   * sketchEditor2D.setSketchStyle(sketchStyle)
   */
  setSketchStyle() {
    super.setSketchStyle()
  }

  /**
   * 获取草图样式<a id='getSketchStyle'></a>
   * @returns {SketchStyle}
   */
  getSketchStyle() {
    return super.getSketchStyle()
  }

  /**
   * 获取草图几何对象<a id='getGeometry'></a>
   * @returns {Geometry}
   */
  getGeometry() {
    return super.getGeometry()
  }

  /**
   * 合并多个区几何<a id='union'></a>
   * @param {Polygon} polygons 被合并的区几何对象
   * @returns {Polygon} 合并后的几何对象
   * @example <caption><h7 id='MapView'>二维草图几何合并</h7></caption>
   * // [ES5引入方式]:
   * const { MapView, SketchEditor2D, polygon } = Zondy
   * [ES6引入方式]:
   * import { MapView, SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
   * import { polygon } from "@mapgis/webclient-common" <br/>
   * var map = new Map()
   * var mapView = new MapView({
   *   viewId: "mapgis-2d-viewer",
   *   map: this.map,
   * })
   * var sketchEditor2D = new SketchEditor2D({
   *   mapView: this.mapView,
   *   layer: new GraphicsLayer()
   * })
   * const polygon = new Polygon({
   *   coordinates: [
   *     [
   *       [0, -60],
   *       [0, 60],
   *       [160, 60],
   *       [160, -60],
   *       [0, -60]
   *     ]
   *   ]
   * })
   * const polygon1 = new Polygon({
   *   coordinates: [
   *     [
   *       [10, -60],
   *       [10, 60],
   *       [170, 60],
   *       [170, -60],
   *       [10, -60]
   *     ]
   *   ]
   * })
   * const polygons = [polygon,polygon1]
   * sketchEditor2D.union(polygons)
   */
  union(polygons) {
    return super.union(polygons)
  }

  /**
   * 分割草图对象或区几何对象<a id='split'></a>
   * @param {Polygon|SketchEditorNew} target 被分割的几何/草图对象
   * @param {Polyline} splitPolyline 线几何对象
   * @returns {Array<SketchEditorNew>} 合并后的几何对象
   * @example <caption><h7 id='MapView'>二维草图几何分割</h7></caption>
   * // [ES5引入方式]:
   * const { MapView, SketchEditor2D, Polygon, LineString } = Zondy
   * [ES6引入方式]:
   * import { MapView, SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
   * import { Polygon, LineString } from "@mapgis/webclient-common" <br/>
   * var map = new Map()
   * var mapView = new MapView({
   *   viewId: "mapgis-2d-viewer",
   *   map: this.map,
   * })
   * var sketchEditor2D = new SketchEditor2D({
   *   mapView: this.mapView,
   *   layer: new GraphicsLayer()
   * })
   * const polygon = new Polygon({
   *   coordinates: [
   *   [
   *       [108, 29],
   *       [116, 29],
   *       [116, 33],
   *       [108, 33],
   *       [108, 29]
   *     ]
   *   ]
   * })
   * const polyline = new LineString({
   *   coordinates: [
   *     [100, 30],
   *     [120, 30]
   *   ]
   * })
   * const newSketchEditors = sketchEditor2D.split(polygon,polyline)
   */
  split(target, splitPolyline) {
    let polygon = null
    const self = this
    if (target instanceof Polygon) {
      polygon = target
    } else if (
      target instanceof SketchEditorNew &&
      target.drawTool._sketchDataType === SketchDataType.POLYGON
    ) {
      polygon = target._sketchStage.entityGraphic
    } else {
      Log.error('传入对象不符合要求,请检查')
      return
    }
    const splitPolygon = function (polygon, splitPolyline) {
      const sketchEditors = []
      const splitPolygons = self._sketchTopologyTool.splitPolygonByPolyline(
        polygon,
        splitPolyline
      )
      if (splitPolygons.length > 0) {
        // 创建分割后的草图
        splitPolygons.forEach((polygon) => {
          // if (i != 0) return
          const sketchEditor = new SketchEditor2D({
            mapView: self._mapView,
            layer: self._layer
          })
          sketchEditor.start(polygon)
        })
      }
      return sketchEditors
    }
    return splitPolygon(polygon, splitPolyline)
  }

  /**
   * 撤销当前编辑操作<a id='undo'></a>
   * @returns {Geometry}
   * @example <caption><h7 id='MapView'>二维草图几何分割</h7></caption>
   * // [ES5引入方式]:
   * const { MapView, SketchEditor2D, Polygon, LineString, SketchDataType } = Zondy
   * [ES6引入方式]:
   * import { MapView, SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
   * import { Polygon, LineString, SketchDataType } from "@mapgis/webclient-common" <br/>
   * var map = new Map()
   * var mapView = new MapView({
   *   viewId: "mapgis-2d-viewer",
   *   map: this.map,
   * })
   * var sketchEditor2D = new SketchEditor2D({
   *   mapView: this.mapView,
   *   layer: new GraphicsLayer()
   * })
   * sketchEditor2D.start(SketchDataType.POLYGON)
   * console.log("是否可以进行撤销操作:" + this.sketchEditor2D.canUndo())
   * const geometry = this.sketchEditor2D.undo()
   * console.log("恢复后的几何对象" + geometry)
   */
  undo() {
    return super.undo()
  }

  /**
   * 恢复被撤销的草图<a id='redo'></a>
   * @returns {Geometry}
   * @example <caption><h7 id='MapView'>二维草图几何分割</h7></caption>
   * // [ES5引入方式]:
   * const { SketchEditor2D } = Zondy
   * [ES6引入方式]:
   * import { MapView, SketchEditor2D } from "@mapgis/webclient-leaflet-plugin" <br/>
   * import { Polygon, LineString } from "@mapgis/webclient-common" <br/>
   * var map = new Map()
   * var mapView = new MapView({
   *   viewId: "mapgis-2d-viewer",
   *   map: this.map,
   * })
   * var sketchEditor2D = new SketchEditor2D({
   *   mapView: this.mapView,
   *   layer: new GraphicsLayer()
   * })
   * sketchEditor2D.start(SketchDataType.POLYGON)
   * console.log("是否可以进行恢复操作:" + this.sketchEditor2D.canRedo())
   * const geometry = this.sketchEditor2D.redo()
   * console.log("恢复后的几何对象" + geometry)
   */
  redo() {
    return super.redo()
  }

  /**
   * 草图是否可执行撤销操作<a id='canUndo'></a>
   * @returns {Boolean}
   */
  canUndo() {
    return super.canUndo()
  }

  /**
   * 草图是否可执行恢复操作<a id='canRedo'></a>
   * @returns {Boolean}
   */
  canRedo() {
    return super.canRedo()
  }

  /**
   * 二维leaflet初始化监听图层加载完成事件
   * @private
   */
  _initLayerEvent() {
    const self = this
    this._layer.on('layerview-created', function (event) {
      event.layerView.innerLayer.on('layeradd', (event) => {
        if (self._drawTool && self._drawTool._hitTestDrawToolStack) {
          let existIndex = -1
          self._drawTool._hitTestDrawToolStack.forEach((drawTool, index) => {
            if (
              event.layer.__feature__id ===
              drawTool._sketchStage.entityGraphic.id
            ) {
              existIndex = index
            }
          })
          if (existIndex > -1) {
            self._drawTool._hitTestDrawToolStack[existIndex]._hitTestEvent()
            self._drawTool._hitTestDrawToolStack.splice(existIndex, 1)
          }
        }
      })
    })
  }

  /**
   * 二维leaflet草图拾取事件
   * @private
   */
  _hitTestEvent() {
    const self = this
    let handler = null
    this._disableMapDrag = () => {
      self._mapView._innerView.dragging.disable()
    }
    this._enableMapDrag = () => {
      self._mapView._innerView.dragging.enable()
    }
    if (this._hitTestHandler) {
      handler = this._hitTestHandler.bind(this)
    }

    this._hitTestEventHandlers = [handler]
    if (this.snappingOption) {
      const mode = this.snappingOption._hitTestMode
      if (this._layer) {
        for (const i in this._mapView._innerView._layers) {
          const iLayer = this._mapView._innerView._layers[i]
          if (iLayer.__feature__id) {
            if (this._sketchStage.entityGraphic.id === iLayer.__feature__id) {
              const curFeature = this._sketchStage.entityGraphic
              const callbackFun = function (event) {
                self._hitTestILayer = iLayer
                event.lon = event.latlng.lng
                event.lat = event.latlng.lat
                self._hitTestFeature(curFeature, event)
                // 发送草图被选中事件
                self.fire('selected', { isSelected: true }, self)
              }
              if (mode === 0) {
                iLayer.on('click', (event) => {
                  callbackFun(event)
                })
              } else {
                iLayer.on('mousedown', (event) => {
                  // mouseDown拖动点图形时,地图拖拽事件会触发
                  self._disableMapDrag()
                  callbackFun(event)
                })
              }
            }
          }
        }
      }
    }
  }
}
Zondy.SketchEditor2D = SketchEditor2D
export default SketchEditor2D
构造函数
成员变量
方法
事件