When I launch the file everything works fine and the mouse movements are correct however the zoom is catastrophic and it does not zoom/refresh the next tiles of OpenStreetMap
class CustomMap {
constructor(containerId) {
this.container = document.getElementById(containerId);
if (!this.container) {
console.error(`Element with ID '${containerId}' not found.`);
return;
}
this.tileContainer = document.createElement('div');
this.tileContainer.classList.add('tile-container');
this.container.appendChild(this.tileContainer);
this.zoomLevels = [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Niveaux de zoom disponibles
this.zoomIndex = 2; // Index du niveau de zoom initial
this.tileSize = 256; // Taille d'une tuile
this.center = { x: 0, y: 0 }; // Centre initial de la carte
this.tiles = {}; // Pour stocker les tuiles chargées
this.initMap();
this.enableDrag();
this.enableZoom();
}
initMap() {
this.updateTiles();
}
updateTiles() {
const zoomLevel = this.zoomLevels[this.zoomIndex];
const tilesInViewportX = Math.ceil(this.container.offsetWidth / this.tileSize);
const tilesInViewportY = Math.ceil(this.container.offsetHeight / this.tileSize);
const startX = Math.max(0, Math.floor(this.center.x - tilesInViewportX / 2));
const startY = Math.max(0, Math.floor(this.center.y - tilesInViewportY / 2));
const endX = startX + tilesInViewportX;
const endY = startY + tilesInViewportY;
// Supprimer les tuiles qui ne sont plus visibles
for (let key in this.tiles) {
const tilePos = key.split('_').map(Number);
if (tilePos[0] < startX || tilePos[0] >= endX || tilePos[1] < startY || tilePos[1] >= endY) {
this.tiles[key].remove();
delete this.tiles[key];
}
}
// Ajouter les tuiles manquantes
for (let x = startX; x < endX; x++) {
for (let y = startY; y < endY; y++) {
const key = `${x}_${y}`;
if (!this.tiles[key]) {
const tile = document.createElement('img');
tile.classList.add('tile');
tile.src = `https://a.tile.openstreetmap.org/${zoomLevel}/${x}/${y}.png`;
tile.style.width = `${this.tileSize}px`;
tile.style.height = `${this.tileSize}px`;
tile.style.position = 'absolute';
tile.style.left = `${(x - startX) * this.tileSize}px`;
tile.style.top = `${(y - startY) * this.tileSize}px`;
this.tiles[key] = tile;
this.tileContainer.appendChild(tile);
}
}
}
// Déplacer le conteneur de tuiles pour simuler le déplacement de la carte
this.tileContainer.style.transform = `translate(${-(this.center.x % 1) * this.tileSize}px, ${-(this.center.y % 1) * this.tileSize}px)`;
}
enableDrag() {
let isDragging = false;
let startX, startY;
let startCenterX, startCenterY;
this.container.addEventListener('mousedown', (event) => {
if (event.button !== 0) return; // Ne rien faire si ce n'est pas le clic gauche
event.preventDefault();
isDragging = true;
startX = event.clientX;
startY = event.clientY;
startCenterX = this.center.x;
startCenterY = this.center.y;
this.container.style.cursor = 'grabbing';
});
document.addEventListener('mouseup', () => {
isDragging = false;
this.container.style.cursor = 'grab';
});
document.addEventListener('mousemove', (event) => {
if (isDragging) {
const deltaX = (event.clientX - startX) / this.tileSize / this.zoomLevels[this.zoomIndex];
const deltaY = (event.clientY - startY) / this.tileSize / this.zoomLevels[this.zoomIndex];
this.center.x = startCenterX - deltaX;
this.center.y = startCenterY - deltaY;
this.updateTiles();
}
});
// Désactiver le défilement de la page lors du déplacement de la carte
this.container.addEventListener('dragstart', (event) => event.preventDefault());
}
enableZoom() {
this.container.addEventListener('wheel', (event) => {
event.preventDefault();
const rect = this.container.getBoundingClientRect();
const mouseX = event.clientX - rect.left;
const mouseY = event.clientY - rect.top;
const oldZoomIndex = this.zoomIndex;
const zoomDelta = event.deltaY < 0 ? 1 : -1;
this.zoomIndex += zoomDelta;
this.zoomIndex = Math.min(Math.max(this.zoomIndex, 0), this.zoomLevels.length - 1);
// Calculer les facteurs de zoom
const oldZoomFactor = this.zoomLevels[oldZoomIndex];
const newZoomFactor = this.zoomLevels[this.zoomIndex];
// Calculer le déplacement relatif du centre de la carte
const deltaX = (mouseX - rect.width / 2) / this.tileSize / oldZoomFactor;
const deltaY = (mouseY - rect.height / 2) / this.tileSize / oldZoomFactor;
// Mettre à jour le centre de la carte
this.center.x += deltaX * (oldZoomFactor - newZoomFactor);
this.center.y += deltaY * (oldZoomFactor - newZoomFactor);
// Mettre à jour les tuiles
this.updateTiles();
});
}
}
// Utilisation de la bibliothèque
const customMap = new CustomMap('mapContainer');
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ma Carte</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="mapContainer" style="width: 800px; height: 600px;"></div>
<script src="searchAreaMap.js"></script>
<script>
const customMap = new CustomMap('mapContainer');
</script>
</body>
</html>
It should zoom perfectly where the mouse cursor is and the tiles should update when I zoom (a bit like if you zoom in on your house on Google Maps for example) I tried different corrections in the JS and SAME CHATGPT!
New contributor
SearchArea France is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.