类名 Widget/Draw/DrawControl.js
import { Zondy, defaultValue, Feature } from '@mapgis/webclient-common'
import Widget from '../Widget'
import {
  Circle,
  LineString,
  Polygon,
  Point
} from '@mapgis/webclient-common'

/**
 * 绘制工具
 * @class DrawControl
 * @moduleEX ViewModule
 * @extends Widget
 * @param {Object} options 构造参数
 * @param {complete} [options.complete] 绘制完成后的回调函数
 * @example <caption><h7>初始化绘制工具</h7></caption>
 * // ES5引入方式
 * const { Map, MapView } = Zondy
 * const { DrawControl } = Zondy.Widget
 * // ES6引入方式
 * import { Map, MapView, DrawControl } from "@mapgis/webclient-leaflet-plugin"
 * // 初始化图层管理容器
 * const map = new Map();
 * // 初始化地图视图对象
 * const mapView = new MapView({
 *   // 视图id
 *   viewId: "viewer-id",
 *   // 图层管理容器
 *   map: map
 * });
 * // 初始化绘制控件
 * const drawControl = new DrawControl({
 *   view: mapView,
 *   visible: true,
 *   complete: function (type, feature) {
 *     console.log("绘制类型:", type, ",绘制完成:", feature);
 *     featureLayer.add(feature);
 *   }
 * })
 * // 开始绘制
 * drawControl.start('lineString', {})
 *
 * @example <caption><h7>通过控件进行绘制</h7></caption>
 * // ES5引入方式
 * const { Map, MapView } = Zondy
 * const { DrawControl } = Zondy.Widget
 * // ES6引入方式
 * import { Map, MapView, DrawControl } from "@mapgis/webclient-leaflet-plugin"
 * // 初始化图层管理容器
 * const map = new Map();
 * // 初始化地图视图对象
 * const mapView = new MapView({
 *   // 视图id
 *   viewId: "viewer-id",
 *   // 图层管理容器
 *   map: map
 * });
 * // 初始化绘制控件
 * const drawControl = new DrawControl({
 *   view: mapView,
 *   visible: true,
 *   complete: function (type, feature) {
 *     console.log("绘制类型:", type, ",绘制完成:", feature);
 *     featureLayer.add(feature);
 *   }
 * })
 * // 添加控件
 * mapView.ui.add(drawControl)
 */

/**
 * 绘制完成的回调函数
 * @callback complete
 * @param {Object} result 回调参数
 * @param {String} [result.type] 几何类型
 * @param {Feature} [result.feature] 绘制完成后返回的要素对象
 * @param {Object} [result.drawConfig] 绘制配置
 */
class DrawControl extends Widget {
  constructor(options) {
    super(options)
    options = defaultValue(options, {})
    this.drawConfig = defaultValue(options.drawConfig, {
      polygon: {
        allowIntersection: false,
        showArea: true
      },
      circlemarker: false
    })
    this._complete = defaultValue(options.complete, function () {})
    this._drawHandler = null
    this._drawTool = null
    this._initHandler()
    this._initStyles()
  }

  _initHandler() {
    const mapView = this._view.getInnerView()
    this._processEvent = this._processEvent.bind(this)
    if (mapView) {
      mapView.on(L.Draw.Event.CREATED, this._processEvent)
    }
  }

  _initStyles() {
    this.styles = {
      circle: {
        shapeOptions: {
          stroke: true,
          color: '#3388ff',
          weight: 4,
          opacity: 0.5,
          fill: true,
          fillColor: null, // same as color by default
          fillOpacity: 0.2,
          clickable: true
        },
        showRadius: true,
        metric: true, // Whether to use the metric measurement system or imperial
        feet: true, // When not metric, use feet instead of yards for display
        nautic: false // When not metric, not feet use nautic mile for display
      },
      marker: {
        icon: new L.Icon.Default(),
        repeatMode: false,
        zIndexOffset: 2000 // This should be > than the highest z-index any markers
      },
      polygon: {
        showArea: false,
        showLength: false,
        shapeOptions: {
          stroke: true,
          color: '#3388ff',
          weight: 4,
          opacity: 0.5,
          fill: true,
          fillColor: null, // same as color by default
          fillOpacity: 0.2,
          clickable: true
        },
        // Whether to use the metric measurement system (truthy) or not (falsy).
        // Also defines the units to use for the metric system as an array of
        // strings (e.g. `['ha', 'm']`).
        metric: true,
        feet: true, // When not metric, to use feet instead of yards for display.
        nautic: false, // When not metric, not feet use nautic mile for display
        // Defines the precision for each type of unit (e.g. {km: 2, ft: 0}
        precision: {}
      },
      polyline: {
        allowIntersection: true,
        repeatMode: false,
        drawError: {
          color: '#b00b00',
          timeout: 2500
        },
        guidelineDistance: 20,
        maxGuideLineLength: 4000,
        shapeOptions: {
          stroke: true,
          color: '#3388ff',
          weight: 4,
          opacity: 0.5,
          fill: false,
          clickable: true
        },
        metric: true, // Whether to use the metric measurement system or imperial
        feet: true, // When not metric, to use feet instead of yards for display.
        nautic: false, // When not metric, not feet use nautic mile for display
        showLength: true, // Whether to display distance in the tooltip
        zIndexOffset: 2000, // This should be > than the highest z-index any map layers
        factor: 1, // To change distance calculation
        maxPoints: 0 // Once this number of points are placed, finish shape
      },
      rectangle: {
        shapeOptions: {
          stroke: true,
          color: '#3388ff',
          weight: 4,
          opacity: 0.5,
          fill: true,
          fillColor: null, // same as color by default
          fillOpacity: 0.2,
          clickable: true
        },
        showArea: true, // Whether to show the area in the tooltip
        metric: true // Whether to use the metric measurement system or imperial
      }
    }
  }

