Mam aplikację opartą na SVG, która w dużym stopniu wykorzystuje transformacje, takie jak translacja, obrót i skalowanie. Chociaż nie mam problemu w przeglądarce Firefox, w przeglądarce Chrome transform-origin
nieruchomość nie jest brana pod uwagę. Wydaje się, że stosuje domyślną wartość klienta użytkownika 0px 0px 0
.
Oto przykład (JSFiddle):
<svg width="400" height="400">
<defs>
<rect id="shape" width="200" height="200"/>
</defs>
<g transform="translate(100,100)">
<use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
<ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
<g transform="translate(0,0) scale(0.5) rotate(45)" style="transform-origin: 100px 100px;">
<use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
</g>
</g>
</svg>
Jak widać, Chrome stosuje całą transformację z lewego górnego rogu kształtu niezależnie od zdefiniowanego pochodzenia, podczas gdy Firefox szanuje zdefiniowane pochodzenie.
Czy brakuje mi czegoś na temat tego, jak transform-origin
działa z SVG?
Czy ktoś rzeczywiście znalazł sposób na naprawienie tego bez kompensowania tłumaczeniami?
Odpowiedzi:
6 dla odpowiedzi № 1Odpowiadam na własne pytanie, aby w pełni wyjaśnić, o co chodzi transform-origin
właściwości funkcji transformacji SVG 1.1 i jak rozwiązać ten problem w Chrome 48.
Po pierwsze, transform-origin
to czysta właściwość CSS 3, w ogóle nie jest związana z SVG 1.1. Pomimo tego, że transform
brzmi bardzo podobnie transform-origin
, mają zastosowanie do różnych systemów. transform
istnieje w CSS 3 i SVG 1.1, ale mają oddzielne implementacje. transform-origin
istnieje tylko w CSS 3 i dlatego nie powinien wpływać na SVG 1.1. Fakt, że transform-origin
nie ma wpływu na SVG w Chrome 48.
Więc dlaczego transform-origin
dotyczy SVG w przeglądarce Firefox 44? Cóż, powód nie jest do końca jasny, ale wydaje się, że jest to część ciągłych wysiłków Mozilli, aby powoli wprowadzić obsługę SVG 2 w Firefoksie. Rzeczywiście, z SVG 2, wszystko stanie się transformacją CSS 3 (bez oddzielnej implementacji), a zatem SVG otrzyma wsparcie dla transform-origin
. Dowiedziałem się o tym w doskonałym artykule na temat Układy współrzędnych SVG od Sary Soueidan.
Jak można to przezwyciężyć w Chrome 48. Jest to dość proste, ale jeśli chcesz zastosować translate()
, scale()
i rotate()
w tym samym czasie nadal będziesz musiał obliczyć przesunięcie wywołane skalowaniem i skompensować je w swoim tłumaczeniu.
Tak jak Bobby Orndorff wspomniany w swojej odpowiedzi, faktycznie możliwe jest zapewnienie środka obrotu dla rotate()
funkcji, zapewniając dodatkowe parametry x i y. To już jest duża poprawa. Ale niestety scale()
funkcja nie obsługuje takich rzeczy i zawsze będzie skalowany od lewego górnego rogu swojego rodzica. Dlatego nadal będziesz musiał poprawić swoje tłumaczenie, aby zasymulować skalę wokół środka.
Oto ostateczne rozwiązanie, które działa w Chrome 48 i Firefox 44:
<svg width="400" height="400">
<defs>
<rect id="shape" width="200" height="200"/>
</defs>
<g transform="translate(100,100)">
<use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
<ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
<g transform="translate(50,50) scale(0.5) rotate(45, 100, 100)">
<use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
</g>
</g>
</svg>
1 dla odpowiedzi nr 2
Przykładem jest mieszane pochodzenie transformacji CSS z rozszerzeniemTransformacja SVG. Chociaż transformacja CSS i transformacja SVG są podobne, istnieją różnice. Na przykład transformacja CSS może być 2D i 3D, podczas gdy transformacja SVG jest tylko 2D. Funkcja obracania transformacji CSS akceptuje kąt jako liczbę połączoną z jednostką (np. Degs, grad, rad, turn), podczas gdy transformacja SVG akceptuje kąt jako liczbę (z domniemaną jednostką stopni) wraz z opcjonalnymi parametrami drugim i trzecim (x, y) reprezentujące pochodzenie rotacji.
Aby przykład działał w FireFox i Chrome, możesz użyć transformacji CSS zamiast transformacji SVG. Na przykład...
<svg width="400" height="400">
<defs>
<rect id="shape" width="200" height="200"/>
</defs>
<g transform="translate(100,100)">
<use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
<ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
<g style="transform: translate(0,0) scale(0.5) rotate(45deg); transform-origin: 100px 100px;">
<use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
</g>
</g>
</svg>
Aby przykład działał w FireFox, Chrome i IE, możesz użyć funkcji obracania transformacji SVG z opcjonalnymi parametrami drugim i trzecim zamiast źródła transformacji CSS. Na przykład...
<svg width="400" height="400">
<defs>
<rect id="shape" width="200" height="200"/>
</defs>
<g transform="translate(100,100)">
<use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
<ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
<g transform="translate(0,0) scale(0.5) rotate(45,200,200)">
<use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
</g>
</g>
</svg>