> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# Marqueurs SVG Leaflet : aligne la pointe avec iconAnchor

> Positionne des marqueurs SVG dans Leaflet en reliant la pointe visible à iconAnchor. Tiens compte des marges du viewBox, de l’ajustement des proportions et de la taille de l’icône.

Source: https://perfectvector.com/fr/blog/leaflet-svg-marker-anchor

Language: fr
Author: Irene Kim
Published: 2026-10-05T08:00:00+09:00
Updated: 2026-10-05T08:00:00+09:00

Pour un marqueur SVG personnalisé dans Leaflet, définis `iconSize` aux dimensions de l’image affichée et `iconAnchor` à la position en pixels de la pointe visible dans cette image. Mesure depuis le coin supérieur gauche de l’image. Les marges transparentes du SVG comptent dans ces dimensions : la moitié de la largeur et la hauteur entière peuvent donc manquer la pointe d’une épingle asymétrique ou entourée de marges.

Ce guide utilise une épingle originale dont la pointe est à droite du centre du corps. Nous comparons deux cadres sources à deux tailles d’icône dans une carte de navigateur sans tuiles. Si tu possèdes déjà un dessin SVG propre, utilise-le directement ; positionner l’ancrage ne nécessite pas de vectorisation.

## Sépare le dessin, le cadre de l’image et le point de carte

