/ / SVG transform-origin non funziona in Chrome - google-chrome, svg

Trasformazione SVG-origine non funzionante in Chrome - google-chrome, svg

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>

problema di origine della trasformazione

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

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