Skip to content

An elegant OpenLayers extension for editing geometric shapes.

License

jackchoumine/ol-geom-editor

Repository files navigation

ol-geom-editor

An elegant OpenLayers extension for editing geometric shapes. Really easy to use with elegant and intuitive api.

docs and demo

code in github. If helpful, give me a star!

Usage

installation

in node

npm i ol-geom-editor

then

import { GeomEditor } from 'ol-geom-editor'
// import style if need show tool bar
import 'ol-geom-editor/dist/index.css'

const geomEditor = new GeomEditor(olMap) // pass ol map instance

in browser

<!-- import style if need show tool bar -->
<link href="https://unpkg.com/ol-geom-editor/dist/index.css" rel="stylesheet" />
<script src="https://unpkg.com/ol-geom-editor"></script>

then

const { GeomEditor } = window.olGeomEditor

const geomEditor = new GeomEditor(olMap) // pass ol map instance

ol-geom-editor depends on ol, you should import ol firstly!

create a GeomEditor instance

GeomEditor constructor has two params,the second is optional object.

const geomEditor = new GeomEditor(olMapInstance, options)

options has some props:

prop type default desc
showToolBar boolean true render tool bar or not
supportFreehand boolean true support freehand draw or not
drawTypes Array ['Point', 'LineString', 'Polygon', 'Circle'] draw feature types
actions Array ['remove', 'modify', 'translate', 'complete'] operations on feature
layerStyle Style | StyleLike | FlatStyle openLayers default feature style default feature style
selectedStyle StyleLike below feature style is selected

default selected style:

import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style'

const selectedStyle = new Style({
  fill: new Fill({ color: 'rgba(255,255,255,0.5)' }),
  stroke: new Stroke({
    width: 2.5,
    color: 'red',
  }),
  image: new CircleStyle({
    radius: 5,
    stroke: new Stroke({ width: 2.5, color: 'red' }),
  }),
})

GeomEditor has some methods

method desc
addFeatureFromWKT add feature by wkt
addFeatureFromJSON add feature by GeoJSON or GeoJSON Object
enableDraw enable draw interaction
disableDraw disable draw interaction
enableFreehand enable freehand draw
disableFreehand disable freehand draw
select select features
deselect deselect features
enableSelect enable select interaction
disableSelect disable select interaction
enableModify enable modify interaction
disableModify disable modify interaction
enableTranslate enable translate interaction
disableTranslate disable translate interaction
removeFeatures remove features
removeAllFeatures remove all features
completeEdit complete edit

add features

You can add feature by WKT or GeoJSON.

addFeatureFromWKT(wkt:string, id?:string, dataProjection?:string | FeatureOptions): Feature | null

param type default optional desc
wkt string required WKT
id string | number random string id of feature
dataProjection string | FeatureOptions 'EPSG:4326' EPSG projection

FeatureOptions is a Object :

prop type default optional desc
dataProjection string 'EPSG:4326' EPSG projection
featureProjection string 'EPSG:3857' map projection
style StyleLike default ol feature style feature style

addFeatureFromJSON(JSON:string | geoJSONObj, dataProjection?:string | FeatureOptions): Feature | null

examples

const lineWKT = 'LINESTRING(106.55773424492708 26.68974989181626,106.79592190619702 26.712142565234185)'
geomEditor.addFeatureFromWKT(lineWKT, 'test', 'EPSG:3857')
const pointJSON = JSON.stringify({
  type: 'Feature',
  feature: {
    type: 'Point',
    coordinates: [106.51521987473564, 26.73992541007939],
  },
  properties: null,
  id: 'p2CQqn2lFk',
})
geomEditor.addFeatureFromJSON(pointJSON, 'EPSG:3857')

const circle = {
  type: 'Feature',
  feature: {
    type: 'Polygon',
    coordinates: [
      [
        [106.66476503874576, 26.738016763637745],
        [106.68640913786953, 26.736111276601743],
        [106.70721936319747, 26.730468229538047],
        [106.72639420813869, 26.721305014609847],
        [106.74319560707363, 26.708974566151827],
        [106.75697747969463, 26.69395167555302],
        [106.76721062138205, 26.676814601696407],
        [106.77350297396065, 26.658222705723794],
        [106.77561450846642, 26.63889099150018],
        [106.77346617656862, 26.619562548517454],
        [106.76714262863425, 26.6009799682551],
        [106.75688864282368, 26.58385683635614],
        [106.7430994506547, 26.568850391436218],
        [106.7263053711149, 26.556536388677117],
        [106.70715137023352, 26.54738711575494],
        [106.68637234032467, 26.541753384449873],
        [106.66476503874576, 26.539851168674797],
        [106.64315773716687, 26.541753384449873],
        [106.62237870725802, 26.54738711575494],
        [106.60322470637662, 26.556536388677117],
        [106.58643062683683, 26.568850391436218],
        [106.57264143466786, 26.58385683635614],
        [106.5623874488573, 26.6009799682551],
        [106.55606390092291, 26.619562548517454],
        [106.55391556902511, 26.63889099150018],
        [106.55602710353088, 26.658222705723794],
        [106.56231945610948, 26.676814601696407],
        [106.5725525977969, 26.69395167555302],
        [106.5863344704179, 26.708974566151827],
        [106.60313586935284, 26.721305014609847],
        [106.62231071429407, 26.730468229538047],
        [106.64312093962201, 26.736111276601743],
        [106.66476503874576, 26.738016763637745],
      ],
    ],
  },
  properties: {
    geometryType: 'circle',
    center3857: [11873867.329697348, 3078433.290578392],
    center: [106.66476503874576, 26.638933966156273],
    radius: 11017.51961571537,
  },
}
geomEditor.addFeatureFromJSON(circle, { featureProjection: 'EPSG:3857' })

