UNPKG

kmap-ui

Version:

A components of zmap base on vue2.X

303 lines (277 loc) 9.49 kB
/* Copyright (c) 2016 Jean-Marc VIGLINO, released under the CeCILL-B license (French BSD license) (http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt). */ import ol_ext_inherits from '../util/ext' import {unByKey as ol_Observable_unByKey} from 'ol/Observable' import ol_interaction_CenterTouch from './CenterTouch' import ol_style_Style from 'ol/style/Style' import ol_style_Circle from 'ol/style/Circle' import ol_style_Stroke from 'ol/style/Stroke' import ol_style_Fill from 'ol/style/Fill' import ol_Feature from 'ol/Feature' import ol_layer_Vector from 'ol/layer/Vector' import ol_source_Vector from 'ol/source/Vector' import ol_geom_LineString from 'ol/geom/LineString' import ol_geom_Polygon from 'ol/geom/Polygon' import ol_geom_Point from 'ol/geom/Point' import ol_geom_Circle from 'ol/geom/Circle' import ol_ext_getMapCanvas from '../util/getMapCanvas' import {ol_coordinate_dist2d} from '../geom/GeomUtils' /** Interaction DrawTouch : * @constructor * @fires drawstart * @fires drawend * @extends {ol_interaction_CenterTouch} * @param {olx.interaction.DrawOptions} options * @param {ol_source_Vector | undefined} options.source Destination source for the drawn features. * @param {ol.geom.GeometryType} options.type Drawing type ('Point', 'LineString', 'Polygon') not ('MultiPoint', 'MultiLineString', 'MultiPolygon' or 'Circle'). Required. * @param {boolean} options.tap enable on tap, default true * @param {ol_style_Style|Array<ol_style_Style>} options.targetStyle a style to draw the target point, default cross style * @param {string} options.composite composite operation : difference|multiply|xor|screen|overlay|darken|lighter|lighten|... */ var ol_interaction_DrawTouch = function(options) { options = options||{}; options.handleEvent = function(e) { if (this.get('tap')) { switch (e.type) { case 'singleclick': { this.addPoint(); break; } case 'dblclick': { this.addPoint(); this.finishDrawing(); return false; //break; } default: break; } } return true; } ol_interaction_CenterTouch.call(this, options); this.typeGeom_ = options.type; this._geometryFunction = options.geometryFunction; this.source_ = options.source; this.set('tap', (options.tap!==false)); // Style var white = [255, 255, 255, 1]; var blue = [0, 153, 255, 1]; var width = 3; var defaultStyle = [ new ol_style_Style({ stroke: new ol_style_Stroke({ color: white, width: width + 2 }) }), new ol_style_Style({ image: new ol_style_Circle({ radius: width * 2, fill: new ol_style_Fill({ color: blue }), stroke: new ol_style_Stroke({ color: white, width: width / 2 }) }), stroke: new ol_style_Stroke({ color: blue, width: width }), fill: new ol_style_Fill({ color: [255, 255, 255, 0.5] }) }) ]; this.overlay_ = new ol_layer_Vector({ source: new ol_source_Vector({useSpatialIndex: false }), style: defaultStyle }); this.geom_ = []; }; ol_ext_inherits(ol_interaction_DrawTouch, ol_interaction_CenterTouch); /** * Remove the interaction from its current map, if any, and attach it to a new * map, if any. Pass `null` to just remove the interaction from the current map. * @param {ol.Map} map Map. * @api stable */ ol_interaction_DrawTouch.prototype.setMap = function(map) { if (this._listener.drawSketch) ol_Observable_unByKey(this._listener.drawSketch); this._listener.drawSketch = null; ol_interaction_CenterTouch.prototype.setMap.call (this, map); this.overlay_.setMap(map); if (this.getMap()){ this._listener.drawSketch = this.getMap().on('postcompose', this.drawSketchLink_.bind(this)); } }; /** Get geometry type * @return {ol.geom.GeometryType} */ ol_interaction_DrawTouch.prototype.getGeometryType = function() { return this.typeGeom_; }; /** Start drawing and add the sketch feature to the target layer. * The ol.interaction.Draw.EventType.DRAWEND event is dispatched before inserting the feature. */ ol_interaction_DrawTouch.prototype.finishDrawing = function() { if (!this.getMap()) return; var valid = true; if (this._feature) { switch (this.typeGeom_) { case 'LineString': { if (this.geom_.length > 1) { this._feature.setGeometry(new ol_geom_LineString(this.geom_)); } else { valid = false; } break; } case 'Polygon': { // Close polygon if (this.geom_[this.geom_.length-1] != this.geom_[0]) { this.geom_.push(this.geom_[0]); } // Valid ? if (this.geom_.length > 3) { this._feature.setGeometry(new ol_geom_Polygon([ this.geom_ ])); } else { valid = false; } break; } default: break; } if (this._feature) this.source_.addFeature (this._feature); this.dispatchEvent({ type: 'drawend', feature: this._feature, valid: valid }); } // reset this.geom_ = []; this.drawSketch_(); this._feature = null; }; /** Add a new Point to the drawing */ ol_interaction_DrawTouch.prototype.addPoint = function() { if (!this.getMap()) return; this.geom_.push(this.getPosition()); var start = false; if (!this._feature) { this._feature = new ol_Feature(); start = true; } switch (this.typeGeom_) { case 'Point': this._feature.setGeometry(new ol_geom_Point(this.geom_.pop())); break; case 'LineString': case 'Polygon': case 'Circle': this.drawSketch_(); break; default: break; } // Dispatch events if (start) { this.dispatchEvent({ type: 'drawstart', feature: this._feature }); } if (this.typeGeom_ ==='Point' || (this.typeGeom_==='Circle' && this.geom_.length>1) ) { this.finishDrawing(); } }; /** Remove last point of the feature currently being drawn. */ ol_interaction_DrawTouch.prototype.removeLastPoint = function() { if (!this.getMap()) return; this.geom_.pop(); this.drawSketch_(); }; /** Draw sketch * @private */ ol_interaction_DrawTouch.prototype.drawSketch_ = function() { if (!this.overlay_) return; this.overlay_.getSource().clear(); if (this.geom_.length) { var geom = new ol_geom_LineString(this.geom_); switch (this.typeGeom_) { case 'Circle': { if (!this._feature.getGeometry()) { this._feature.setGeometry(new ol_geom_Circle(this.geom_[0], ol_coordinate_dist2d(this.geom_[0], this.geom_[this.geom_.length-1]))); } else { this._feature.getGeometry().setCenter(this.geom_[0]); this._feature.getGeometry().setRadius(ol_coordinate_dist2d(this.geom_[0], this.geom_[this.geom_.length-1])); } break; } case 'Polygon': { if (!this._feature.getGeometry()) { this._feature.setGeometry(new ol_geom_Polygon([this.geom_])); } else { this._feature.getGeometry().setCoordinates([this.geom_]); } this.overlay_.getSource().addFeature(new ol_Feature(geom)); break; } default: { if (!this._feature.getGeometry()) { this._feature.setGeometry(new ol_geom_LineString(this.geom_)); } else { this._feature.getGeometry().setCoordinates(this.geom_); } break; } } this.overlay_.getSource().addFeature(this._feature); var f = new ol_Feature( new ol_geom_Point (this.geom_.slice(-1).pop()) ); this.overlay_.getSource().addFeature(f); } }; /** Draw contruction lines on postcompose * @private */ ol_interaction_DrawTouch.prototype.drawSketchLink_ = function(e) { if (!this.getActive() || !this.getPosition()) return; var ctx = e.context || ol_ext_getMapCanvas(this.getMap()).getContext('2d'); ctx.save(); var p, pt = this.getMap().getPixelFromCoordinate(this.getPosition()); var ratio = e.frameState.pixelRatio || 1; ctx.scale(ratio,ratio); ctx.strokeStyle = 'rgba(0, 153, 255, 1)'; ctx.lineWidth = 1; ctx.beginPath(); ctx.arc (pt[0],pt[1], 5, 0, 2*Math.PI); ctx.stroke(); if (this.geom_.length) { if (this.typeGeom_ === 'Circle') { p = this.getMap().getPixelFromCoordinate(this.geom_[0]); var r = ol_coordinate_dist2d(pt, p); ctx.beginPath(); ctx.arc (p[0],p[1], r, 0, 2*Math.PI); ctx.stroke(); } else { p = this.getMap().getPixelFromCoordinate(this.geom_[this.geom_.length-1]); ctx.beginPath(); ctx.moveTo(p[0],p[1]); ctx.lineTo(pt[0],pt[1]); if (this.typeGeom_ == 'Polygon') { p = this.getMap().getPixelFromCoordinate(this.geom_[0]); ctx.lineTo(p[0],p[1]); } ctx.stroke(); } } ctx.restore(); }; /** * Activate or deactivate the interaction. * @param {boolean} active Active. * @observable * @api */ ol_interaction_DrawTouch.prototype.setActive = function(b) { ol_interaction_CenterTouch.prototype.setActive.call (this, b); if (!b) this.geom_ = []; this.drawSketch_(); }; export default ol_interaction_DrawTouch