SVG Canvas Path2D : réutiliser les tracés à la bonne taille
Réutilise les tracés SVG sur canvas avec la bonne transformation viewBox, les couleurs, trous et densité de pixels. Suis l’exemple et garde l’original SVG éditable.
Sur cette page
Transmets l’attribut d d’un tracé à new Path2D(d), puis dessine-le avec un contexte canvas. Pour reproduire le SVG, reprends aussi sa correspondance de coordonnées, son rendu et sa règle de remplissage. Le constructeur accepte des données de tracé ; il n’importe pas un document SVG et n’applique pas son viewBox, son CSS ou ses transformations de groupes (constructeur Path2D sur MDN).
Cela compte lorsqu’une icône est correcte en SVG, mais devient petite, décalée, noire ou pleine dans son ouverture sur canvas. L’exemple ci-dessous corrige ces différences avec deux tracés et une transformation d’ajustement explicite. Pars d’une géométrie vectorielle existante si tu en as une. La vectorisation n’est utile que lorsque le dessin à réutiliser existe encore en pixels.
Ce que contient un objet Path2D
Considère les données de tracé comme la description des contours. Les autres instructions SVG existent hors de cette chaîne et ton code de dessin canvas doit fournir celles dont il a besoin.
| Entrée SVG | Responsabilité côté canvas |
|---|---|
Valeur d d’un tracé | Construire la géométrie Path2D |
viewBox et taille affichée | Calculer la transformation de dessin |
fill et fill-rule | Définir fillStyle et transmettre la règle à fill() |
transform du parent ou du tracé | Appliquer séparément la transformation équivalente |
| CSS, dégradés, masques, texte et images | Implémenter le rendu nécessaire ou choisir une autre méthode |
L’exemple utilise des remplissages littéraux, deux tracés enfants directs et aucune autre fonctionnalité SVG. Il est volontairement assez petit pour être examiné. Copier sa boucle d’extraction dans un importateur SVG général ferait perdre les styles hérités et les éléments non pris en charge.
Comparer la source à un canvas non configuré
Cet emblème original comporte un corps arrondi bleu-vert, une pointe orange et une ouverture carrée. Son viewBox commence à (20, 10), pas à (0, 0). Le sous-tracé intérieur suit le même sens que la limite extérieure ; la règle déclarée evenodd compte donc.
Place ce SVG et un canvas dans une page HTML :
<svg id="source" xmlns="http://www.w3.org/2000/svg"
viewBox="20 10 120 80" width="240" height="160">
<path fill="#126d70" fill-rule="evenodd"
d="M40 20 H90 Q110 20 110 40 V60 Q110 80 90 80 H40 Q30 80 30 70 V30 Q30 20 40 20 Z M50 35 H80 V60 H50 Z"/>
<path fill="#f19b38" d="M115 25 L135 50 L115 75 Z"/>
</svg>
<canvas id="result"></canvas>Si tu parcours les deux valeurs d et appelles ctx.fill(new Path2D(d)) sans rien régler d’autre, la géométrie utilise les coordonnées canvas, le rendu et la règle de remplissage par défaut. Elle ne reprend pas automatiquement l’apparence du SVG. La méthode canvas fill() accepte un tracé et une règle explicite evenodd ou nonzero ; nonzero est la valeur par défaut (fill() sur MDN).