Trois systèmes de coordonnées se rencontrent ici. Le chemin SVG décrit le dessin en unités sources. `iconSize` établit son cadre d’image affiché en pixels. Leaflet place le point de ce cadre indiqué par `iconAnchor` à la position géographique du marqueur. La [référence d’Icon](https://leafletjs.com/reference.html#icon) définit ces options et l’origine de l’ancrage en haut à gauche.

Une épingle classique peut atteindre le milieu du bord inférieur, mais ton dessin peut finir ailleurs. Le comportement par défaut documenté de Leaflet est un ancrage centré lorsqu’une taille est définie. Les valeurs du bas au centre de notre expérience sont une hypothèse explicite que nous testons, pas cette valeur par défaut.

Le [tutoriel officiel des icônes personnalisées](https://leafletjs.com/examples/custom-icons/) montre comment fournir une instance de `L.icon` à un marqueur. Avec un dessin importé, le travail supplémentaire consiste à trouver le point dans son image qui doit toucher la coordonnée de carte.

**La pointe visible et l’ancrage**

![Comparaison conceptuelle d’une épingle de localisation asymétrique dans un canevas avec marges, avec sa pointe décalée d’un réticule puis alignée sur lui](https://perfectvector.com/blog/leaflet-svg-marker-anchor/source-tip-anchor.webp)

*Illustration : tiens compte du cadre entier de l’image pour positionner la pointe visible. L’expérience mesurée dans le navigateur ci-dessous utilise des fichiers SVG créés séparément.*

## Convertis la pointe source en pixels d’icône

La pointe de notre épingle est à la coordonnée source `(40, 80)`. Son cadre serré est `viewBox="0 0 60 80"`. La version avec marges ne change que ce cadre en `viewBox="-20 -10 100 120"` ; les deux fichiers conservent le même chemin et la même ouverture transparente.

La [référence de `viewBox`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) décrit ce rectangle source. L’espace vide qu’il contient accompagne le dessin. Notre [guide de la boîte englobante SVG](https://perfectvector.com/fr/blog/svg-bounding-box) explique pourquoi un canevas et une forme peinte peuvent avoir des limites différentes.

Les deux versions utilisent explicitement `preserveAspectRatio="xMidYMid meet"`. Ce réglage ajuste uniformément le cadre dans le viewport et centre l’espace restant. Consulte la [référence de preserveAspectRatio de MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/preserveAspectRatio) pour ces réglages.

Pour ce mode d’ajustement, appelons `W` et `H` les dimensions de l’icône, `(minX, minY, vbW, vbH)` le viewBox et `(tipX, tipY)` la pointe source :

```text
s = min(W / vbW, H / vbH)
offsetX = (W - vbW * s) / 2
offsetY = (H - vbH * s) / 2
anchorX = (tipX - minX) * s + offsetX
anchorY = (tipY - minY) * s + offsetY
```

Pour l’icône de 60×80 avec marges, `s` vaut `0.6`. Le cadre source de 100×120 occupe 60×72 pixels et laisse quatre pixels au-dessus et au-dessous. La pointe devient `[36, 58]`, en incluant ce décalage vertical. Prendre simplement une fraction de chaque dimension séparément ferait manquer l’étape d’ajustement uniforme.

| Cadre source                 | Taille de l’icône | Ancrage de pointe calculé |
| ---------------------------- | ----------------- | ------------------------- |
| Serré, 0 0 60 80             | 60×80             | \[40, 80]                 |
| Serré, 0 0 60 80             | 90×120            | \[60, 120]                |
| Avec marges, -20 -10 100 120 | 60×80             | \[36, 58]                 |
| Avec marges, -20 -10 100 120 | 90×120            | \[54, 87]                 |

Ces calculs s’appliquent à notre image sans transformation et au réglage `meet` explicitement centré. Un autre alignement, `slice` ou `none` exige le mappage de coordonnées correspondant. Notre [guide des proportions](https://perfectvector.com/fr/blog/svg-preserveaspectratio) couvre ces choix. Des transformations CSS supplémentaires sur l’image du marqueur nécessitent aussi une inspection distincte.

## Vérifie la position dans une carte sans tuiles

Nous avons utilisé Leaflet 1.9.4, la version stable indiquée sur la [page officielle de téléchargement](https://leafletjs.com/download.html). L’expérience charge localement son JavaScript et son CSS de version fixe, sans ajouter de couche de tuiles. Chaque carte projette la coordonnée `[0, 0]` sur un réticule bleu ; elle affiche une image SVG à côté de ce point de référence.

L’inspection source a trouvé un chemin composé identique et aucune image matricielle intégrée dans chaque SVG. Les dimensions d’image du navigateur étaient de 60×80 et 90×120 pixels, comme demandé. Avec le rectangle observé de chaque image, nous avons comparé la position convertie de la pointe au point géographique projeté :

| Source      | Taille de l’icône | Erreur avec l’ancrage supposé au bas au centre | Erreur avec l’ancrage de pointe calculé |
| ----------- | ----------------- | ---------------------------------------------- | --------------------------------------- |
| Serrée      | 60×80             | 10 px à droite                                 | 0 px                                    |
| Serrée      | 90×120            | 15 px à droite                                 | 0 px                                    |
| Avec marges | 60×80             | 6 px à droite, 22 px en haut                   | 0 px                                    |
| Avec marges | 90×120            | 9 px à droite, 33 px en haut                   | 0 px                                    |

Le réticule rejoignait aussi visiblement les pointes corrigées. Ce sont des observations de ce fichier de test créé par nos soins dans un navigateur Chrome, pas une garantie pour tous les SVG, navigateurs ou intégrations de carte. L’épingle avec marges reste plus petite dans le même cadre d’image après correction de son ancrage. La position et la taille du dessin sont des décisions distinctes.

## Copie une base de marqueur fonctionnelle

Enregistre ce HTML complet sous `marker.html` et sers-le depuis un serveur web local. Il charge les fichiers Leaflet de version fixe depuis le CDN lié par la page de téléchargement de Leaflet. Le SVG est encodé en URL d’image : l’exemple n’a donc besoin ni de fichier d’icône ni de service de tuiles. Une connexion Internet est nécessaire pour ces deux fichiers de bibliothèque.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Leaflet SVG tip anchor</title>
<link rel="stylesheet"
      href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<style>
  #map { width: 360px; height: 300px; background: #edf3ef; }
  .cross { position: absolute; z-index: 1000; pointer-events: none;
    width: 24px; height: 24px; transform: translate(-50%, -50%); }
  .cross::before, .cross::after { content: ""; position: absolute;
    background: #006cbe; }
  .cross::before { top: 12px; width: 24px; height: 1px; }
  .cross::after { left: 12px; width: 1px; height: 24px; }
</style>
<div id="map"></div>
<pre id="status">Loading marker…</pre>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="60" height="80" viewBox="-20 -10 100 120" preserveAspectRatio="xMidYMid meet"><path fill="#bf593c" fill-rule="evenodd" d="M30 0 C46 0 60 12 60 28 C60 46 46 54 40 80 C30 62 0 46 0 28 C0 12 14 0 30 0 Z M40 26 A10 10 0 1 0 20 26 A10 10 0 1 0 40 26 Z"/></svg>`;
const size = [60, 80];
const viewBox = [-20, -10, 100, 120];
const sourceTip = [40, 80];
const scale = Math.min(size[0] / viewBox[2], size[1] / viewBox[3]);
const anchor = [
  (sourceTip[0] - viewBox[0]) * scale
    + (size[0] - viewBox[2] * scale) / 2,
  (sourceTip[1] - viewBox[1]) * scale
    + (size[1] - viewBox[3] * scale) / 2
];
const map = L.map("map", {
  zoomControl: false, attributionControl: false,
  dragging: false, scrollWheelZoom: false, doubleClickZoom: false,
  boxZoom: false, keyboard: false, touchZoom: false
}).setView([0, 0], 2);
const position = [0, 0];
const icon = L.icon({
  iconUrl: "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg),
  iconSize: size,
  iconAnchor: anchor
});
const marker = L.marker(position, { icon }).addTo(map);
const container = document.querySelector("#map");
const cross = document.createElement("span");
cross.className = "cross";
container.append(cross);
const point = map.latLngToContainerPoint(position);
cross.style.left = point.x + "px";
cross.style.top = point.y + "px";
(async () => {
  const image = marker.getElement();
  await image.decode();
  const ir = image.getBoundingClientRect();
  const mr = container.getBoundingClientRect();
  const displacement = [
    ir.left + anchor[0] - mr.left - point.x,
    ir.top + anchor[1] - mr.top - point.y
  ];
  document.querySelector("#status").textContent = JSON.stringify({
    version: L.version, size, anchor,
    observedImageSize: [ir.width, ir.height], displacement
  }, null, 2);
})();
</script>
</html>
```

L’état affiché devrait indiquer `anchor: [36, 58]`, une taille d’image de `[60, 80]` et un déplacement nul. Change `size` en `[90, 120]` : le même calcul donne `[54, 87]`. Pour utiliser le cadre serré, change à la fois le `viewBox` du SVG et le tableau JavaScript `viewBox` en `0 0 60 80`. Garde-les cohérents.

Le chemin inclut un contour intérieur circulaire avec `fill-rule="evenodd"`, créant une vraie ouverture. La [référence de fill-rule de MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/fill-rule) explique la règle. L’exemple n’ajoute ni bordure ni transformation au conteneur de carte ; cela demanderait de la prudence pour comparer les rectangles du viewport aux coordonnées du conteneur.

## Examine la destination avant de changer le dessin

Si ton marqueur manque encore sa coordonnée, vérifie dans cet ordre :

1. Confirme que l’image SVG est chargée et que l’élément marqueur a la largeur et la hauteur en pixels prévues.
2. Localise la pointe source réelle, y compris les transformations appliquées dans le SVG.
3. Vérifie le viewBox complet, ses coordonnées minimales et son mode d’ajustement.
4. Recalcule l’ancrage à chaque changement du cadre ou de la taille d’icône.
5. Retire les remplacements CSS sans rapport pendant le test, puis vérifie à nouveau le style final et les tailles d’affichage prévues.

Garde la coordonnée géographique fixe pendant cette vérification. Déplacer cette coordonnée pour compenser les marges d’image masquerait l’erreur de position du dessin.

Il s’agit d’un processus de marqueur dans le navigateur. Un [marqueur SVG QGIS](https://perfectvector.com/fr/blog/qgis-svg-markers) utilise ses propres réglages de destination et sa syntaxe de peinture paramétrée ; conserve un maître SVG ordinaire pour une livraison générale dans les navigateurs.

Si ton icône n’existe qu’en PNG ou JPG et que tu as besoin de contours modifiables, [convertis le dessin avec PerfectVector](https://perfectvector.com/fr/image-to-vector), examine l’ouverture et la pointe, puis enregistre un maître SVG propre. Calcule ensuite son ancrage Leaflet à partir du cadre source final. La vectorisation prépare le dessin ; ton code de carte fournit les lieux et le positionnement. Si le seul problème est un décalage dans un SVG existant, corrige directement son cadre ou son ancrage. Le [guide de vectorisation d’images](https://perfectvector.com/fr/blog/what-is-image-vectorization) explique quand convertir une source matricielle est utile.

## Questions fréquentes

**iconAnchor est-il une latitude et une longitude ?**
Non. C’est une position en pixels dans l’image d’icône affichée, mesurée depuis son coin supérieur gauche. La position géographique du marqueur est fournie séparément.

**Pourquoi mon SVG avec marges reste-t-il petit après correction de son ancrage ?**
Le cadre source vide occupe toujours une partie du cadre d’image. Corriger l’ancrage positionne la pointe ; cela ne supprime pas cet espace vide et n’agrandit pas la forme peinte.

**Faut-il toujours utiliser la moitié de la largeur et la hauteur entière ?**
Utilise cette paire uniquement lorsque le point d’attache visible se trouve réellement là. Notre épingle asymétrique et notre source avec marges nécessitent des valeurs différentes, même si les deux sont des dessins de marqueur de localisation.

**Convertir un PNG en SVG corrige-t-il la position du marqueur ?**
La conversion peut fournir un dessin modifiable. Le cadre source final, les dimensions affichées, l’ancrage et les coordonnées de carte déterminent toujours la position du marqueur.

## Sources

1. [Leaflet — Référence d’Icon](https://leafletjs.com/reference.html#icon) — Dimensions en pixels, origine de l’ancrage, centrage par défaut et alignement géographique.
2. [Leaflet — Marqueurs avec icônes personnalisées](https://leafletjs.com/examples/custom-icons/) — Création d’une icône et affectation à un marqueur.
3. [Leaflet — Téléchargement](https://leafletjs.com/download.html) — Version stable et liens JavaScript et CSS de version fixe.
4. [MDN — viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) — Rectangle de coordonnées source utilisé dans les deux cadres.
5. [MDN — preserveAspectRatio](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/preserveAspectRatio) — Ajustement uniforme et espace restant centré pour xMidYMid meet.
6. [MDN — fill-rule](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/fill-rule) — Règle pair-impair utilisée pour l’ouverture transparente.

## Explore

- [Read the HTML article](https://perfectvector.com/fr/blog/leaflet-svg-marker-anchor)
- [Images SVG dans Cytoscape.js : ajustement et marges](https://perfectvector.com/fr/blog/cytoscape-svg-node-artwork.md)
- [Mesurer un tracé SVG sans confondre les échelles](https://perfectvector.com/fr/blog/measure-svg-path-length.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
