Leaflet.draw icon indicating copy to clipboard operation
Leaflet.draw copied to clipboard

Angular - Resize Circle

Open fabiopachecooss opened this issue 3 years ago • 8 comments

  • [x ] I'm reporting a bug, not asking for help
  • [ ] I've looked at the documentation to make sure the behaviour is documented and expected
  • [ ] I'm sure this is a Leaflet Draw code issue, not an issue with my own code nor with the framework I'm using (Cordova, Ionic, Angular, React…)
  • [ ] I've searched through the issues to make sure it's not yet reported

How to reproduce

when try to resize the circle

  • Leaflet version I'm using:
  • Leaflet Draw version I'm using:
  • Browser (with version) I'm using:
  • OS/Platform (with version) I'm using:
  • step 1
  • step 2

https://user-images.githubusercontent.com/83339630/116379608-783c6100-a813-11eb-8924-0561784dd34d.mp4

  • "@asymmetrik/ngx-leaflet": "^8.1.0", "@asymmetrik/ngx-leaflet-draw": "^7.0.0", "leaflet": "^1.7.1", "leaflet-draw": "^1.0.4",

What behaviour I'm expecting and which behaviour I'm seeing

Minimal example reproducing the issue

ERROR ReferenceError: radius is not defined at NewClass._resize (leaflet.draw.js:9) at NewClass._onMarkerDrag (leaflet.draw.js:9) at NewClass.fire (leaflet-src.js:588) at NewClass._onDrag (leaflet-src.js:7333) at NewClass.fire (leaflet-src.js:588) at NewClass._updatePosition (leaflet-src.js:5929) at ZoneDelegate.invokeTask (zone-evergreen.js:399) at Object.onInvokeTask (core.js:41686) at ZoneDelegate.invokeTask (zone-evergreen.js:398) at Zone.runTask (zone-evergreen.js:167)

  • [x ] this example is as simple as possible
  • [ ] this example does not rely on any third party code

Using jsfiddle or another example site.

fabiopachecooss avatar Apr 28 '21 09:04 fabiopachecooss

drawnItems: L.FeatureGroup = L.featureGroup();
	options = {
		layers: [
			L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: 'Open Street Map' })
		],
		zoom: 5,
		center: L.latLng({ lat: 46.879966, lng: -121.726909 })
	};

	drawOptions = {
		position: 'topright',
		draw: {
			marker: {
				icon: L.icon({
					iconSize: [ 25, 41 ],
					iconAnchor: [ 13, 41 ],
					    iconUrl: 'leaflet/marker-icon.png',
      iconRetinaUrl: 'leaflet/marker-icon-2x.png',
      shadowUrl: 'leaflet/marker-shadow.png'
				})
			},
      circle: {
        shapeOptions: {
            color: '#aaaaaa'
        }
      }
		},
    
		edit: {
			featureGroup: this.drawnItems
		}
	};

	drawLocal: any = {
		draw: {
			toolbar: {
				buttons: {
					polygon: 'Draw an awesome polygon!'
				}
			}
		}
	};

  public onDrawCreated(e: any) {
		console.log('Draw Created Event!');

		const layer = (e as L.DrawEvents.Created).layer;
		this.drawnItems.addLayer(layer);
	}

	public onDrawStart(e: any) {
		console.log('Draw Started Event!');
	}

  onMapReady(map: L.Map) {}

fabiopachecooss avatar Apr 28 '21 09:04 fabiopachecooss

<div leaflet style="height: 700px"
     leafletDraw
     [leafletOptions]="options"
     [leafletDrawOptions]="drawOptions"
     [leafletDrawLocal]="drawLocal"
     (leafletDrawCreated)="onDrawCreated($event)"
     (leafletDrawStart)="onDrawStart($event)">

	<!-- Add the drawnItems featureGroup to the map -->
	<div [leafletLayer]="drawnItems"></div>

</div>

fabiopachecooss avatar Apr 28 '21 09:04 fabiopachecooss

We get the same error. And we created this issue 3 years ago, without any response. https://github.com/Leaflet/Leaflet.draw/issues/945

It looks like a declaration of variable (var radius) would save the error. But they need to approve the pull request.

claudia9 avatar Aug 23 '22 10:08 claudia9

I think it was a missing variable declaration, should be fixed with this PR: https://github.com/Leaflet/Leaflet.draw/pull/1053

poet-of-the-fall avatar Nov 11 '22 08:11 poet-of-the-fall

I am also having this same issue. @poet-of-the-fall Has this been resolved yet?

ferily7 avatar Apr 18 '23 23:04 ferily7

It should be fixed with PR, but if you don't want find another plugin you can try this solution:

L.Edit.Circle is the class controlling the edition of the circle and it has a method call _resize. If a class is already defined, you can replace how a class method works using L.Class.include().

In our case:

