Largeur de trait fixe en SVG

103

Je voudrais pouvoir définir la largeur de trait d'un élément SVG pour qu'elle soit "consciente des pixels", c'est-à-dire toujours 1px de large quelles que soient les transformations de mise à l'échelle actuelles appliquées. Je suis conscient que cela peut être impossible, car le but de SVG est d'être indépendant des pixels.

Le contexte suit:

J'ai un élément SVG avec son jeu d'attributs viewBox et preserveAspectRatio. Ça ressemble à quelque chose comme ça

<svg version="1.1" baseProfile="full"
    viewBox="-100 -100 200 200" preserveAspectRatio="xMidYMid meet"
    xmlns="http://www.w3.org/2000/svg" >
</svg>

Cela signifie que lorsque je redimensionne cet élément, les formes réelles à l'intérieur sont mises à l'échelle en conséquence (jusqu'ici tout va bien).

Comme vous pouvez le voir, j'ai configuré la viewBox pour que l'origine soit au centre. Je voudrais dessiner un axe x et un axe y dans cet élément, ce que je fais ainsi:

<line x1="-1000" x2="1000" y1="0" y2="0" />

Encore une fois, cela fonctionne très bien. Dans l'idéal, cependant, cet axe n'aurait toujours qu'une largeur de 1 px. Je n'ai aucun intérêt à ce que les axes deviennent plus gros lorsque je redimensionne l'élément svg parent.

Alors suis-je foutu?

wxs
la source

Réponses:

128

Vous pouvez utiliser la vector-effectpropriété définie sur non-scaling-stroke, voir la documentation . Une autre façon est d'utiliser transform(ref).

Cela fonctionnera dans les navigateurs qui supportent ces parties de SVG Tiny 1.2, par exemple Opera 10. La solution de secours comprend l'écriture d'un petit script pour faire la même chose, inversant fondamentalement le CTM et l'appliquant sur les éléments qui ne devraient pas être mis à l'échelle.

Si vous souhaitez des lignes plus nettes, vous pouvez également désactiver l'anticrénelage ( shape-rendering=optimizeSpeedou shape-rendering=crispEdges) et / ou jouer avec le positionnement.

Erik Dahlström
la source
1
Malheureusement, cela se trouve dans une application XUL, et cela ne semble pas encore prendre en charge l'effet vectoriel. Tant pis.
wxs
1
Cela devrait apparaître dans Firefox 15, tout va bien, vous devriez donc pouvoir l'utiliser une fois que vous avez créé votre application XUL sur gecko 15.
Robert Longson
2
IE11 ne prend toujours pas en charge la vector-effectpropriété. Est-il possible d'obtenir le même effet que vector-effect: non-scaling-strokedans IE11?
merlin
1
@merlin oui, avec js, il est possible d'émuler cela dans IE.
Erik Dahlström
3
@merlin clone l'élément (en définissant fillsur noneet vice versa pour le stroke), calculez et définissez les transformations appropriées (une pour la partie de remplissage et une pour la partie de trait). Cela va être un peu compliqué à coup sûr, mais ça y est - vous voudrez peut-être aussi demander à Microsoft d'ajouter une prise en charge. En tout cas, je pense que votre question mérite d’être une question à part entière.
Erik Dahlström