Méthode : nous avons rendu ce SVG écrit à la main dans le navigateur, dessiné ses deux tracés avec les deux méthodes canvas et réexécuté le code publié dans une page HTML séparée. La capture est la sortie réelle du navigateur. Elle démontre la gestion des coordonnées et du rendu, pas une conversion PerfectVector.
Faire correspondre le viewBox au canvas
Le comportement SVG par défaut préservant les proportions ajuste le viewBox dans sa zone d’affichage et le centre. La spécification du système de coordonnées SVG définit cette correspondance. Pour cet exemple sans hiérarchie, reproduis xMidYMid meet avec une échelle uniforme et une translation :
scale = min(cssWidth / viewBoxWidth, cssHeight / viewBoxHeight)
tx = (cssWidth - viewBoxWidth * scale) / 2 - viewBoxX * scale
ty = (cssHeight - viewBoxHeight * scale) / 2 - viewBoxY * scaleLes derniers termes retirent l’origine non nulle. À 240 × 160, l’échelle est 2, tx vaut -40 et ty vaut -20. À 300 × 120, l’échelle devient 1.5 ; le viewBox ajusté de 180 pixels de large dispose de 60 pixels d’espace horizontal de chaque côté. La translation est donc (30, -15) après prise en compte de l’origine source.
Utilise le script suivant après le HTML ci-dessus. Il gère les attributs directs des tracés de cet exemple, redessine tout le canvas et distingue taille CSS et taille du bitmap sous-jacent :
const source = document.querySelector("#source");
const vb = source.viewBox.baseVal;
const layers = [...source.querySelectorAll("path")].map(el => ({
path: new Path2D(el.getAttribute("d")),
fill: el.getAttribute("fill"),
rule: el.getAttribute("fill-rule") || "nonzero"
}));
function draw(canvas, cssWidth, cssHeight, dpr = window.devicePixelRatio || 1) {
canvas.style.width = `${cssWidth}px`;
canvas.style.height = `${cssHeight}px`;
canvas.width = Math.round(cssWidth * dpr);
canvas.height = Math.round(cssHeight * dpr);
const ctx = canvas.getContext("2d");
const scale = Math.min(cssWidth / vb.width, cssHeight / vb.height);
const tx = (cssWidth - vb.width * scale) / 2 - vb.x * scale;
const ty = (cssHeight - vb.height * scale) / 2 - vb.y * scale;
const px = canvas.width / cssWidth;
const py = canvas.height / cssHeight;
ctx.setTransform(px * scale, 0, 0, py * scale, px * tx, py * ty);
for (const layer of layers) {
ctx.fillStyle = layer.fill;
ctx.fill(layer.path, layer.rule);
}
}
draw(document.querySelector("#result"), 240, 160);
Définir canvas.width et canvas.height efface et réinitialise le contexte. La fonction définit ensuite toute la transformation et repeint chaque couche ; les appels répétés n’accumulent donc pas les échelles. Elle suppose un viewBox valide de largeur et hauteur positives et des dimensions demandées positives.
px et py utilisent les dimensions réelles arrondies du bitmap. Les coordonnées CSS restent ainsi correctement associées aux pixels alloués même lorsque la densité demandée produit des dimensions fractionnaires. L’exemple MDN de devicePixelRatio explique pourquoi la taille affichée du canvas et ses dimensions en pixels doivent être traitées séparément.
Vérifier séparément taille et densité de pixels
Nous avons transmis explicitement les valeurs DPR 1 et 2 à la même fonction pour deux tailles CSS. Il s’agit d’entrées de densité contrôlées, pas d’une affirmation que nous avons testé deux appareils physiques. Le rapport de pixels indiqué par le navigateur pour l’appel par défaut était 2.
| Taille CSS | Argument DPR | Bitmap canvas observé |
|---|---|---|
| 240 × 160 | 1 | 240 × 160 |
| 240 × 160 | 2 | 480 × 320 |
| 300 × 120 | 1 | 300 × 120 |
| 300 × 120 | 2 | 600 × 240 |
Le centre de l’ouverture est resté transparent dans les quatre cas. Une densité supérieure change la résolution du bitmap ; elle ne corrige pas une mauvaise transformation ni une règle de remplissage manquante. Redessine lorsque les dimensions CSS prévues ou le rapport de pixels de l’appareil changent. Un agrandissement uniquement CSS étire le bitmap déjà présent sur le canvas.
Si la source est déjà incorrecte avant d’atteindre canvas, utilise les vérifications de dimensions et viewBox SVG. Si seul canvas est incorrect, compare d’abord sa transformation et sa gestion du rendu à la référence SVG fonctionnelle.
Préserver la source et choisir la bonne méthode d’import
Garde l’original SVG et ses attributs avec les données de tracé dérivées. Une routine de dessin Path2D est utile lorsque tu contrôles un petit ensemble de contours et leurs styles. Pour un SVG complexe dont seule l’apparence rendue par le navigateur t’intéresse, le charger comme image et dessiner cette image peut éviter de reconstruire toutes ses fonctionnalités. Cette méthode peint toujours dans le bitmap canvas.
Enregistrer la sortie canvas en PNG crée une image matricielle, même si le dessin a commencé avec des tracés vectoriels. L’API d’export canvas produit un blob d’image ; la prise en charge du PNG est requise (toBlob() sur MDN). Garde le SVG pour modifier les tracés plus tard. De même, un fichier SVG peut contenir une image matricielle plutôt que des données de tracé utiles ; le diagnostic des images intégrées aide à distinguer ces cas.
PerfectVector convient lorsqu’il ne reste qu’un PNG ou JPG de ton icône et que tu as besoin de contours réutilisables. Convertis cette image en SVG, puis examine sa silhouette, ses couleurs séparées et ses petites ouvertures avant d’extraire les tracés pour canvas. Un original SVG propre doit passer directement à l’étape de préparation. La vectorisation n’implémente pas la correspondance viewBox, ne copie pas le CSS et ne rend pas un PNG canvas éditable en vecteurs.
Pour une famille complète d’icônes, établis les règles communes de grille et de couleurs du kit d’interface avant de connecter chaque routine de dessin. Tu trouveras d’autres exemples de préparation SVG dans le blog.
Avant d’utiliser le dessin dans ton interface
- Vérifie la référence SVG aux mêmes dimensions d’affichage que le canvas.
- Confirme l’origine du viewBox ainsi que sa largeur et sa hauteur.
- Transfère les couleurs et la règle de remplissage prévue ; examine chaque ouverture.
- Tiens compte des transformations de groupes au lieu de copier seulement
d. - Lis les
canvas.widthetcanvas.heightréels, puis teste la plus grande taille d’affichage prévue. - Préserve l’original SVG et fournis un nom accessible ou un texte environnant adapté à l’interface.
FAQ
Path2D peut-il importer tout un fichier SVG ? Non. Son entrée chaîne est constituée de données de tracé SVG, comme la valeur de l’attribut d d’un tracé. La structure du document, la correspondance viewBox, les styles et les transformations de groupes nécessitent une gestion distincte.
Pourquoi le trou de mon SVG s’est-il rempli sur canvas ? Vérifie la règle de remplissage et le sens des sous-tracés. Cet exemple nécessite evenodd, alors que fill de canvas utilise nonzero par défaut. Transmets la règle prévue lors du remplissage de l’objet Path2D.
Dessiner des tracés SVG sur canvas préserve-t-il un export vectoriel ? Les tracés restent des instructions de dessin réutilisables dans ton programme, mais exporter canvas en PNG produit des pixels. Garde le SVG original pour l’édition et la livraison vectorielle.
Sources
- MDN — Constructeur Path2D — Définit la chaîne de données de tracé acceptée par le constructeur.
- W3C — Systèmes de coordonnées SVG — Définit l’origine du viewBox, la correspondance de zone d’affichage et l’alignement préservant les proportions.
- MDN — fill() de Canvas — Décrit le remplissage de tracés et les règles evenodd et nonzero.
- MDN — devicePixelRatio — Explique la taille CSS affichée et la résolution sous-jacente du canvas.
- MDN — toBlob() de Canvas — Décrit l’export d’une image matricielle depuis un canvas.
Tu n’as qu’une icône matricielle ? Prépare son SVG avec PerfectVector, vérifie le contour et les ouvertures, puis compare le dessin canvas à ce SVG aux tailles réelles de ton interface.
Plus depuis le blog

Images SVG Graphviz : des illustrations portables
Ajoute un SVG à un nœud Graphviz, examine sa référence d’image et teste les ressources complètes, le diagramme déplacé et une copie de livraison autonome.

Images SVG WeasyPrint : rétablir les logos des PDF
Corrige les logos SVG absents des PDF WeasyPrint avec une URL de base et des dimensions CSS explicites, puis vérifie tracés, proportions et dessin dans le PDF.