UNPKG

ol-plot-enhanced

Version:
417 lines (394 loc) 11.9 kB
/** * Created by FDD on 2017/5/15. * @desc PlotDraw */ import { Map } from 'ol' import { Draw as $DrawInteraction, DoubleClickZoom } from 'ol/interaction' import { Style as $Style, Icon as $Icon, Stroke as $Stroke, Fill as $Fill } from 'ol/style' import Feature from 'ol/Feature' import { createBox } from 'ol/interaction/Draw' import Observable from 'observable-emit' import { getuuid, MathDistance, bindAll } from '../Utils/utils' import { BASE_LAYERNAME } from '../Constants' import { createVectorLayer } from '../Utils/layerUtils' import PlotTextBox from '../Geometry/Text/PlotTextBox' import * as Plots from '../Geometry/index' import * as PlotTypes from '../Utils/PlotTypes' class PlotDraw extends Observable { constructor (map, params) { super() if (map && map instanceof Map) { this.map = map } else { throw new Error('传入的不是地图对象!') } this.options = params || {} /** * 交互点 * @type {null} */ this.points = null /** * 当前标绘工具 * @type {null} */ this.plot = null /** * 当前要素 * @type {null} */ this.feature = null /** * 标绘类型 * @type {null} */ this.plotType = null /** * 当前标绘参数 * @type {null} */ this.plotParams = null /** * 当前地图视图 * @type {Element} */ this.mapViewport = this.map.getViewport() /** * 地图双击交互 * @type {null} */ this.dblClickZoomInteraction = null /** * draw交互工具 * @type {null} * @private */ this.drawInteraction_ = null /** * 创建图层名称 * @type {string} */ this.layerName = ((this.options && this.options['layerName']) ? this.options['layerName'] : BASE_LAYERNAME) bindAll([ 'textAreaDrawEnd', 'mapFirstClickHandler', 'mapNextClickHandler', 'mapDoubleClickHandler', 'mapMouseMoveHandler' ], this) /** * 当前矢量图层 * @type {*} */ this.drawLayer = createVectorLayer(this.map, this.layerName, { create: true }) this.drawLayer.setZIndex(this.options['zIndex'] || 99) } /** * 创建Plot * @param type * @param points * @param _params * @returns {*} */ createPlot (type, points, _params) { let params = _params || {} switch (type) { case PlotTypes.TEXTAREA: return 'TextArea' case PlotTypes.POINT: return new Plots.Point([], points, params) case PlotTypes.PENNANT: return new Plots.Pennant([], points, params) case PlotTypes.POLYLINE: return new Plots.Polyline([], points, params) case PlotTypes.ARC: return new Plots.Arc([], points, params) case PlotTypes.CIRCLE: return new Plots.Circle([], points, params) case PlotTypes.CURVE: return new Plots.Curve([], points, params) case PlotTypes.FREEHANDLINE: return new Plots.FreeHandLine([], points, params) case PlotTypes.RECTANGLE: return new Plots.RectAngle([], points, params) case PlotTypes.ELLIPSE: return new Plots.Ellipse([], points, params) case PlotTypes.LUNE: return new Plots.Lune([], points, params) case PlotTypes.SECTOR: return new Plots.Sector([], points, params) case PlotTypes.CLOSED_CURVE: return new Plots.ClosedCurve([], points, params) case PlotTypes.POLYGON: return new Plots.Polygon([], points, params) case PlotTypes.ATTACK_ARROW: return new Plots.AttackArrow([], points, params) case PlotTypes.FREE_POLYGON: return new Plots.FreePolygon([], points, params) case PlotTypes.DOUBLE_ARROW: return new Plots.DoubleArrow([], points, params) case PlotTypes.STRAIGHT_ARROW: return new Plots.StraightArrow([], points, params) case PlotTypes.FINE_ARROW: return new Plots.FineArrow([], points, params) case PlotTypes.ASSAULT_DIRECTION: return new Plots.AssaultDirection([], points, params) case PlotTypes.TAILED_ATTACK_ARROW: return new Plots.TailedAttackArrow([], points, params) case PlotTypes.SQUAD_COMBAT: return new Plots.SquadCombat([], points, params) case PlotTypes.TAILED_SQUAD_COMBAT: return new Plots.TailedSquadCombat([], points, params) case PlotTypes.GATHERING_PLACE: return new Plots.GatheringPlace([], points, params) case PlotTypes.RECTFLAG: return new Plots.RectFlag([], points, params) case PlotTypes.TRIANGLEFLAG: return new Plots.TriangleFlag([], points, params) case PlotTypes.CURVEFLAG: return new Plots.CurveFlag([], points, params) } return null } /** * 激活工具 * @param type * @param params */ active (type, params = {}) { this.disActive() this.deactiveMapTools() this.plotType = type this.plotParams = params if (type === PlotTypes.TEXTAREA) { this.activeInteraction() } else if (Object.keys(PlotTypes).some(key => (PlotTypes[key] === type))) { this.map.on('click', this.mapFirstClickHandler) } else { console.warn('不存在的标绘类型!') } } /** * 激活交互工具 */ activeInteraction () { this.drawInteraction_ = new $DrawInteraction({ style: new $Style({ fill: new $Fill({ color: 'rgba(255, 255, 255, 0.7)' }), stroke: new $Stroke({ color: 'rgba(0, 0, 0, 0.15)', width: 2 }), image: new $Icon({ anchor: [1, 1], anchorXUnits: 'fraction', anchorYUnits: 'fraction', opacity: 0.75, src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABgklEQVQ4T41T0W3CQAy1lfwRqR0h/CE5UhkBJmiZADpB0wlKJwA2aDegE5QR+Igl/noj9OPuLydXPuXQEYUKS5FyPvvd87ONRDRFxEdr7c4Y8ws3WFmW90VRvIjIF1ZVtQaANxH59N6v8zwvRaQEgCMATDu88I+Ipm1bk2XZHhEfAOAdFW00Gh2YOQafOeidHoaYEdGHc65GDZhMJuXpdDJ99hqkPmZe9e9iTgCoqmrWNM0hDerq/FGftXbcZxFzAgARrZg5vBaNiGpE3OhZRF6Zedu7DzkRYMrMKlQKYBBRQVVgw8zj3n3IGWSg9ESkds6tiqJQbe4AYJ6WGVkPAqh4+romdP9LbXMqZh/gXIKqm+d5EK9vbduOY7d0AAdL6AYLmqbRAQtGRMc4ONF/wSC2RF/PsuwbABapqLEjKqb3fq4sLtoYh6Lbiydr7TbtuwYDgH5qB9XmPEjdKG+Y+Xmo7ms+Lcs5N0uX6ei9X9y4TGtEXIZlukb7PzbdmNcisv8DtQILak2vZsYAAAAASUVORK5CYII=' }) }), type: 'Circle', geometryFunction: createBox() }) this.map.addInteraction(this.drawInteraction_) this.drawInteraction_.on('drawend', this.textAreaDrawEnd) } /** * 绘制结束 * @param event */ textAreaDrawEnd (event) { if (event && event.feature) { this.map.removeInteraction(this.drawInteraction_) const extent = event.feature.getGeometry().getExtent() const _center = [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2] const topLeft = this.map.getPixelFromCoordinate([extent[0], extent[1]]) const bottomRight = this.map.getPixelFromCoordinate([extent[2], extent[3]]) const [_width, _height] = [Math.abs(topLeft[0] - bottomRight[0]), Math.abs(topLeft[1] - bottomRight[1])] const _plotText = new PlotTextBox({ id: getuuid(), position: _center, value: '', width: _width, height: _height, style: { width: _width + 'px', height: _height + 'px' } }) if (this.map && this.map instanceof Map && _plotText) { this.map.addOverlay(_plotText) } else { console.warn('未传入地图对象或者plotText创建失败!') } } else { console.info('未获取到要素!') } } /** * 取消激活状态 */ disActive () { this.removeEventHandlers() if (this.drawInteraction_) { this.map.removeInteraction(this.drawInteraction_) this.drawInteraction_ = null } this.points = [] this.plot = null this.feature = null this.plotType = null this.plotParams = null this.activateMapTools() } /** * PLOT是否处于激活状态 * @returns {boolean} */ isDrawing () { return !!this.plotType } /** * 地图事件处理 * 激活工具后第一次点击事件 * @param event */ mapFirstClickHandler (event) { this.map.un('click', this.mapFirstClickHandler) this.points.push(event.coordinate) this.plot = this.createPlot(this.plotType, this.points, this.plotParams) this.feature = new Feature(this.plot) this.feature.set('isPlot', true) this.drawLayer.getSource().addFeature(this.feature) if (this.plotType === PlotTypes.POINT || this.plotType === PlotTypes.PENNANT) { this.plot.finishDrawing() this.drawEnd(event) } else { this.map.on('click', this.mapNextClickHandler) if (!this.plot.freehand) { this.map.on('dblclick', this.mapDoubleClickHandler) } this.map.un('pointermove', this.mapMouseMoveHandler) this.map.on('pointermove', this.mapMouseMoveHandler) } if (this.plotType && this.feature) { this.plotParams['plotType'] = this.plotType this.feature.setProperties(this.plotParams) } } /** * 地图点击事件处理 * @param event * @returns {boolean} */ mapNextClickHandler (event) { if (!this.plot.freehand) { if (MathDistance(event.coordinate, this.points[this.points.length - 1]) < 0.0001) { return false } } this.points.push(event.coordinate) this.plot.setPoints(this.points) if (this.plot.fixPointCount === this.plot.getPointCount()) { this.mapDoubleClickHandler(event) } if (this.plot && this.plot.freehand) { this.mapDoubleClickHandler(event) } } /** * 地图双击事件处理 * @param event */ mapDoubleClickHandler (event) { event.preventDefault() this.plot.finishDrawing() this.drawEnd(event) } /** * 地图事件处理 * 鼠标移动事件 * @param event * @returns {boolean} */ mapMouseMoveHandler (event) { let coordinate = event.coordinate if (MathDistance(coordinate, this.points[this.points.length - 1]) < 0.0001) { return false } if (!this.plot.freehand) { let pnts = this.points.concat([coordinate]) this.plot.setPoints(pnts) } else { this.points.push(coordinate) this.plot.setPoints(this.points) } } /** * 移除事件监听 */ removeEventHandlers () { this.map.un('click', this.mapFirstClickHandler) this.map.un('click', this.mapNextClickHandler) this.map.un('pointermove', this.mapMouseMoveHandler) this.map.un('dblclick', this.mapDoubleClickHandler) } /** * 绘制结束 */ drawEnd (event) { this.dispatchSync('drawEnd', { type: 'drawEnd', originalEvent: event, feature: this.feature }) if (this.feature && this.options['isClear']) { this.drawLayer.getSource().removeFeature(this.feature) } this.disActive() } /** * 添加要素 */ addFeature () { this.feature = new Feature(this.plot) if (this.feature && this.drawLayer) { this.drawLayer.getSource().addFeature(this.feature) } } /** * 取消激活地图交互工具 */ deactiveMapTools () { let interactions = this.map.getInteractions().getArray() interactions.every(item => { if (item instanceof DoubleClickZoom) { this.dblClickZoomInteraction = item this.map.removeInteraction(item) return false } else { return true } }) } /** * 激活已取消的地图工具 * 还原之前状态 */ activateMapTools () { if (this.dblClickZoomInteraction && this.dblClickZoomInteraction instanceof DoubleClickZoom) { this.map.addInteraction(this.dblClickZoomInteraction) this.dblClickZoomInteraction = null } } } export default PlotDraw