draw feature

enableDraw(type: GeomType, style?: Style | StyleLike | FlatStyle)

param type default optional desc
type string required draw feature type
style Style | StyleLike | FlatStyle ol default sketch style sketch style

type pass None to draw nothing.

disableDraw() -- disable draw interaction.

enableFreehand() -- enable freehand draw interaction.

disableFreehand() -- disable freehand draw interaction.

select feature

select(id: Id | Id[], options?: SelectOptions): Feature[]

select some features.

param type default optional desc
id string | string[] required feature id
options SelectOptions Object below

options is a object , props :

prop type default optional desc
selectedStyle Style | StyleLike | FlatStyle below selected style
eachFeature function traverse features
fit boolean | viewFitOptions Object true fit selected feature to view

default selected style:

import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style'

const highlightStyle = new Style({
  fill: new Fill({ color: 'rgba(255,255,255,0.5)' }),
  stroke: new Stroke({
    width: 2.5,
    color: 'red',
  }),
  image: new CircleStyle({
    radius: 5,
    stroke: new Stroke({ width: 2.5, color: 'red' }),
  }),
})

eachFeature return truthy value, will stop traverse.

examples

const fillColor = 'rgba(218,228,194,0.5)'
const strokeColor = 'rgba(255, 204, 51, 0.9)'

const features = geomEditor.select(['line1', 'p2CQqn2lFk'], {
  selectedStyle: new Style({
    fill: new Fill({
      color: fillColor,
    }),
    stroke: new Stroke({
      color: strokeColor,
      width: 4,
    }),
    image: new CircleStyle({
      radius: 7,
      fill: new Fill({ color: fillColor }),
      stroke: new Stroke({ color: strokeColor, width: 2 }),
    }),
  }),
  eachFeature: (feat: Feature, index: number) => {
    console.log({ feat })
    if (index === 0) return true
  },
})

deselect feature

deselect(id: Id | Id[], options?: DeselectOptions)

options is a object, props:

prop type default optional desc
deselectedStyle Style | StyleLike | FlatStyle deselected style
eachFeature function traverse features

examples

geomEditor.deselect(['line1', 'p2CQqn2lFk'])

select interaction

enableSelect(options?: SelectModeOptions) -- enable select interaction

options is a object, set select mode

prop type default optional desc
multi boolean true select multiple features
single boolean false only can select one feature

translate interaction support multi mode default, modify interaction support single mode only.

disableSelect() -- disable select interaction

modify feature

enableModify(style?: StyleLike | FlatStyle) -- enable modify interaction

disableModify() -- disable modify interaction

translate features

enableTranslate() -- enable translate interaction

disableTranslate() -- disable translate interaction

translate interaction support multi mode default, modify interaction support single mode only.

remove feature

removeFeatures(id?: Id | Id[]) - remove features

param type default optional desc
id string | string[] feature id

if don't pass id, will remove all selected features.

removeAllFeatures():Promise<boolean> -- remove all features

examples

geomEditor.removeFeatures() // remove all selected features
geomEditor.removeFeatures('test') // remove one feature by id
geomEditor.removeFeatures(['test1', 'test2']) // remove features by id array
geomEditor.removeAllFeatures().then(success => {
  console.log({ success })
})

complete edit

completeEdit() -- complete edit

All style of features will reset original status.

events

GeomEditor trigger some events when interact with features.

GeomEditor trigger custom events and trigger ol interaction event.

Custom events have a better name over ol, like drawBegin is better than drawbegin in ol event style name in my opinion.

All events includes soma data you can use directly and align with the original event.

event list:

event when emit
select select feature
deselect deselect feature
drawBegin begin draw feature
drawComplete finish draw feature
modifyBegin begin modify feature
modifyComplete finish modify feature
translateBegin begin translate features
translateComplete finish translate features
remove remove feature
complete complete edit feature

The original event will also be triggered during interacting.

Recommend use GeomEditor events, because it has converted feature to WKT and GeoJSON and include data in original event. More convenient!

examples

// original event
geomEditor.on('modifystart', event => {
  console.log({ event })
})
// original event
geomEditor.on('modifyend', event => {
  console.log({ event })
})
// NOTE GeomEditor event, you can get data including original event
geomEditor.on('modifyBegin', event => {
  console.log({ event })
})
geomEditor.on('modifyComplete', event => {
  console.log({ event })
})
geomEditor.on('remove', event => {
  console.log({ event })
})
geomEditor.on('complete', event => {
  console.log({ event })
})

Open the console panel on this page, operate the demo, and check the events.

🤝 Contributing

Contributions are always welcome! Feel free to open an issue, suggest a feature, or submit a pull request.

⭐ Support

If you find this project helpful, please consider giving it a star ⭐ — it helps others discover the project and keeps us motivated! give me a star