Mike
Mike

Reputation: 799

leaflet editable restrict draw to a specific area

In Leaflet.Editable I want to confine/limit my customers to draw only in a specific area/bounds.

actually im trying to limit them to (90, -90, 180, -180) bounds of map..

maxBounds: [[-90, -180], [90, 180]]

enter image description here enter image description here I was not able to find anything anywhere and it seems that i am missing something.

CODEPEN DEMO

please help.


EDIT:

the Y axis is blocking correctly and mouse cannot stretch shape beyond top and bottom.

the problem is in X axis (as seen in pictures)

as for now i solved it with after save check and clear shape if it out of map bounds (BAD USER EXPERIENCE). i need a mouse confinement just like y axis does.

Upvotes: 4

Views: 3847

Answers (1)

nothingisnecessary
nothingisnecessary

Reputation: 6233

Without knowing your use case (why the whole world map??) Quickest and easiest fix would be to simply set the map's minZoom to something a bit higher, for example, I found that minZoom: 5 was adequate except for cases where the map was both really short and really wide (which is rarely the case in most apps I've seen).

But the real fix involves writing your own custom overrides for dragging markers and shapes.

According to API doc the L.Editable plugin allows you to override a bunch of stuff including the VertexMarker class, via map.editTools.options.vertexMarkerClass.

Fixed codepen: http://codepen.io/anon/pen/GrPpRY?editors=0010

This snippet of code that allows you to constrain the longitude for dragging vertex markers by correcting values under -180 and over 180 is this:

// create custom vertex marker editor
var vertexMarkerClass = L.Editable.VertexMarker.extend({
  onDrag: function(e) {
    e.vertex = this;
    var iconPos = L.DomUtil.getPosition(this._icon),
      latlng = this._map.layerPointToLatLng(iconPos);

    // fix out of range vertex
    if (latlng.lng < -180) {
      e.latlng.lng = latlng.lng = -180;
      this.setLatLng(latlng);
    }
    if (latlng.lng > 180) {
      e.latlng.lng = latlng.lng = 180;
      this.setLatLng(latlng);
    }

    this.editor.onVertexMarkerDrag(e);

    this.latlng.update(latlng);
    this._latlng = this.latlng; // Push back to Leaflet our reference.
    this.editor.refresh();
    if (this.middleMarker) this.middleMarker.updateLatLng();
    var next = this.getNext();
    if (next && next.middleMarker) next.middleMarker.updateLatLng();
  }
});

// attach custom editor
map.editTools.options.vertexMarkerClass = vertexMarkerClass;

I didn't code for dragging the shape as a whole (the rectangle, in this case). While the VertexMarker fix should address all kinds of vertex dragging, you need to override each shape's drag handler to properly constrain the bounds. And if bounds are exceeded, crop the shape appropriately. As was pointed out, Leaflet already does this for latitude, but because Leaflet allows wrapping the map around horizontally you have your essential problem. Using rec.on("drag") to correct the bounds when they cross over your min/max longitude is the only way to address it. It is basically the same solution as I have laid out for the vertexMarkerClass - actual code left as exercise for the diligent reader.

Upvotes: 1

Related Questions