geoman-io / leaflet-geoman

🍂🗺️ The most powerful leaflet plugin for drawing and editing geometry layers
https://geoman.io
MIT License
2.21k stars 433 forks source link

Events for `pm:globalrotatemodetoggled` emitted when they should not be #1259

Closed igorshmukler closed 11 months ago

igorshmukler commented 1 year ago

Hello,

I am trying to integrate 'leaflet-editable-marker' with 'leaflet-geoman'. I used to have a custom rotate button, but since the modern geoman supports rotate, I decided to integrate my code. Build the below to handle this:

  map.on('pm:globalrotatemodetoggled', function (e) {
    const { enabled } = e;
    console.log('pm:globalrotatemodetoggled, enabled:', enabled);
    console.log('in rotate mode:', map.pm.globalRotateModeEnabled());
    // XXX FIXME
    // we should not need `rotate`, but instead call `globalRotateModeEnabled()`
    if (enabled && enabled !== rotate) {
      rotate = enabled;
      // enableRotate();
    } else if (!enabled && rotate) {
      // XXX FIXME
      // disableRotate() removes _transformationToolbar
      // no idea how to add it back
      rotate = false;
      disableRotate();
    }
  });

Please excuse the temporary code. I did discover that for no apparent reason, geoman throws a bunch of events when there is no change for the rotate.

I added console.log to both editable marker and leaflet package sources, and it prints the following:

finished _setTransformationRuler, this._transformationRuler: NewClass {options: {…}, _latlng: LatLng, _initHooksCalled: true, pm: NewClass, _events: {…}}
leaflet.editableMarker.js:173 updateTransformation #2
map.editor.js:845 update
leaflet-src.js:6739 LayerGroup clear
leaflet-src.js:6717 LayerGroup remove
leaflet-src.js:6766 LayerGroup onRemove
map.editor.js:118 pm:globalrotatemodetoggled, enabled: false
map.editor.js:119 in rotate mode: false
map.editor.js:118 pm:globalrotatemodetoggled, enabled: true
map.editor.js:119 in rotate mode: true

These pm:globalrotatemodetoggled state changes are triggered by the below:

          layer.on('click', (e) => {
            if (rotate) {
              // if (layer._transformationRuler) {
              //   layer.finishTransformation();
              // }

              layer.activateTransformation();
            }
            propagateClick(e.target.properties);
          });

Specifically, the problem occurs while executing layer.activateTransformation() which is a method from the "editable marker" package. I don't know geoman well, so I don't see what could be triggering the rotate status change. To make it easier, below is the code for activateTransformation.

    activateTransformation: function () {
      console.log('activateTransformation');
      var iconOptions = this.options.icon.options;
      var xPercent = ((iconOptions.iconAnchor[0] / iconOptions.iconSize[0]) * 100);
      var yPercent = ((iconOptions.iconAnchor[1] / iconOptions.iconSize[1]) * 100);
      var that = this;
      this._icon.style.transformOrigin = xPercent + "% " + yPercent + "%";
      if (!this.transformationActivated) {
        this.transformationActivated = true;
        this.registerTransformationDragHandler();
      }
      this.updateTransformation();
      return that;
    },
    updateTransformation: function () {
      console.log('updateTransformation');
      var that = this;
      that._setTransformationRuler();
      console.log('updateTransformation #2');
      that._transformationMouseDown = false;
      that._transformationRuler.addTo(that._map);
      that._transformationRuler.on('mousedown', beginTransformation);
      that._transformationRuler.on('mouseup', stopTransformation);
      that._initRulerElement();
      that._map.on('mousemove', moveTransformation);
      function beginTransformation() {
        that._savedDragging = that._map.dragging;
        that._map.dragging.disable();
        that._transformationMouseDown = true;
      }
      function mobileMoveTransformation(e) {
        if (that._transformationMouseDown) {
          var touches = e.changedTouches, lastTouch = touches[touches.length - 1];
          var newLatLng = that._map.layerPointToLatLng(that._map.mouseEventToLayerPoint({
            clientX: lastTouch.pageX,
            clientY: lastTouch.pageY
          }));
          moveTransformation({ latlng: newLatLng });
        }
      }
      function moveTransformation(e) {
        if (that._transformationMouseDown) {
          var pointB = new L.LatLng(e.latlng.lat, e.latlng.lng);
          that._transformationRuler.setLatLng(pointB);
          that._setAngle();
          that.fire('rotateend');
        }
      }
      function stopTransformation() {
        if (that._transformationMouseDown) {
          that._transformationMouseDown = false;
          that._map.dragging.enable();
          that._setAngle();
          that.fire('rotateend');
        }
      }
    },
    _setTransformationRuler: function () {
      console.log('--------------------');
      console.log('_setTransformationRuler');
      if (this._transformationRuler) {
        console.log('removing ruler');
        this._map.removeLayer(this._transformationRuler);
      }
      var size = this.getSize();
      var transformation = new L.Transformation(1, Math.sin(this.options.angle * Math.PI / 180) * (size[1]), 1, Math.cos(this.options.angle * Math.PI / 180) * (0 - size[1]));
      var pointB = this._map.layerPointToLatLng(transformation.transform(this._map.latLngToLayerPoint(this._latlng)));
      this._transformationRuler = new origin(pointB, {
        icon: this._rulerIcon
      });
      console.log('finished _setTransformationRuler, this._transformationRuler:', this._transformationRuler);
    },

Why is the event emitted when I understand it should not be? What could flip the status back and forth? Is this a geoman bug, or am I doing something wrong? I am happy to change whatever is necessary in my code and/or in editable marker. I just don't understand what causes the problem, so I am at loss as to what has to be adjusted.

Falke-Design commented 1 year ago

I tried to reproduce your problem without success. Please create a demo: https://jsfiddle.net/nzmb18es/

matthewtboyle commented 11 months ago

I just spent the last few days dealing with a similar issue.

Devs can correct me if I'm wrong but in order to show rotation vertices, geoman will throttle global rotation mode if you add a rotatable item to the map while globalRotateModeEnabled() is true. I recently was working with this in a similar situation where I was adding my own temp polygons to be able to rotate markers.

I know it's a year later but I hope this can help someone that might find themselves in a similar sitaution. In your code it looks like the only culprit of the rotation mode throttle I think could be this line that._transformationRuler.addTo(that._map);

If transformationRuler is a polygon/polyline then that is likely your issue.

Falke-Design commented 11 months ago

@matthewtboyle thank you, I found now the problem. I opened a new issue to have a better description #1412