L.Edit.Circle.include({
	_resize(){
		var moveLatLng = this._moveMarker.getLatLng();
		
		var radius = this._map.distance(moveLatLng, latlng);
			
		this._shape.setRadius(radius);

		if (this._map._editTooltip) {
			this._map._editTooltip.updateContent({
				text: L.drawLocal.edit.handlers.edit.tooltip.subtext + '<br />' + L.drawLocal.edit.handlers.edit.tooltip.text,
				subtext: L.drawLocal.draw.handlers.circle.radius + ': ' +
				L.GeometryUtil.readableDistance(radius, true, this.options.feet, this.options.nautic)
				});
			}

		this._shape.setRadius(radius);

		this._map.fire(L.Draw.Event.EDITRESIZE, {layer: this._shape});
	}
});

antoniovlx avatar Sep 20 '23 10:09 antoniovlx

// Solution pour le redimensionnement du cercle avec Leaflet

// Après avoir rencontré des difficultés avec le redimensionnement du cercle dans Leaflet, j'ai développé une solution qui a fonctionné efficacement.

// Étapes de la solution : // 1. Création d'un marqueur personnalisé : J'ai créé un marqueur personnalisé et j'ai ajusté son icône pour qu'il ressemble à l'outil de dessin par défaut. // 2. Suivi du dernier marqueur ajouté : J'ai mis en place un mécanisme pour garder la trace du dernier marqueur ajouté au cercle, ce qui me permet de contrôler le redimensionnement de manière précise. // 3. Suppression des autres marqueurs : Pour éviter toute confusion, j'ai supprimé tous les autres marqueurs de redimensionnement une fois que le dernier marqueur est ajouté. // 4. Rendre l'ancien marqueur invisible : Pour assurer une manipulation fluide du cercle, j'ai utilisé une requête jQuery pour rendre l'ancien marqueur invisible.

public addCircleListenersOSM(circle: L.Circle) { document.querySelectorAll('.leaflet-marker-icon.leaflet-div-icon.leaflet-editing-icon.leaflet-edit-resize.leaflet-touch-icon.leaflet-zoom-animated.leaflet-interactive.leaflet-marker-draggable').forEach((element) => { // Assurez-vous que l'élément est un HTMLElement avant d'accéder à la propriété 'style' if (element instanceof HTMLElement) { const width = parseInt(element.style.width, 10); const height = parseInt(element.style.height, 10);

    if (width === 20 && height === 20) {
      // Cet élément correspond aux dimensions spécifiées, le rendre invisible
      element.style.opacity = '0';
    }
  }
});
 this.initializeResizeMarker(circle);

// Gestion du déplacement du cercle
circle.on('move', (event) => {
  const newCenter = event.target.getLatLng();
   this.updateResizeMarkerPosition(circle);
});

// Gestion du redimensionnement du cercle via le marqueur de redimensionnement
this.resizeMarker.on('drag', (event) => {
  const newLatLng = event.target.getLatLng();
  const newRadius = circle.getLatLng().distanceTo(newLatLng);
  circle.setRadius(newRadius);
  this.updateResizeMarkerPosition(circle); // Optionnel si vous voulez déplacer le marqueur de redimensionnement pendant le drag
});

}

private initializeResizeMarker(circle: L.Circle) { const resizeMarkerLatLng = this.calculatePointOnCircle(circle.getLatLng(), circle.getRadius());

this.removeExistingMarker(this.resizeMarker);

this.resizeMarker = L.marker(resizeMarkerLatLng, {
  draggable: true,
  icon: L.divIcon({
    className: 'leaflet-marker-icon leaflet-div-icon leaflet-editing-icon leaflet-touch-icon leaflet-zoom-animated leaflet-interactive leaflet-marker-draggable'
  ,iconSize: [21, 21]})
}).addTo(this.openMap);

}

private updateResizeMarkerPosition(circle: L.Circle) { if (this.resizeMarker) { const newLatLng = this.calculatePointOnCircle(circle.getLatLng(), circle.getRadius()); this.resizeMarker.setLatLng(newLatLng); } }

private removeExistingMarker(marker: L.Marker | null) { if (marker) { this.openMap.removeLayer(marker); } }

// Méthode pour calculer la position du marqueur de redimensionnement sur le bord du cercle private calculatePointOnCircle(center: L.LatLng, radius: number): L.LatLng { // Utiliser une approximation simple pour positionner le marqueur sur le bord du cercle const angle = Math.PI / 2; // 90 degrés en radians pour simplifier const dx = radius * Math.cos(angle); const dy = radius * Math.sin(angle); const earthRadiusMeters = 6371000; const dLat = dy / earthRadiusMeters * (180 / Math.PI); const dLng = dx / (earthRadiusMeters * Math.cos(Math.PI * center.lat / 180)) * (180 / Math.PI);

return L.latLng(center.lat + dLat, center.lng + dLng); } appeler cette methode au bon endroit .Cette approche m'a permis de manipuler le cercle proprement ! .

AdliAB avatar Feb 08 '24 14:02 AdliAB