mapview_interactions_modify.mjs

/**
## Mapview.interactions.modify()

@module /mapview/interactions/modify

@param {Object} params
The params object argument.
*/

export default function(params){

  const mapview = this
  
  // Finish the current interaction.
  mapview.interaction?.finish()

  mapview.interaction = {

    type: 'modify',

    finish,
  
    format: new ol.format.GeoJSON(),

    source: new ol.source.Vector(),

    Layer: new ol.layer.Vector({
      zIndex: Infinity
    }),
  
    vertices: [],

    modifyend: mapp.ui?.elements.contextMenu.modify.bind(this),
  
    getFeature,

    Style: [
      new ol.style.Style({
        image: new ol.style.Circle({
          stroke: new ol.style.Stroke({
            color: '#3399CC',
            width: 1.25
          }),
          radius: 5
        }),
        stroke: new ol.style.Stroke({
          color: '#3399CC',
          width: 1.25
        })
      }),
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 5,
          fill: new ol.style.Fill({
            color: '#eee',
          }),
          stroke: new ol.style.Stroke({
            color: '#3399CC',
            width: 1.25
          })
        }),
        geometry: mapp.utils.verticeGeoms
      })
    ],

    deleteCondition: e => {

      if (e.type === 'singleclick') {

        const geom = mapview.interaction.Feature.getGeometry()

        const geomType = geom.getType()

        if (geomType === 'Point') return;

        const coords = geom.getCoordinates()

        // Return on point or line with 2 vertices.
        if (geomType === 'LineString' && coords.length < 3) return;

        // Return on polygon with less than 3 vertices.
        if (geomType === 'Polygon' && coords[0].length <= 4) return;
     
        // Set popup to remove vertex.
        mapview.popup({
          coords: geom.getClosestPoint(e.coordinate),
          content: mapp.utils.html.node`<ul>
            <li
              onclick=${() => {
              mapview.interaction.interaction.removePoint()
              mapview.interaction.vertices.push(mapview.interaction.Feature.getGeometry().getClosestPoint(e.coordinate))
            }}>${mapp.dictionary.delete_vertex}`
        })
      }
    },
    
    // Spread params argument.
    ...params
  }

  mapview.Map.getTargetElement().style.cursor = 'crosshair'

  mapview.interaction.source.addFeature(mapview.interaction.Feature)
   
  // Set mapview.interaction.Layer source.
  mapview.interaction.Layer.setSource(mapview.interaction.source)

  // Set mapview.interaction.Layer style
  mapview.interaction.Layer.setStyle(mapview.interaction.Style)
  
  // Add mapview.interaction.Layer to mapview.
  mapview.Map.addLayer(mapview.interaction.Layer)
   
  mapview.interaction.interaction = new ol.interaction.Modify(mapview.interaction)

  // Will clear remove vertex popup.
  mapview.interaction.interaction.on('modifystart', e => {
    mapview.popup(null)
  })

  if (typeof mapview.interaction.modifyend === 'function') {

    mapview.interaction.interaction.on('modifyend', mapview.interaction.modifyend)
  }

  // Add OL interaction to mapview.Map
  mapview.Map.addInteraction(mapview.interaction.interaction)

  // Assign snap interaction.
  mapview.interactions.snap(mapview)
 
  function getFeature() {
     
    return JSON.parse(
      mapview.interaction.format.writeFeature(
        mapview.interaction.Feature,
        { 
          dataProjection: 'EPSG:' + mapview.interaction.srid || mapview.srid,
          featureProjection: 'EPSG:' + mapview.srid
        })
    )
  }
  
  function finish(feature) {

    // Remove snap interaction.
    mapview.interaction.snap?.remove?.()

    // Reset the cursor style.
    mapview.Map.getTargetElement().style.cursor = 'default'
  
    // Remove popup from mapview.
    mapview.popup(null)
    
    // Remove interaction from mapview.Map.
    mapview.Map.removeInteraction(mapview.interaction.interaction)

    // Clear the modify source.
    mapview.interaction.source.clear()
  
    // Remove draw Layer from mapview.Map.
    mapview.Map.removeLayer(mapview.interaction.Layer)

    mapview.interaction.callback?.(feature)
  }
}