Search code examples
leafleteditorleaflet-geoman

Custom transform control for geoman


I am trying to add a custom transform control to geoman, to do certain transformations with polylines and polygons. I see that on edit, geoman draws hint lines above vertices etc. I would like my tool to highlight polylines/polygons with the same type of hints. Below is the skeleton of my action:

const ConvertAction = L.Toolbar2.Action.extend({
  options: {
    toolbarIcon: {
      html:
        '<div class="icon-maps icon-convert" title="Convert point"></div>',
      tooltip: 'Convert point'
    }
  },
  addHooks: () => {
    // draw polygon
    // map.pm.enableDraw();

    changeConvert();
  }
});

function changeConvert() {
  convert = true;
  map.eachLayer(function (layer) {
    if (layer.feature && layer.feature.geometry.type === 'Point') {
      layer._icon.style['pointer-events'] = 'auto';
    }
  });
}

Is there an internal function or something that I could use to outline shapes? When I enable Edit layers tool already built into the geoman, shapes are outlined for me. How could I achieve this from my code without having to reimplement the entire thing?


Solution

  • Thus far, after quickly reviewing geoman code, I was able to come up with:

      const ConvertAction = L.Toolbar2.Action.extend({
        options: {
          toolbarIcon: {
            html:
              '<div class="icon-maps icon-convert" title="Convert point"></div>',
            tooltip: 'Convert point'
          }
        },
        addHooks: () => {
          // draw polygon
          // map.pm.enableDraw();
          if (!convert) changeConvert();
          else disableConvert();
        }
      });
    
      function changeConvert() {
        convert = true;
        map.eachLayer(function (layer) {
          if (
            layer?.feature?.geometry.type === 'Polygon' ||
            layer?.feature?.geometry.type === 'LineString'
          ) {
            const coords = layer.getLatLngs();
    
            const markerGroup = new L.LayerGroup();
            markerGroup._pmTempLayer = true;
    
            const createMarker = (latlng) => {
              const marker = new L.Marker(latlng, {
                draggable: true,
                icon: L.divIcon({ className: 'marker-icon' })
              });
              layer.options.pane =
                (map.pm.globalOptions.panes &&
                  map.pm.globalOptions.panes.vertexPane) ||
                'markerPane';
    
              marker._pmTempLayer = true;
    
              markerGroup.addLayer(marker);
    
              return marker;
            };
    
            const handleRing = (coordsArr) => {
              // if there is another coords ring, go a level deep and do this again
              if (Array.isArray(coordsArr[0])) {
                return coordsArr.map(handleRing, this);
              }
    
              // the marker array, it includes only the markers of vertexes (no middle markers)
              const ringArr = coordsArr.map(createMarker);
    
              return ringArr;
            };
            const markers = handleRing(coords);
            map.addLayer(markerGroup);
          }
        });
      }
    
      function disableConvert() {
        convert = false;
        map.eachLayer(function (layer) {
          if (
            layer.dragging &&
            layer.options?.draggable === true &&
            layer._pmTempLayer === true
          ) {
            console.log('temp layer:', layer);
            map.removeLayer(layer);
          }
        });
        update();
      }
    

    Seems like an excessive amount of code, and reimplementation [and probably not as good the geoman version as I don't fully understand geoman code by far] of existing functionality.

    How do I simplify/fix this?