class MapDrawingManager {
constructor(mapSelector) {
this.mapSelector = mapSelector;
this.hasUnsavedChanges = false;
this.hasMultiPolygon = false;
}
setupDrawControls() {
const drawOptions = {
position: "topright",
draw: {
polyline: false,
circlemarker: false,
marker: false,
circle: {
shapeOptions: {
color: "#00394D",
fillColor: "#00394D",
fillOpacity: 0.2,
weight: 2,
},
showRadius: true,
metric: true,
},
rectangle: {
shapeOptions: {
color: "#00394D",
fillColor: "#00394D",
fillOpacity: 0.2,
weight: 2,
},
},
polygon: {
allowIntersection: false,
drawError: {
color: "#f03e3e",
message: "Erreur: Les polygones ne peuvent pas s'intersecter!",
},
shapeOptions: {
color: "#00394D",
fillColor: "#00394D",
fillOpacity: 0.2,
weight: 2,
},
},
},
edit: {
featureGroup: this.mapSelector.drawnItems,
remove: true,
poly: {
allowIntersection: false,
},
edit: {
selectedPathOptions: {
maintainColor: true,
fillOpacity: 0.3,
}
}
},
};
this.mapSelector.drawControl = new L.Control.Draw(drawOptions);
this.mapSelector.map.addControl(this.mapSelector.drawControl);
}
disableEditingForMultiPolygon(geoJSON) {
if (geoJSON.geometry && geoJSON.geometry.type === 'MultiPolygon') {
this.hasMultiPolygon = true;
if (this.mapSelector.drawControl) {
const currentOptions = this.mapSelector.drawControl.options;
const newOptions = {
...currentOptions,
edit: {
...currentOptions.edit,
edit: false
}
};
this.mapSelector.map.removeControl(this.mapSelector.drawControl);
this.mapSelector.drawControl = new L.Control.Draw(newOptions);
this.mapSelector.map.addControl(this.mapSelector.drawControl);
this.replaceDrawIcons();
}
}
}
updateMultiPolygonState() {
const hasMultiPolygon = this.mapSelector.selectedAreas.some(area =>
area.geometry && area.geometry.type === 'MultiPolygon'
);
if (!hasMultiPolygon && this.hasMultiPolygon) {
this.hasMultiPolygon = false;
if (this.mapSelector.drawControl) {
const currentOptions = this.mapSelector.drawControl.options;
const newOptions = {
...currentOptions,
edit: {
...currentOptions.edit,
edit: true
}
};
this.mapSelector.map.removeControl(this.mapSelector.drawControl);
this.mapSelector.drawControl = new L.Control.Draw(newOptions);
this.mapSelector.map.addControl(this.mapSelector.drawControl);
this.replaceDrawIcons();
}
}
}
setupMapEvents() {
this.mapSelector.map.on(L.Draw.Event.CREATED, this._handleDrawCreated.bind(this));
this.mapSelector.map.on(L.Draw.Event.DELETED, this._handleDrawDeleted.bind(this));
this.mapSelector.map.on('draw:edited', (e) => {
const layers = e.layers;
const updatedAreas = [];
this.mapSelector.drawnItems.eachLayer((layer) => {
if (layer instanceof L.Circle) {
const center = layer.getLatLng();
const radius = layer.getRadius();
updatedAreas.push({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [center.lng, center.lat]
},
properties: {
type: 'circle',
radius: radius
}
});
} else if (layer instanceof L.Polygon || layer instanceof L.Rectangle) {
const geoJSON = layer.toGeoJSON();
const existingArea = this.mapSelector.selectedAreas.find(area =>
area.geometry.type === 'Polygon' &&
area.properties?.name === geoJSON.properties?.name
);
if (existingArea) {
updatedAreas.push({
...existingArea,
geometry: geoJSON.geometry
});
} else {
updatedAreas.push(geoJSON);
}
}
});
this.mapSelector.selectedAreas = updatedAreas;
this.mapSelector.uiManager.updateSelectedAreasList();
});
this.mapSelector.map.on('editable:editing', () => {
this.hasUnsavedChanges = true;
});
this.mapSelector.map.on('draw:editstart', () => {
this.mapSelector.isEditing = true;
const confirmBtn = document.querySelector('#confirmSelectionBtn');
const closeBtn = document.querySelector('.mapSelectorCloseBtn');
if (confirmBtn) confirmBtn.classList.add('disabled');
if (closeBtn) closeBtn.classList.add('disabled');
});
this.mapSelector.map.on('draw:editstop', () => {
this.mapSelector.isEditing = false;
const confirmBtn = document.querySelector('#confirmSelectionBtn');
const closeBtn = document.querySelector('.mapSelectorCloseBtn');
if (confirmBtn) confirmBtn.classList.remove('disabled');
if (closeBtn) closeBtn.classList.remove('disabled');
});
}
replaceDrawIcons() {
const iconMappings = {
'.leaflet-draw-draw-polygon': '',
'.leaflet-draw-draw-rectangle': '',
'.leaflet-draw-draw-circle': '',
'.leaflet-draw-edit-edit': '',
'.leaflet-draw-edit-remove': ''
};
Object.entries(iconMappings).forEach(([selector, html]) => {
const element = document.querySelector(selector);
if (element) element.innerHTML = html;
});
this.mapSelector.map.on(L.Draw.Event.DRAWSTART, () => {
setTimeout(() => this.replaceActionIcons(), 100);
});
}
replaceActionIcons() {
const actionMappings = {
'Cancel': ' Annuler',
'Finish': ' Terminer',
'Delete last point': ' Supprimer dernier point'
};
const actionButtons = document.querySelectorAll('.leaflet-draw-actions a');
actionButtons.forEach(btn => {
const text = btn.textContent.trim();
if (actionMappings[text]) {
btn.innerHTML = actionMappings[text];
}
});
}
_handleDrawCreated(event) {
const layer = event.layer;
const type = event.layerType;
let geoJSON = layer.toGeoJSON();
if (type === 'circle') {
this._setupCircleProperties(layer, geoJSON);
}
this.mapSelector.drawnItems.addLayer(layer);
this.mapSelector.selectedAreas.push(geoJSON);
this.mapSelector.uiManager.updateSelectedAreasList();
}
_setupCircleProperties(layer, geoJSON) {
const radius = layer.getRadius();
geoJSON.properties = geoJSON.properties || {};
geoJSON.properties.radius = radius;
geoJSON.properties.type = 'circle';
const radiusText = this.mapSelector.geoJSONHandler._formatRadiusText(radius);
layer.bindPopup(`Rayon: ${radiusText}`);
layer.on('edit', (e) => this._handleCircleEdit(e, geoJSON));
}
_handleCircleEdit(e, geoJSON) {
const newRadius = e.target.getRadius();
const index = this.mapSelector.selectedAreas.findIndex(area =>
area.geometry.coordinates[0] === geoJSON.geometry.coordinates[0] &&
area.geometry.coordinates[1] === geoJSON.geometry.coordinates[1]
);
if (index >= 0) {
this.mapSelector.selectedAreas[index].properties.radius = newRadius;
}
const newRadiusText = this.mapSelector.geoJSONHandler._formatRadiusText(newRadius);
e.target.setPopupContent(`Rayon: ${newRadiusText}`);
this.mapSelector.uiManager.updateSelectedAreasList();
}
_handleDrawDeleted(event) {
const layers = event.layers;
layers.eachLayer((layer) => {
const geoJSON = layer.toGeoJSON();
this.mapSelector.selectedAreas = this.mapSelector.selectedAreas.filter(area =>
JSON.stringify(area) !== JSON.stringify(geoJSON)
);
});
this.updateMultiPolygonState();
this.mapSelector.uiManager.updateSelectedAreasList();
}
_handleDrawEdited(event) {
const layers = event.layers;
layers.eachLayer((layer) => {
const geoJSON = layer.toGeoJSON();
if (layer instanceof L.Circle) {
this._updateCircleProperties(layer, geoJSON);
} else {
this._updatePolygonProperties(geoJSON);
}
});
this.mapSelector.uiManager.updateSelectedAreasList();
}
_updateCircleProperties(layer, geoJSON) {
const radius = layer.getRadius();
const center = layer.getLatLng();
geoJSON.properties = geoJSON.properties || {};
geoJSON.properties.radius = radius;
geoJSON.properties.type = 'circle';
const newRadiusText = this.mapSelector.geoJSONHandler._formatRadiusText(radius);
const areaInSqMeters = Math.PI * Math.pow(radius, 2);
const areaText = this.mapSelector.geoJSONHandler._formatAreaText(areaInSqMeters);
layer.setPopupContent(`Rayon: ${newRadiusText}
Surface: ${areaText}`);
for (let i = 0; i < this.mapSelector.selectedAreas.length; i++) {
const area = this.mapSelector.selectedAreas[i];
if (this._isMatchingCircle(area, center)) {
this.mapSelector.selectedAreas[i].properties.radius = radius;
this.mapSelector.selectedAreas[i].geometry.coordinates = [center.lng, center.lat];
break;
}
}
}
_isMatchingCircle(area, center) {
if ((area.geometry.type === 'Point' && area.properties &&
(area.properties.type === 'circle' || area.properties.radius))) {
const areaLat = area.geometry.coordinates[1];
const areaLng = area.geometry.coordinates[0];
return Math.abs(areaLat - center.lat) < 0.1 && Math.abs(areaLng - center.lng) < 0.1;
}
return false;
}
_updatePolygonProperties(geoJSON) {
for (let i = 0; i < this.mapSelector.selectedAreas.length; i++) {
const area = this.mapSelector.selectedAreas[i];
if (area.geometry.type === geoJSON.geometry.type) {
this.mapSelector.selectedAreas[i].geometry = geoJSON.geometry;
break;
}
}
}
// ... autres méthodes de gestion du dessin
}