Ok. Quindi ecco quello che capisco che tu vuoi fare con le mie parole.
loop attraverso tutti gli elementi DOM conversione dimensioni assolute (cioè altezza/larghezza in termini di pixel) in dimensioni relative (cioè altezza/larghezza in termini di percentuali). Questo dovrebbe essere fatto con la sensibilità per stabilire se la dimensione è impostata usando gli attributi CSS o HTML in modo da essere utilizzabile per gli elementi SVG.
Detto questo, v'è un vincolo importante: Se si desidera convertire dimensioni assolute di dimensioni relative utilizzando <x>
come l'elemento radice, quindi <x>
deve avere dimensioni assolute. In caso contrario, le dimensioni relative all'interno del contenitore cambieranno le dimensioni in base al loro contenuto anziché alla dimensione complessiva del genitore <x>
.
Con questa clausola, quello che stai chiedendo è abbastanza facile. Questo è l'algoritmo che deve essere usato.
- Inizia dai
<body>
- Dare
<body>
dimensioni fisse
- piedi dell'albero DOM per
<body>
fare quanto segue per ogni elemento
- Prendi le dimensioni dell'elemento
- Ricevi le dimensioni del genitore
- Convert alle dimensioni relative (cioè larghezza/larghezza genitore).
- Applicare dimensioni relative
Per testare il mio codice che ho usato il seguente codice HTML. Ha sia il codice che includi sia un'istanza in cui un elemento figlio è più grande di quello genitore. Questo è un caso che ho identificato come condizione al contorno da testare.
<div style="width:100%;height:800px">
<svg width="150" height="200" style="background: red;">
<rect width="30" height="50" x="34" y="24"/>
</svg>
<div style="background: green; width: 50px; height: 50px;">
<p style="background: teal; width: 100px; height: 20px;">Content</p>
</div>
</div>
Questo è il codice JavaScript. È abbastanza ben commentato e fornisce un'uscita console decente. Per il codice di produzione suggerirei di raccomandare di rimuovere la registrazione della console.
Si prega di tenere presente che il codice non viene eseguito immediatamente, ma con un ritardo di 2 secondi. In questo modo puoi vedere come appare il DOM prima che venga modificato.
Per coloro che non conoscono il seguente codice restituirà a
se è presente e non falso e b
in caso contrario.
foo = a || b;
Potremmo riscrivere come uno dei due sotto, ma questo è più sintetico.
foo = a ? a : b;
if(a)
foo = a
else
foo = b
Ecco uno jsFiddle.
E il codice!
/** convertToRelative
* Convert absolute width/height to relative. Should work for
* Both HTML and SVG objects. Tries to use CSS attributes, falls
* back on HTML attributes.
*/
function convertToRelative(element) {
// Get Element and Parent
element = $(element);
parent = element.parent();
// If there is no valid with, we need to use attributes
var useAttr = !element.width();
// Get dimensions from css or attributes
var width = element.width() || element.attr('width');
var height = element.height() || element.attr('height');
var pWidth = parent.width() || parent.attr('width');
var pHeight = parent.height() || parent.attr('height');
// Find relative dimensions
var relWidth = (width/pWidth) * 100.0;
var relHeight = (height/pHeight) * 100.0;
// Log info
console.log(element);
console.log("1: "+ parent.height() +", 2: "+ parent.attr('height'));
console.log("Width: "+ width +", Height: "+ height);
console.log("PWidth: "+ pWidth +", pHeight: "+ pHeight);
console.log("relWidth: "+ relWidth +", relHeight: "+ relHeight);
// Clear current stylings
element.removeAttr('width');
element.removeAttr('height');
// Apply relative dimensions
if (useAttr) {
element.attr('width', relWidth +'%');
element.attr('height', relHeight +'%');
} else {
element.width(relWidth +"%");
element.height(relHeight +"%");
}
}
/** walk
* Walk through a DOM element and all its sub elements running
* the convertToRelative function to convert absolute positions
* to relative positions.
* DOES NOT CONVERT THE FIRST ELEMENT, ONLY CHILDREN.
*/
function walk(element) {
$(element).children().each(function() {
convertToRelative(this);
walk(this);
});
}
/** fixBody
* In order to play with relative dimensions for children of the
* body, we need to fix the dimensions of the body. Otherwise it
* will resize as we begin to use relative dimensions.
*/
function fixBody() {
$('body').css('width', $('body').width() +"px");
$('body').css('height', $('body').height() +"px");
}
// Walk the body and all children on a 2 second delay.
setTimeout(function() {
console.log('Running Conversion');
fixBody()
walk('body');
console.log('Conversion Finished');
}, 2000);
Fammi sapere se questo non è quello che volevi o ti imbatti in un problema!
Per le vostre domande
Quali sono gli errori più comuni che possono probabilmente accadrà?
La trappola più comune sarà una conversione errata. Qualcosa andrà storto nella trasformazione e il DOM risultante non assomiglierà all'input.
Probabilmente ci sono tag che non hanno una larghezza o altezza impostata, come svg: g. Poi ci sono definizioni di dimensioni non standard come in svg: circle o attributi a cui non si pensa inizialmente, come svg: testi dy.
Ci sono tag che non hanno un elemento width
/height
. Tuttavia, l'utilizzo di jQuery dovrebbe darci un po 'più di robustezza in questo reparto.Non ho lavorato molto con jQuery e SVG, ma è disponibile un plug-in per il supporto in caso di problemi con gli elementi più oscuri.
C'è un modo per fare un'ipotesi plausibile sul successo in termini di prestazioni a causa di enormi riflessi?
credo che questo codice verrà eseguito in O(m * n)
Dove m = delay for a single reflow
e n = number of nodes
. I Reflows dovrebbero avere un cambiamento abbastanza consistente perché stiamo convertendo gli elementi più grandi prima del più piccolo. MA Posso essere smentito in quest'ultima affermazione.
Cos'altro?
Questo sarà molto difficile per diversi motivi. Pensa all''attributo '
Se sto capendo correttamente, il tuo ridimensionamento SVG dovrebbe essere risolto dalla proprietà 'viewBox'. – Duopixel
Qual è lo scopo alla base di questo? – screenmutt