Ho un'app basata su SVG che fa un uso massiccio di trasformazioni come traslazioni, rotazioni e ridimensionamenti. Anche se non ho problemi con Firefox, in Chrome, il transform-origin
la proprietà non viene presa in considerazione. Sembra applicare il valore predefinito dell'agente utente 0px 0px 0
.
Ecco un esempio (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>
Come puoi vedere Chrome applica tutte le trasformazioni dall'angolo in alto a sinistra della forma indipendentemente dall'origine definita mentre Firefox rispetta l'origine definita.
Mi sto perdendo qualcosa su come transform-origin
funziona con SVG?
Qualcuno ha davvero trovato un modo per risolvere questo problema senza compensare con le traduzioni?
risposte:
6 per risposta № 1Rispondo alla mia stessa domanda per chiarire completamente cosa sta succedendo transform-origin
proprietà sulle funzioni di trasformazione SVG 1.1 e su come risolvere questo problema in Chrome 48.
Prima di tutto, transform-origin
è una pura proprietà CSS 3, non è affatto correlata a SVG 1.1. Nonostante il fatto che transform
suona molto simile transform-origin
, si applicano a diversi sistemi. transform
esiste sia in CSS 3 che in SVG 1.1 ma hanno implementazioni separate. transform-origin
esiste solo in CSS 3 e quindi non dovrebbe influenzare SVG 1.1. Il fatto che transform-origin
non ha alcuna influenza su SVG in Chrome 48 è prevista.
Quindi perché transform-origin
si applica a SVG in Firefox 44? Ebbene, il motivo non è esattamente chiaro, ma sembra che faccia parte dello sforzo in corso da Mozilla per portare lentamente il supporto per SVG 2 in Firefox. Infatti con SVG 2, tutto diventerà una trasformazione CSS 3 (nessuna implementazione separata) e SVG riceverà quindi supporto per transform-origin
. L'ho scoperto nell'ottimo articolo sul Sistemi di coordinate SVG di Sara Soueidan.
Ora come può essere superato in Chrome 48. È abbastanza semplice, ma se vuoi applicare translate()
, scale()
e rotate()
allo stesso tempo, dovrai comunque calcolare l'offset indotto dal ridimensionamento e compensarlo nella tua traduzione.
Come Bobby Orndorff menzionato nella sua risposta, è effettivamente possibile fornire il centro di rotazione al rotate()
funzione fornendo parametri xey aggiuntivi. Questo è già un grande miglioramento. Ma sfortunatamente il file scale()
funzione non supporta una cosa del genere e verrà sempre ridimensionato dall'angolo in alto a sinistra del suo genitore. Pertanto dovrai comunque correggere la tua traduzione per simulare una scala attorno a un centro.
Ecco la soluzione finale che funziona su Chrome 48 e 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 per risposta № 2
L'esempio è un CSS transform-origin misto con un fileTrasformazione SVG. Sebbene la trasformazione CSS e la trasformazione SVG siano simili, ci sono differenze. Ad esempio, la trasformazione CSS può essere 2D e 3D mentre la trasformazione SVG è solo 2D. La funzione CSS transform rotate accetta l'angolo come un numero combinato con un'unità (ad esempio degs, grad, rad, turn) mentre SVG transforms accetta l'angolo come numero (con unità implicita di gradi) insieme al secondo e terzo parametro opzionale (x, y) che rappresenta l'origine della rotazione.
Per far funzionare l'esempio in FireFox e Chrome, puoi utilizzare una trasformazione CSS invece di una trasformazione SVG. Per esempio...
<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>
Per far funzionare l'esempio in FireFox, Chrome e IE, è possibile utilizzare la funzione di rotazione della trasformazione SVG con il secondo e il terzo parametro opzionale invece di un'origine della trasformazione CSS. Per esempio...
<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>