SVG feComposite : comparer les dessins avec in, out et xor
Compare les entrées de filtres SVG avec in, out et xor, teste l’ordre des opérandes et l’alpha partiel, et garde les chemins quand une ouverture visuelle n’est pas une géométrie modifiable.
Sur cette page
- Nomme les deux entrées avant de choisir l’opérateur
- Aligne explicitement le second dessin
- Exécute la comparaison originale complète
- Compare séparément la peinture et la géométrie
- L’opacité partielle change le sens d’une ouverture
- Livre un effet de filtre ou crée de vrais contours
- Questions fréquentes
- Sources
feComposite de SVG combine deux entrées rendues. Pour des entrées entièrement opaques, in garde la première dans le chevauchement, out la garde hors du chevauchement et xor combine les deux entrées hors de leur chevauchement commun. Ces opérations changent la peinture au moment du rendu. Elles ne réécrivent pas les chemins sources en intersection ou différence modifiable.
Cette distinction compte lorsqu’un chevauchement ressemble à une ouverture mais que le livrable nécessite de vrais contours. L’exemple ci-dessous compare deux formes asymétriques originales, inverse les entrées et vérifie une transparence partielle. Garde le dessin source à côté du résultat filtré.
Nomme les deux entrées avant de choisir l’opérateur
La référence de feComposite de MDN décrit une opération pixel par pixel dans l’espace image. in nomme la première entrée ; in2 nomme la seconde. Donne des noms explicites aux résultats intermédiaires pour qu’un changement de chaîne de filtres ne change pas silencieusement les opérandes.
Pour des intérieurs opaques, ces trois opérations sont faciles à comparer :
| Opération | Première entrée A, seconde entrée B | Ce que change l’inversion des entrées |
|---|---|---|
in | La peinture de A dans le chevauchement | Le chevauchement porte la peinture de B à la place |
out | La peinture de A hors de B | La peinture de B hors de A est une autre région |
xor | Les deux entrées hors de leur chevauchement opaque commun | Les mêmes régions sans chevauchement restent |
Le même attribut operator apparaît aussi sur d’autres primitives de filtre avec d’autres valeurs. Garde le contexte de composition explicite ; la référence de operator de MDN le distingue des opérations morphologiques.

