ol-ext
Version:
A set of cool extensions for OpenLayers (ol) in node modules structure
302 lines (294 loc) • 9.19 kB
JavaScript
/* Copyright (c) 2019 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_layer_Vector from 'ol/layer/Vector.js'
import ol_style_Style from 'ol/style/Style.js'
import ol_style_RegularShape from 'ol/style/RegularShape.js'
import ol_style_Stroke from 'ol/style/Stroke.js'
import ol_source_Vector from 'ol/source/Vector.js'
import ol_Feature from 'ol/Feature.js'
import ol_geom_Point from 'ol/geom/Point.js'
import ol_geom_LineString from 'ol/geom/LineString.js'
import ol_geom_Polygon from 'ol/geom/Polygon.js'
import ol_geom_Circle from 'ol/geom/Circle.js'
import ol_style_Style_defaultStyle from '../style/defaultStyle.js'
import {ol_coordinate_dist2d} from "../geom/GeomUtils.js";
/** A sketch layer used as overlay to handle drawing sketch (helper for drawing tools)
* @constructor
* @extends {ol/layer/Vector}
* @fires drawstart
* @fires drawend
* @fires drawabort
* @param {*} options
* @param {string} options.type Geometry type, default LineString
* @param {ol_style_Style|Array<ol_style_Style>} options.style Drawing style
* @param {ol_style_Style|Array<ol_style_Style>} options.sketchStyle Sketch style
*/
var ol_layer_SketchOverlay = class ollayerSketchOverlay extends ol_layer_Vector {
constructor(options) {
options = options || {}
var style = options.style || ol_style_Style_defaultStyle(true)
var sketchStyle = options.sketchStyle
if (!sketchStyle) {
sketchStyle = ol_style_Style_defaultStyle()
sketchStyle = [
new ol_style_Style({
image: new ol_style_RegularShape({
points: 4,
radius: 10,
radius2: 0,
stroke: new ol_style_Stroke({
color: [255, 255, 255, .5],
width: 3
})
})
}),
sketchStyle[0].clone()
]
sketchStyle[1].setImage(new ol_style_RegularShape({
points: 4,
radius: 10,
radius2: 0,
stroke: new ol_style_Stroke({
color: [0, 153, 255, 1],
width: 1.25
})
}))
}
super({
name: 'sketch',
source: new ol_source_Vector({ useSpatialIndex: false }),
style: function (f) {
return (f.get('sketch') ? sketchStyle : style)
},
updateWhileAnimating: true,
updateWhileInteracting: true
})
this._geom = []
// Sketch features
this.getSource().addFeatures([
new ol_Feature({
sketch: true,
geometry: new ol_geom_Point([])
}),
new ol_Feature({
sketch: true,
geometry: new ol_geom_LineString([])
}),
new ol_Feature(),
new ol_Feature(new ol_geom_Point([]))
])
this.setGeometryType(options.type)
}
/** Set geometry type
* @param {string} type Geometry type
* @return {string} the current type
*/
setGeometryType(type) {
var t = /^Point$|^LineString$|^Polygon$|^Circle$/.test(type) ? type : 'LineString'
if (t !== this._type) {
this.abortDrawing()
this._type = t
}
return this._type
}
/** Get geometry type
* @return {string} Geometry type
*/
getGeometryType() {
return this._type
}
/** Add a new Point to the sketch
* @param {ol.coordinate} coord
* @return {boolean} true if point has been added, false if same coord
*/
addPoint(coord) {
if (this._lastCoord !== this._position) {
if (!this._geom.length) {
this.startDrawing()
}
this._geom.push(coord)
this._lastCoord = coord
this._position = coord
this.drawSketch()
if (this.getGeometryType() === 'Point') {
this.finishDrawing()
}
if (this.getGeometryType() === 'Circle' && this._geom.length >= 2) {
this.finishDrawing()
}
return true
}
return false
}
/** Remove the last Point from the sketch
*/
removeLastPoint() {
this._geom.pop()
this._lastCoord = this._geom[this._geom.length - 1]
this.drawSketch()
}
/** Strat a new drawing
* @param {*} options
* @param {string} type Geometry type, default the current type
* @param {Array<ol.coordinate>} coordinates a list of coordinates to extend
* @param {ol.Feature} feature a feature to extend (LineString or Polygon only)
* @param {boolean} atstart extent coordinates or feature at start, default false (extend at end)
*/
startDrawing(options) {
options = options || {}
this._geom = []
if (options.type)
this.setGeometryType(options.type)
this.drawSketch()
if (!this._drawing) {
this.dispatchEvent({
type: 'drawstart',
feature: this.getFeature()
})
}
this._drawing = true
}
/** Finish drawing
* @return {ol.Feature} the drawed feature
*/
finishDrawing(valid) {
var f = this.getSource().getFeatures()[2].clone()
var isvalid = !!f
switch (this.getGeometryType()) {
case 'Circle':
case 'LineString': {
isvalid = this._geom.length > 1
break
}
case 'Polygon': {
isvalid = this._geom.length > 2
break
}
}
if (valid && !isvalid)
return false
this._geom = []
this._lastCoord = null
this.drawSketch()
if (this._drawing) {
this.dispatchEvent({
type: 'drawend',
valid: isvalid,
feature: f
})
}
this._drawing = false
return f
}
/** Abort drawing
*/
abortDrawing() {
if (this._drawing) {
this.dispatchEvent({
type: 'drawabort',
feature: this.getFeature()
})
}
this._drawing = false
this._geom = []
this._lastCoord = null
this.drawSketch()
}
/** Set current position
* @param {ol.coordinate} coord
*/
setPosition(coord) {
this._position = coord
this.drawLink()
}
/** Get current position
* @return {ol.coordinate}
*/
getPosition() {
return this._position
}
/** Draw/refresh link
*/
drawLink() {
var features = this.getSource().getFeatures()
if (this._position) {
if (this._lastCoord && this._lastCoord === this._position) {
features[0].getGeometry().setCoordinates([])
} else {
features[0].getGeometry().setCoordinates(this._position)
}
if (this._geom.length) {
if (this.getGeometryType() === 'Circle') {
features[1].setGeometry(new ol_geom_Circle(this._geom[0], ol_coordinate_dist2d(this._geom[0], this._position)))
} else if (this.getGeometryType() === 'Polygon') {
features[1].setGeometry(new ol_geom_LineString([this._lastCoord, this._position, this._geom[0]]))
} else {
features[1].setGeometry(new ol_geom_LineString([this._lastCoord, this._position]))
}
} else {
features[1].setGeometry(new ol_geom_LineString([]))
}
} else {
features[0].getGeometry().setCoordinates([])
features[1].setGeometry(new ol_geom_LineString([]))
}
}
/** Get current feature
*/
getFeature() {
return this.getSource().getFeatures()[2]
}
/** Draw/refresh sketch
*/
drawSketch() {
this.drawLink()
var features = this.getSource().getFeatures()
if (!this._geom.length) {
features[2].setGeometry(null)
features[3].setGeometry(new ol_geom_Point([]))
} else {
if (!this._lastCoord)
this._lastCoord = this._geom[this._geom.length - 1]
features[3].getGeometry().setCoordinates(this._lastCoord)
switch (this._type) {
case 'Point': {
features[2].setGeometry(new ol_geom_Point(this._lastCoord))
break
}
case 'Circle': {
if (!features[2].getGeometry()) {
features[2].setGeometry(new ol_geom_Circle(this._geom[0], ol_coordinate_dist2d(this._geom[0], this._geom[this._geom.length - 1])))
} else {
features[2].getGeometry().setRadius(ol_coordinate_dist2d(this._geom[0], this._geom[this._geom.length - 1]))
}
break
}
case 'LineString': {
if (!features[2].getGeometry()) {
features[2].setGeometry(new ol_geom_LineString(this._geom))
} else {
features[2].getGeometry().setCoordinates(this._geom)
}
break
}
case 'Polygon': {
this._geom.push(this._geom[0])
if (!features[2].getGeometry()) {
features[2].setGeometry(new ol_geom_Polygon([this._geom]))
} else {
features[2].getGeometry().setCoordinates([this._geom])
}
this._geom.pop()
break
}
default: {
console.error('[ol/layer/SketchOverlay~drawSketch] geometry type not supported (' + this._type + ')')
break
}
}
}
}
}
export default ol_layer_SketchOverlay