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