Aligne explicitement le second dessin
Notre premier opérande A est un bloc en escalier bleu-vert. B est un cerf-volant déformé ocre. Les deux utilisent le même viewBox 0 0 240 160. B dépasse la boîte englobante locale de A : utiliser les limites de A comme région de filtre serait donc une mauvaise hypothèse de départ.
Le filtre utilise filterUnits="userSpaceOnUse" pour sa région explicite x=0, y=0, width=240, height=160. La référence de filterUnits de MDN explique ce choix de coordonnées. Nous définissons aussi primitiveUnits="userSpaceOnUse" et donnons à la seconde entrée les mêmes coordonnées de cadre entier.
B est une URL de données SVG autonome fournie via feImage, avec le nom de résultat operandB. Cela l’introduit dans le filtre comme entrée image ; cela n’insère pas le chemin de B comme nouvel enfant direct du dessin filtré. La référence de feImage de MDN décrit son comportement d’entrée image.
Le filtre choisit explicitement sRGB. La valeur par défaut de ces primitives est linearRGB, comme le documente la référence de feComposite. Ni cette valeur par défaut ni le nom de l’opérateur ne fournit une opération de modification de chemin.
Exécute la comparaison originale complète
Enregistre ceci sous starter.html et sers le dossier en HTTP local, par exemple avec python3 -m http.server 8766 --bind 127.0.0.1. Ouvre http://127.0.0.1:8766/starter.html ; utilise un autre port libre si nécessaire.
La page crée deux originaux et sept cas filtrés à chacune de deux tailles explicites. Chaque ID de filtre inclut son cas et sa largeur pour que plusieurs SVG en ligne du même document aient des références uniques. Chaque lien d’enregistrement SVG garde le filtre autonome et son entrée B encodée.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Original SVG composite artwork</title>
<style>
body { margin: 24px; font: 16px system-ui; background: #f6f2e8; }
main { display: grid; grid-template-columns: repeat(3, 260px); gap: 18px; }
figure { margin: 0; }
svg { display: block; background: white; border: 1px solid #bbb; }
figcaption { margin: 6px 0; }
pre { white-space: pre-wrap; font-size: 12px; }
</style>
<h1>Original operands and rendered composites</h1>
<main id="cases"></main>
<pre id="report"></pre>
<script>
const A = 'M24 24 H132 V56 H192 V136 H24 Z';
const B = 'M92 8 L216 84 L92 152 L60 84 Z';
const svgNS = 'http://www.w3.org/2000/svg';
const cases = [
{ id: 'a' }, { id: 'b' },
{ id: 'a-in-b', operator: 'in' },
{ id: 'a-out-b', operator: 'out' },
{ id: 'a-xor-b', operator: 'xor' },
{ id: 'b-in-a', operator: 'in', reverse: true },
{ id: 'b-out-a', operator: 'out', reverse: true },
{ id: 'b-xor-a', operator: 'xor', reverse: true },
{ id: 'a-out-half-b', operator: 'out', opacity: 0.5 },
];
function documentSVG(test, width) {
const height = width * 2 / 3;
const id = test.id + '-' + width;
const second = '<svg xmlns="' + svgNS + '" width="240" height="160" viewBox="0 0 240 160">'
+ '<path d="' + B + '" fill="#d4a53a" opacity="' + (test.opacity ?? 1) + '"/></svg>';
const href = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(second);
const first = test.reverse ? 'operandB' : 'SourceGraphic';
const other = test.reverse ? 'SourceGraphic' : 'operandB';
const defs = test.operator ? '<defs><filter id="' + id + '" filterUnits="userSpaceOnUse" primitiveUnits="userSpaceOnUse" x="0" y="0" width="240" height="160" color-interpolation-filters="sRGB">'
+ '<feImage href="' + href + '" x="0" y="0" width="240" height="160" preserveAspectRatio="none" result="operandB"/>'
+ '<feComposite in="' + first + '" in2="' + other + '" operator="' + test.operator + '"/></filter></defs>' : '';
return '<svg xmlns="' + svgNS + '" width="' + width + '" height="' + height + '" viewBox="0 0 240 160">'
+ defs + '<path d="' + (test.id === 'b' ? B : A) + '" fill="' + (test.id === 'b' ? '#d4a53a' : '#176b5b')
+ '"' + (test.operator ? ' filter="url(#' + id + ')"' : '') + '/></svg>';
}
async function run() {
const results = [];
for (const width of [120, 240]) {
for (const test of cases) {
const source = documentSVG(test, width);
const svg = new DOMParser().parseFromString(source, 'image/svg+xml').documentElement;
const figure = document.createElement('figure');
const caption = document.createElement('figcaption');
caption.textContent = test.id + ', ' + width + ' × ' + width * 2 / 3;
figure.append(document.importNode(svg, true), caption);
document.getElementById('cases').append(figure);
const path = figure.querySelector('path');
const bbox = path.getBBox();
const image = new Image();
image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source);
await image.decode();
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = width * 2 / 3;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
const sample = (x, y) => [...ctx.getImageData(Math.floor(x * width / 240), Math.floor(y * width / 240), 1, 1).data];
const hash = [...new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(path.getAttribute('d'))))]
.map(v => v.toString(16).padStart(2, '0')).join('');
const download = document.createElement('a');
download.href = image.src;
download.download = test.id + '-' + width + '.svg';
download.textContent = 'Save SVG';
figure.append(download);
results.push({ id: test.id, width, height: canvas.height, d: path.getAttribute('d'), dSHA256: hash,
bbox: { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height },
directPaths: svg.querySelectorAll('path').length, filterImages: svg.querySelectorAll('feImage').length,
aOnly: sample(40, 40), bOnly: sample(200, 84), overlap: sample(120, 84), outside: sample(230, 150) });
}
}
document.getElementById('report').textContent = JSON.stringify({ A, B, results }, null, 2);
}
run();
</script>
</html>Le code conserve le même chemin A direct même lorsque les entrées de l’opérateur sont inversées. Par exemple, b-in-a change feComposite en in="operandB" et in2="SourceGraphic" ; il ne remplace pas l’élément source filtré par B. Cela rend l’ordre des opérandes visible sans modifier la géométrie sous-jacente de A.
L’inspection de pixels ici lit un canevas peint depuis chaque SVG généré. Le livrable téléchargeable reste le SVG filtré. Ce n’est ni un nouveau chemin booléen ni une conversion de PerfectVector.
Compare séparément la peinture et la géométrie
Nous avons exécuté exactement cette page dans un environnement Chrome à 120 × 80 et 240 × 160, enregistré les 18 SVG et rouvert ceux-ci comme images dans le même navigateur. Les tailles affichées sont des entrées explicites, pas une affirmation sur deux appareils physiques.
Trois positions d’échantillonnage intérieures utilisent le système de coordonnées d’origine : A seul (40,40), B seul (200,84) et chevauchement (120,84). Les valeurs alpha suivantes ont été observées aux deux tailles avec des opérandes opaques :
| Entrées du filtre et opérateur | Alpha A seul | Alpha B seul | Alpha du chevauchement |
|---|---|---|---|
A in B | 0 | 0 | 255 |
A out B | 255 | 0 | 0 |
A xor B | 255 | 255 | 0 |
B in A | 0 | 0 | 255 |
B out A | 0 | 255 | 0 |
B xor A | 255 | 255 | 0 |
Les lignes in partagent un chevauchement opaque mais diffèrent en couleur : A en premier était bleu-vert (23,107,91,255) ; B en premier était ocre (212,165,58,255). L’échantillon extérieur (230,150) restait transparent partout. Ce sont des pixels intérieurs sélectionnés, pas un test complet de couverture des bords ni de compatibilité.
Chaque fichier filtré conservait la chaîne d originale exacte de A et la même empreinte SHA-256. Son getBBox() géométrique local restait x=24, y=24, width=168, height=112. Cette boîte décrit le chemin source ; ce n’est pas la boîte englobante des pixels visibles du filtre. Le chemin B encodé restait aussi inchangé. Un résultat de filtre peut donc paraître différent alors que les deux contours créés restent intacts.
Les originaux enregistrés ont un chemin direct et aucune image de filtre. Chaque fichier filtré possède un chemin A direct et un feImage contenant le SVG distinct à un chemin de B. Aucun élément image matriciel ordinaire n’est introduit. Une opération rendue en espace image et des opérandes sources vectoriels peuvent coexister ; l’inventaire source seul ne signifie pas que le résultat est devenu une géométrie combinée modifiable.
L’opacité partielle change le sens d’une ouverture
Le dernier cas rend B à moitié opaque tout en gardant A opaque, puis applique A out B. Le chevauchement n’est pas devenu vide. Aux deux tailles, son RGBA observé était (22,106,90,127) : du bleu-vert partiellement transparent, avec des arrondis issus du rendu et de la lecture.
Pour out, l’alpha de sortie est le premier alpha multiplié par un moins le second alpha. Pour in, c’est leur produit. La définition de composition de Filter Effects définit ces opérations avec des couleurs prémultipliées et l’alpha. B opaque peut retirer la peinture superposée de A ; B partiellement transparent en laisse une partie.
Examine le résultat sur le fond réel. Une zone pâle sur blanc peut être une peinture translucide plutôt qu’un trou entièrement transparent. Les pixels anticrénelés des bords nécessitent aussi un contrôle visuel ; l’échantillon intérieur ne promet pas que chaque pixel de limite a un alpha nul. Pour une tâche distincte de remappage d’opacité, consulte le guide des seuils alpha SVG.
Livre un effet de filtre ou crée de vrais contours
Garde ce filtre lorsque le moteur de rendu destinataire doit reproduire la composition visuelle. Préserve les fichiers A et B originaux et examine le SVG filtré rouvert dans sa destination réelle. Notre réouverture réussie dans le navigateur ne certifie pas les autres moteurs de rendu ni les machines de production.
Si la livraison exige des contours combinés sélectionnables ou une ouverture prête à découper, effectue et examine une véritable opération de modification de chemin ou booléenne dans le processus prévu. La peinture visible modifiée ici ne crée pas cette géométrie. Le guide clipPath contre mask établit une distinction liée à la visibilité ; le guide de dégroupement SVG aide lorsque le dessin affiché n’est pas l’objet modifiable attendu.
Si ton clipart n’existe qu’en pixels et que tu as besoin de formes sources modifiables, prépare un SVG de clipart avec PerfectVector, examine les contours et les ouvertures, puis garde le maître. Applique et vérifie séparément le filtre ou l’opération de chemin prévu. La vectorisation ne transforme pas le chevauchement visuel de ce filtre en contour de fabrication vérifié.
Questions fréquentes
feComposite out supprime-t-il la géométrie de chemin superposée ? Non. Il change la peinture rendue à partir de l’alpha de la seconde entrée. Dans nos fichiers filtrés, les données du chemin A original et les limites géométriques locales restaient intactes même là où la peinture superposée devenait transparente.
Pourquoi échanger in et in2 change-t-il le résultat ? Ils identifient la première et la seconde entrée. In garde la peinture de la première dans l’opacité de la seconde ; out garde la première à l’extérieur. Nos cas in inversés partagent le chevauchement opaque mais montrent des couleurs différentes, tandis que les cas out inversés gardent des régions différentes.
xor rend-il toujours le chevauchement complètement vide ? Le chevauchement intérieur entièrement opaque était vide dans nos cas xor. L’alpha partiel et les bords anticrénelés nécessitent leur propre examen ; les diagrammes d’ensembles de formes opaques ne décrivent pas chaque pixel translucide.
Puis-je envoyer directement l’ouverture filtrée comme chemin de coupe modifiable ? Un résultat visuel de filtre n’est pas une géométrie booléenne nouvellement créée. Garde les formes originales, crée et examine les contours requis dans le processus de chemins prévu, puis vérifie séparément l’application destinataire et les exigences de production.
Sources
- MDN : feComposite — Rôles des entrées en espace image, description des opérateurs et espace colorimétrique de filtre par défaut.
- MDN : operator — Valeurs des opérateurs de composition et contexte morphologique distinct.
- MDN : filterUnits — Système de coordonnées de la région du filtre.
- MDN : feImage — Entrée image dans la chaîne de filtres.
- W3C : Composition de Filter Effects — Définitions de composition des couleurs prémultipliées et de l’alpha.
Tu pars de ton propre clipart matriciel ? Crée un maître SVG modifiable, examine ses contours et ses ouvertures, puis conserve-le pendant que tu vérifies la composition visuelle choisie ou le résultat de chemins créé séparément dans la destination.
Plus depuis le blog

Recadrer un SVG définitivement, sans tracés cachés
Recadre des tracés SVG remplis par de vraies intersections, conserve les couleurs séparées et une ouverture, puis inspecte le fichier enregistré pour repérer la géométrie cachée par un simple écrêtage.

Inkscape : objet en chemin ou contour en chemin ?
Compare Objet en chemin et Contour en chemin d’Inkscape sur un même cercle. Découvre lequel conserve un contour réglable, lequel crée une bande remplie et quoi vérifier ensuite.
