Spłaszczanie matrycy SVG przekształca się w Inkscape

Mam darmowy plik clipart SVG stworzony pierwotnie w Inkscape, który modyfikuję do użytku w grze JavaScript na Windows 8. Zawiera wiele instancji ścieżki z transformatą macierzy zastosowaną na otaczającej grupie, jak to:

<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>

Chcę spłaszczyć tę transformację, nakładając ją wcześniej na ścieżkę w Inkscape, aby zmniejszyć pracę przeglądarki podczas animacji. Jednak po podłączeniu 6 wartości matrycy do parametrów A B C D E F w Inkscape i zastosowaniu go, to nadaje ścieżce zupełnie inny obrót i skalowanie do tego, co robi silnik IE10.

Sprawdzałem wiele razy, czy mam poprawnie zmapowane 6 wartości. Co robię źle?

EDIT: OK, oto zrzuty ekranu przed i po IE10 i Inkscape. W przypadku IE10 SVG znajduje się bezpośrednio wewnątrz ciała pustego dokumentu HTML (renderowanie jest dokładnie takie samo w Firefoksie). W Inkscape po prostu otworzyłem plik SVG" przed", który zawiera tylko element path, wybrał ścieżkę i podłączył 6 wartości przekształć macierz w obiekt > Przekształć > macierz. Niewiele wiem o matrycach, chcę tylko móc wstępnie zastosować te przekształcenia w taki sam sposób, jak robi to przeglądarka, a najlepiej zrozumieć, dlaczego jest różnica w Inkscape. Dzięki.

Tylko ścieżka IE10Ścieżka IE10 z transformacjąTylko ścieżka InkscapeInkscape path with transform

Author: Tom Hall, 2013-02-04

5 answers

Krótka odpowiedź

Podczas wpisywania params macierzy transformacji w Inkscape, upewnij się, że masz zaznaczoną opcję "Edytuj bieżącą macierz", ponieważ jeśli zastosujesz nową macierz transformacji do obiektu, to w rzeczywistości mnożysz tę nową macierz z istniejącą macierzą transformacji obiektu, więc upewnij się, że edytujesz ją zamiast tego.
Tutaj wpisz opis obrazka

Długa Odpowiedź

Jak przeliczyć wszystko samodzielnie.

Najpierw spróbujmy zrozumieć transformację matryce trochę. Macierz transformacji jest szybkim i sprytnym narzędziem do stosowania przekształceń afinicznych (transformacji, która zachowuje linie proste) do wektora.
Tak więc, jeśli masz wektor (powiedzmy współrzędne 2d) i macierz transformacji i pomnożysz te dwa razem, skończysz z przekształconymi współrzędnymi, z zastosowanymi transformacjami zdefiniowanymi w macierzy transformacji.
macierz transformacji
Obliczanie x' i y' odbywa się tak:

x' = a*x + c*y + e 
y' = b*x + d*y + f

Następnie musimy zrozum trochę format svg.
Zgodnie ze specyfikacją W3C svg transformata matrix przyjmuje dokładnie te 6 parametrów (a,b,c,d,e,f) jako argumenty.
Dlatego, z twojego przykładu,

<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">

Mamy następujące paramy macierzy transformacji:

a=0.443
b=0.896
c=-0.896
d=0.443
e=589.739
f=-373.223

Teraz, jeśli mamy następującą współrzędną przykładową: x=27, y=-9, możemy ją przekształcić, używając wcześniej zdefiniowanej macierzy transformacji tak:

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

Fajne, co? Możesz uzyskać więcej informacji tutaj

Ale to nie wszystko. Musimy również zrozumieć dane ścieżki svg.
Zgodnie ze specyfikacją W3C svg path dspecification każda litera w danych ścieżki reprezentuje instrukcję. Każda z par liczb, które następują po instrukcji, reprezentuje wartość współrzędnych.

Z twojego przykładu mamy następującą ścieżkę:

<path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />

Tutaj widzimy, że obiekt path używa jednej bezwzględnej instrukcji moveto (Wielkie Litery M ), względnej smooth curveto cubic Bézier curve (lowercase s), relative lineto instruction (lowercase l ), and another relative smooth curveto cubic Bézier curve instruction, nastepnie closepath instruction (lowercase z).

M486,313 jest tłumaczone na absolute moveto x=486, y=313
s27-9,43-29 jest nieco bardziej skomplikowane do odczytania, ponieważ niektóre śpiączki są pomijane, ponieważ nie są potrzebne, jeśli liczba ujemna jest ujemna, więc znak minus działa jak śpiączka - w każdym razie, to przekłada się na relatywnie gładki krzywizna Beziera x=27, y = -9, x=43, y=-29 (jeden punkt docelowy i jeden punkt kontrolny)
I tak dalej.

Jak więc zastosować i usunąć macierz transformacji z grupy svg? Tak:

// 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 Absolute move to

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

Przejście do instrukcji jest teraz M524.589,200.892

S27-9,43-29 - smooth curveto, powtórz ten sam proces dla każdej współrzędnej, ale ustaw e i f (parametry translacji) na 0, ponieważ jest to Instrukcja względna, a nie absolutna.
Teraz jest
s20.025,20.205,45.033,25.680999999999997

L26,4,1,23-22,5
stanie się
l7.934000000000001,25.067999999999998,-20.165,11.085,-14.226,-17.497

S-25-6-48-3
stanie się
s-5.698999999999999,-25.058000000000003,-18.576,-44.337

I z pozostanie z

Więc wynikowa przekształcona ścieżka będzie:

<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" />
Mam nadzieję, że to ma dla ciebie sens.
 51
Author: ArtBIT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-27 14:00:59

Możesz upiec koordy wybierając ścieżkę, a następnie używając Path - > Union (CTRL++). Mam nadzieję, że to pomoże

 18
Author: parameciostudio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-05 17:35:22

Wklej w miejscu może Ci pomóc:

  1. Kliknij dwukrotnie grupę w Inkscape, aby ją wprowadzić.
  2. Zaznacz wszystkie Zawartość grupy, naciskając Ctrl + A, A skopiuj za pomocą Ctrl+C.
  3. Kliknij dwukrotnie na zewnątrz grupy, aby opuścić grupę.
  4. Edit > Wklej w miejsce (Ctrl+Alt+V) – w tym momencie do wklejanych obektów zostaną zastosowane przekształcenia grupowe.
  5. Grupa obiekty ponownie (Ctrl + G)
  6. Przenieś nową grupę do tej samej głębokości co oryginalna i Usuń oryginalną grupę . (Jest to prawdopodobnie łatwiejsze z edytorem XML, Ctrl + Shift+X.)
 13
Author: andraaspar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-25 08:41:02

Po odpowiedzi @ andraaspar, możesz również spróbować rozgrupować (Ctrl-U) i ponownie grupować (Ctrl-G). U mnie zadziałało.

 11
Author: btel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-11 20:37:52

Dzięki ArtBIT za wszystkie informacje ! Miałem pewne problemy z tym w aplikacji PHP i napisałem bibliotekę, która manipuluje danymi czcionek (z pliku SVG) i robi na niej jakiekolwiek przekształcenia. Każdy zainteresowany może spróbować z Githuba:

Https://github.com/kartsims/easysvg

Przykład użycia:

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();

Przykład manipulacji danymi 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)
 2
Author: kartsims,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-21 13:13:38