UNPKG

ol-ext-datatable

Version:
214 lines (199 loc) 6.98 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 from 'ol' import ol_interaction_Pointer from 'ol/interaction/pointer' import ol_style_Style from 'ol/style/style' import ol_style_Stroke from 'ol/style/stroke' import ol_source_Vector from 'ol/source/vector' import ol_style_Fill from 'ol/style/fill' import ol_style_Circle from 'ol/style/circle' import ol_layer_Vector from 'ol/layer/vector' import ol_coordinate from 'ol/coordinate' import ol_geom_Point from 'ol/geom/point' import ol_Feature from 'ol/feature' import ol_geom_LineString from 'ol/geom/linestring' /** Offset interaction for offseting feature geometry * @constructor * @extends {ol_interaction_Pointer} * @fires offsetstart * @fires offsetting * @fires offsetend * @param {any} options * @param {ol.layer.Vector | Array<ol.layer.Vector>} options.layers list of feature to transform * @param {ol.Collection.<ol.Feature>} options.features collection of feature to transform * @param {ol.source.Vector | undefined} options.source source to duplicate feature when ctrl key is down * @param {boolean} options.duplicate force feature to duplicate (source must be set) */ var ol_interaction_Offset = function(options) { if (!options) options = {}; // Extend pointer ol_interaction_Pointer.call(this, { handleDownEvent: this.handleDownEvent_, handleDragEvent: this.handleDragEvent_, handleMoveEvent: this.handleMoveEvent_, handleUpEvent: this.handleUpEvent_ }); // Collection of feature to transform this.features_ = options.features; // List of layers to transform this.layers_ = options.layers ? (options.layers instanceof Array) ? options.layers:[options.layers] : null; // duplicate this.set('duplicate', options.duplicate); this.source_ = options.source; // init this.previousCursor_ = false; }; ol.inherits(ol_interaction_Offset, ol_interaction_Pointer); /** * 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_Offset.prototype.setMap = function(map) { ol_interaction_Pointer.prototype.setMap.call (this, map); }; /** Get Feature at pixel * @param {ol.MapBrowserEvent} evt Map browser event. * @return {any} a feature and the hit point * @private */ ol_interaction_Offset.prototype.getFeatureAtPixel_ = function(e) { var self = this; return this.getMap().forEachFeatureAtPixel(e.pixel, function(feature, layer) { var current; // feature belong to a layer if (self.layers_) { for (var i=0; i<self.layers_.length; i++) { if (self.layers_[i]===layer) { current = feature; break; } } } // feature in the collection else if (self.features_) { self.features_.forEach (function(f) { if (f===feature) { current = feature } }); } // Others else { current = feature; } // Only poygon or linestring var typeGeom = current.getGeometry().getType(); if (current && /Polygon|LineString/.test(typeGeom)) { if (typeGeom==='Polygon' && current.getGeometry().getCoordinates().length>1) return false; // test distance var p = current.getGeometry().getClosestPoint(e.coordinate); var dx = p[0]-e.coordinate[0]; var dy = p[1]-e.coordinate[1]; var d = Math.sqrt(dx*dx+dy*dy) / e.frameState.viewState.resolution; if (d<5) { return { feature: current, hit: p, coordinates: current.getGeometry().getCoordinates(), geom: current.getGeometry().clone(), geomType: typeGeom } } else { return false; } } else { return false; } }, { hitTolerance: 5 }); }; /** * @param {ol.MapBrowserEvent} e Map browser event. * @return {boolean} `true` to start the drag sequence. * @private */ ol_interaction_Offset.prototype.handleDownEvent_ = function(e) { this.current_ = this.getFeatureAtPixel_(e); if (this.source_ && (this.get('duplicate') ||e.originalEvent.ctrlKey)) { this.current_.feature = this.current_.feature.clone(); this.source_.addFeature(this.current_.feature); } if (this.current_) { this.dispatchEvent({ type:'offsetstart', feature: this.current_.feature, offset: 0 }); return true; } else { return false; } }; /** * @param {ol.MapBrowserEvent} e Map browser event. * @private */ ol_interaction_Offset.prototype.handleDragEvent_ = function(e) { var p = this.current_.geom.getClosestPoint(e.coordinate); var d = ol_coordinate.dist2d(p, e.coordinate); switch (this.current_.geomType) { case 'Polygon': { var seg = ol_coordinate.findSegment(p, this.current_.coordinates[0]).segment; if (seg) { var v1 = [ seg[1][0]-seg[0][0], seg[1][1]-seg[0][1] ]; var v2 = [ e.coordinate[0]-p[0], e.coordinate[1]-p[1] ]; if (v1[0]*v2[1] - v1[1]*v2[0] > 0) { d = -d; } var offset = []; for (var i=0; i<this.current_.coordinates.length; i++) { offset.push( ol_coordinate.offsetCoords(this.current_.coordinates[i], i==0 ? d : -d) ); } this.current_.feature.setGeometry(new ol.geom.Polygon(offset)); } break; } case 'LineString': { var seg = ol_coordinate.findSegment(p, this.current_.coordinates).segment; if (seg) { var v1 = [ seg[1][0]-seg[0][0], seg[1][1]-seg[0][1] ]; var v2 = [ e.coordinate[0]-p[0], e.coordinate[1]-p[1] ]; if (v1[0]*v2[1] - v1[1]*v2[0] > 0) { d = -d; } var offset = ol_coordinate.offsetCoords(this.current_.coordinates, d); this.current_.feature.setGeometry(new ol.geom.LineString(offset)); } break; } default: { break; } } this.dispatchEvent({ type:'offsetting', feature: this.current_.feature, offset: d, segment: [p, e.coordinate], coordinate: e.coordinate }); }; /** * @param {ol.MapBrowserEvent} e Map browser event. * @private */ ol_interaction_Offset.prototype.handleUpEvent_ = function(e) { this.dispatchEvent({ type:'offsetend', feature: this.current_.feature, coordinate: e.coordinate }); this.current_ = false; }; /** * @param {ol.MapBrowserEvent} e Event. * @private */ ol_interaction_Offset.prototype.handleMoveEvent_ = function(e) { var f = this.getFeatureAtPixel_(e); if (f) { if (this.previousCursor_ === false) { this.previousCursor_ = e.map.getTargetElement().style.cursor; } e.map.getTargetElement().style.cursor = 'pointer'; } else { e.map.getTargetElement().style.cursor = this.previousCursor_; this.previousCursor_ = false; } }; export default ol_interaction_Offset