  _removeHandler() {
    const mapView = this._view.getInnerView()
    if (mapView) {
      mapView.off(L.Draw.Event.CREATED, this._processEvent)
    }
  }

  _processEvent(event) {
    if (event && event.layer) {
      // 查询几何类型
      let type, feature
      const geoJSON = event.layer.toGeoJSON()
      type = geoJSON.geometry.type
      switch (type) {
        case 'LineString':
          feature = new Feature({
            geometry: new LineString({
              coordinates: geoJSON.geometry.coordinates
            })
          })
          break
        case 'Polygon':
          feature = new Feature({
            geometry: new Polygon({
              coordinates: geoJSON.geometry.coordinates
            })
          })
          break
        case 'Point':
          let geometry
          if (event.layer._mRadius) {
            geometry = new Circle({
              center: [
                geoJSON.geometry.coordinates[0],
                geoJSON.geometry.coordinates[1]
              ],
              radius: event.layer._mRadius
            })
          } else if (event.layer._radius) {
            geometry = new Circle({
              center: [
                geoJSON.geometry.coordinates[0],
                geoJSON.geometry.coordinates[1]
              ],
              radius: event.layer._radius
            })
          } else {
            geometry = new Point({
              coordinates: geoJSON.geometry.coordinates
            })
          }
          feature = new Feature({
            geometry: geometry
          })
          break
      }
      this._complete(type, feature)
    }
  }

  _addView() {
    super._addView()
    const mapView = this._view.getInnerView()
    if (mapView && this._visible) {
      // 添加绘制控件
      const drawnItems = L.featureGroup().addTo(mapView)
      this._drawTool = new L.Control.Draw({
        edit: {
          featureGroup: drawnItems,
          poly: {
            allowIntersection: false
          }
        },
        draw: this.drawConfig
      })

      mapView.addControl(this._drawTool)
    }
  }

  _removeView() {
    super._removeView()
    const mapView = this._view.getInnerView()
    if (mapView && this._visible) {
      this._removeHandler()
      if (this._drawTool) {
        mapView.removeControl(this._drawTool)
        this._print = null
      }
    }
  }

  /**
   * @description 开始绘制
   * @param {String} type 绘制类型,lineString,polygon,rectangle,marker,circle
   * @param drawOptions 绘制参数
   */
  start(type, drawOptions) {
    const mapView = this._view.getInnerView()
    if (!mapView) return
    if (this._drawHandler) {
      this._drawHandler.disable()
    }
    switch (type) {
      case 'lineString': {
        this._drawHandler = new L.Draw.Polyline(mapView, {
          ...this.styles['polyline'],
          ...drawOptions
        })
        this._drawHandler.enable()
        break
      }
      case 'polygon': {
        this._drawHandler = new L.Draw.Polygon(mapView, {
          ...this.styles['polygon'],
          ...drawOptions
        })
        this._drawHandler.enable()
        break
      }
      case 'rectangle': {
        this._drawHandler = new L.Draw.Rectangle(mapView, {
          ...this.styles['rectangle'],
          ...drawOptions
        })
        this._drawHandler.enable()
        break
      }
      case 'marker': {
        this._drawHandler = new L.Draw.Marker(mapView, {
          ...this.styles['marker'],
          ...drawOptions
        })
        this._drawHandler.enable()
        break
      }
      case 'circle': {
        this._drawHandler = new L.Draw.Circle(mapView, {
          ...this.styles['circle'],
          ...drawOptions
        })
        this._drawHandler.enable()
        break
      }
    }
  }

  /**
   * @description 结束绘制
   */
  end() {
    if (this._drawHandler) {
      this._drawHandler.disable()
      this._drawHandler = null
    }
  }

  /**
   * @description 销毁控件
   */
  destory() {}
}

Zondy.Widget.DrawControl = DrawControl
export default DrawControl
构造函数
成员变量
方法
事件