J'ai un fichier SVG clipart gratuit créé à l'origine dans Inkscape auquel je fais des modifications pour l'utiliser dans un jeu JavaScript Windows 8. Il contient de nombreuses instances d'un chemin avec une transformation matricielle appliquée sur un groupe environnant, comme ceci:
<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
<path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
</g>
Je souhaite aplatir cette transformation en l'appliquant à l'avance au chemin dans Inkscape, pour réduire le travail du navigateur pendant l'animation. Cependant, lorsque je branche les 6 valeurs de matrice dans les paramètres A B C D E F dans Inkscape et les applique, cela donne au chemin une rotation et une mise à l'échelle complètement différentes de ce que fait le moteur IE10.
J'ai vérifié à plusieurs reprises que les 6 valeurs sont correctement mappées. Qu'est-ce que je fais mal?
EDIT: OK, voici des captures d'écran avant et après IE10 et Inkscape. Pour le cas IE10, le SVG réside directement dans le corps d'un document HTML autrement vide (le rendu est exactement le même dans Firefox). Dans Inkscape, j'ai simplement ouvert le fichier SVG "avant" qui ne contient que l'élément path, sélectionné le chemin et branché les 6 valeurs de transformation de matrice dans Object> Transform> Matrix. Je connais très peu les matrices, je veux juste pouvoir pré-appliquer ces transformations de la même manière que le navigateur, et idéalement pour comprendre pourquoi il y a une différence dans Inkscape. Merci.
Lorsque vous saisissez les paramètres de la matrice de transformation dans Inkscape, assurez-vous que la case "Modifier la matrice actuelle" est cochée, car si vous appliquez une nouvelle matrice de transformation à un objet, vous multipliez en fait cette nouvelle matrice par la matrice de transformation existante de l'objet, donc assurez-vous de le modifier à la place.
Comment tout recalculer vous-même.
Essayons d'abord de comprendre un peu les matrices de transformation. Une matrice de transformation est un outil rapide et intelligent pour appliquer des transformations affines (transformation qui préserve les lignes droites) à un vecteur.
Donc, si vous avez un vecteur (disons, coordonnées 2D) et une matrice de transformation, et multipliez les deux ensemble, vous vous retrouverez avec des coordonnées transformées, avec les transformations définies dans la matrice de transformation, appliquées.
Calcul de x'
et y'
se fait comme ceci:
x' = a*x + c*y + e
y' = b*x + d*y + f
Ensuite, nous devons comprendre un peu le format svg.
Selon la spécification svg w3c la transformation matrix
prend exactement ces 6 paramètres (a, b, c, d, e, f) comme arguments.
Par conséquent, d'après votre exemple,
<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
nous avons les paramètres de matrice de transformation suivants:
a=0.443
b=0.896
c=-0.896
d=0.443
e=589.739
f=-373.223
Maintenant, si nous avons l'exemple de coordonnée suivant: x=27, y=-9
, nous pouvons le transformer, en utilisant la matrice de transformation précédemment définie comme ceci:
x' = a*x + c*y + e
x' = 0.443*27 + -0.896*-9 + 589.739
x' = 609.764
y' = b*x + d*y + f
y' = 0.896*27 + 0.443*-9 -373.223
y' = −353.018
Neat, hein? Vous pouvez obtenir plus d'informations ici
Mais ce n'est pas tout. Nous devons également comprendre les données du chemin svg.
Selon la w3c svg path dspecification chaque lettre dans les données de chemin représente une instruction. Et chacune des paires de nombres qui suivent une instruction représente une valeur de coordonnées.
D'après votre exemple, nous avons le chemin suivant:
<path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
Ici, nous voyons que cet objet chemin utilise une instruction absolue moveto
(majuscule [~ # ~] m [~ # ~] ), un parent smooth curveto
courbe de Bézier cubique (minuscule s ), une instruction relative lineto
(minuscule l ), et un autre parent smooth curveto
instruction de courbe de Bézier cubique, suivie d'une instruction closepath
(minuscule z ).
M486,313
est traduit en moveto absolu x = 486, y = 313s27-9,43-29
est un peu plus compliqué à lire car certains comas sont omis car ils ne sont pas nécessaires si le nombre négatif est négatif, donc le signe moins agit comme un coma - de toute façon, cela se traduit par relative lisse bezier curveto x = 27, y = -9, x = 43, y = -29 (un point de destination et un point de contrôle)
Etc.
Alors, comment appliquer et supprimer la matrice de transformation de votre groupe svg? Ainsi:
// we read the transformation matrix params
// <g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
a=0.443
b=0.896
c=-0.896
d=0.443
e=589.739
f=-373.223
// we read the path data, and transform each instruction
// <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
M486,313 Déplacement absolu vers
x' = a*x + c*y + e = a*486 + c*313 + e = 524.589
y' = b*x + d*y + f = b*486 + d*313 + f = 200.892
Passer à l'instruction est maintenant M524.589,200.892
S27-9,43-29 - courbure lisse, répétez le même processus pour chaque coordonnée, mais définissez les e
et f
(paramètres de traduction) à 0, car c'est une instruction relative et non un absolu.
C'est maintenant
s20.025,20.205,45.033,25.680999999999997
l26,4,1,23-22,5
va devenir
l7.934000000000001,25.067999999999998, -20.165,11.085, -14.226, -17.497
s-25-6-48-3
va devenir
s-5.698999999999999, -25.058000000000003, -18.576, -44.337
Et z restera z
Ainsi, le chemin transformé résultant sera:
<path d="M524.589,200.892s20.025,20.205,45.033,25.680999999999997l7.934000000000001,25.067999999999998,-20.165,11.085,-14.226,-17.497s-5.698999999999999,-25.058000000000003,-18.576,-44.337z" />
J'espère que cela a du sens pour vous.
Vous pouvez cuire les coordonnées en sélectionnant le chemin puis en utilisant Chemin -> Union (CTRL ++). J'espère que cela t'aides
Coller sur place peut vous aider:
Suite à la réponse de @andraaspar, vous pouvez également essayer de dissocier (Ctrl-U) et de regrouper à nouveau (Ctrl-G). Ça a marché pour moi.
Merci ArtBIT pour toutes les infos! J'ai eu quelques problèmes à ce sujet sur une application PHP, et j'ai écrit une bibliothèque qui manipule les données de police (à partir du fichier SVG) et fait toute sorte de transformation dessus. Toute autre personne intéressée peut l'essayer depuis le GitHub:
https://github.com/kartsims/easysvg
Exemple d'utilisation:
require 'easySVG.php';
$svg = new EasySVG();
$svg->setFont("paris-bold-webfont.svg", 100, "#000000");
$svg->addText("Simple text display");
$svg->addAttribute("width", "800px");
$svg->addAttribute("height", "100px");
echo $svg->asXML();
Exemple de manipulation de données SVG:
$def = 'YOUR SVG DEFINITION HERE';
$easySVG = new EasySVG();
// rotate by 40°
$rotated_def = $easySVG->defRotate($def, 40)
// rotate by 40° with center at (200,100)
$rotated_def2 = $easySVG->defRotate($def, 40, 200, 100)
// scale transform : width*4
$scaled_def = $easySVG->defScale($def, 4)