Mal di testa vettoriale

xmlMi sto dedicando in questi giorni a una revisione del mio sito web e sono incappato in un interessante problema la cui soluzione penso possa interessare gli altri geek.
Dovevo inserire alcune icone social da utilizzare sia nella classica dimensione 32×32 pixel, sia in altre grandezze in pagine diverse. La soluzione iniziale a cui avevo pensato era salvare le immagini nella dimensione più grande necessaria e poi utilizzarle ridimensionadole dove servivano più piccole.
Idea apparentemente buona, ma all’atto pratico non molto gradevole esteticamente: il layout engine del browser si occupa anche di scalare le immagini e applicare lo anti-aliasing dove necessario, ma i risultati visivi variano di molto. Mentre Firefox e Chrome fanno un lavoro abbastanza buono, Internet Explorer – guarda un po’ – fa una riduzione pessima; in nessuno dei tre casi, però, il risultato è ottimale.
Tutte le immagini erano in formato PNG, quello che possiamo definire a grandi linee il GIF dell’informatica moderna: supporta, tra le altre cose, lo alpha compositing e la tavolozza RGB a 24bit. Non è adatto per la grafica professionale – dove dominano JPEG, TIFF e i vari formati proprietari – ma è perfettamente equipaggiato per fornire le grafiche decorative su internet.

Per risolvere il problema della riduzione in maniera definitiva, avrei dovuto preparare immagini di diverse dimensioni a monte: un software di fotoritocco può rimpicciolire una immagine in maniera decisamente migliore rispetto a motore di rendering di un browser. In questo caso però avrei dovuto creare tante copie della immagine quante le dimnsioni di cui avevo bisogno.
Ho quindi iniziato a ragionare su una soluzione diversa più pratica e, possibilmente, più geek.

I moderni browser supportano tutti le grafiche in Scalable Vector Graphics ovvero un formato vettoriale basato su standard XML.
Non solo gli addetti del settore, ma ormai anche gli utenti hanno una ideea, per lo meno vaga, di quale sia la differenza tra la grafica vettoriale e quella raster. Nella grafica vettoriale, tutte le informazioni visive sono rappresentati da disegni di primitive – come linee, ovali, poligoni e così via – hanno il vantaggio di poter essere descritte in un linguaggio a marcatore comodo da visualizzare e possono essere compresse come dei semplici file di testo. Più importante, possono essere scalate a piacere in quanto la loro rappresentazione visiva dipende solo dalla precisione del dispositivo che le visualizza.
Una immagine complessa come una fotografia non può efficientemente essere rappresentata in maniera vettoriale: per questo esistono i formati raster di cui abbiamo già parlato in lungo e in largo e che esulano dall’argomento del post.
Nel mio caso specifico, le grafiche da usare sono semplici logotipi o icone ispirate ad essi e di tutte ero in possesso di un file vettoriale di qualche tipo  (soprattutto grazie all’ottimo lavoro di Allan McAvoy): sono quindi passato a trasformare tutte le immagini in file SVG nella versione 1.1.
Dopodichè mi sono dedicato all’inserimento delle immagini e la questione ha iniziato a farsi interessante.

Per prima cosa ho notato un problema per cui, con alcuni browser, le immagini non erano visualizzate, ma venivano servite come file sconosciuti da scaricare, visualizzando il dialogo Salva con nome… al caricamento della pagina.
Ho immaginato fosse un problema con la mappatura dei tipi MIME e dopo un po’ di ricerche su internet ho scoperto che il server web non era correttamente configurato per servire questi file. Per risolvere il problema, non avendo accesso alla configurazione di IIS, dato che si tratta di un sito in hosting, ho modificato questa caratteristica nel file web.config della mia applicazione (scritta in asp.net):

<staticContent>
<remove fileExtension=".svg"/>
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
</staticContent>

Risolto il primo problema, ne ho riscontrato subito un altro.

I browser moderni supportano l’inserimento della grafica SVG come una normale immagine, quindi in teoria si potrebbe usare il tag <img> per inserire il file: questa soluzione è la più veloce, ma la meno flessibile. Infatti non permette di impostare una visualizzazione alternativa (per esempio delle immagini raster) nel caso il browser non fosse in grado di visualizzare lo SVG.
Per ovviare a questo problema si può usare il tag <object> in una maniera simile all’esempio che segue

<object data="../images/logo.svg" type="image/svg+xml"><img src="../images/logo.png" /></object>

In questa maniera, un browser attrezzato visualizzerà lo SVG correttamente, mentre, uno che non lo capisse, effettuerebbe un fallback automatico alla più tradizionale immagine raster.

A questo punto mi sembrava di aver trovato la soluzione definitiva: risultato esteticamente gradevole, codice compatto e relativamente elegante, compatibilità con un numero piuttosto alto di browser anche in versioni vecchiotte.
Non avrei chiesto di più.
Se non fosse stato per i link.

Le immagini devono poter essere cliccabili e portare ad altre pagine del sito (o di siti esterni), ma il tag <a> non funziona su <object>, almeno non nel modo tradizionale. Per esempio non funzionerebbe

<a href="http://www.azienda.it">
<object data="../images/logo.svg" type="image/svg+xml">
<img src="../images/logo.png" />
</object>
</a>

Dopo aver sbattuto la testa ancora per un po’, mi sono imbattuto in un interessante post su StackOverFlow che ha risolto il problema in maniera abbastanza semplice.
Prima cosa da fare, impostare una classe specifica nel foglio di stile CSS:

a.svg
{
position: relative;
display: inline-block;
}

a.svg:after
{
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left:0;
}

e incorporarla poi nel frammento di HTML visto sopra, da modificare così:

<a href="http://www.azienda.it" class="svg">
<object data="../images/logo.svg" type="image/svg+xml">
<img src="../images/logo.png" />
</object>
</a>

Sfortunatamente queste semplici operazioni mi sono costate buona parte della mattinata di oggi. Sicuramente ha giocato a sfavore la mia conoscenza basica di HTML e CSS, ma resta il fatto che queste tecnologie sono obsolete e del tutto inadatte per soddisfare le necessità del web moderno: per quanto alla fine si riesca a “piegarle” al proprio volere, la quantità di codice da scrivere e i “trucchi” da utilizzare sono del tutto incompatibili con una programmazione ragionevolmente veloce e razionale.

Autore: Luca Mauri

Prima di tutto un Geek e un Trekker, Luca Mauri lavora come IT Manager. Entusiasta della esplorazione spaziale e della scienza in generale. È un lettore vorace e un fotografo amatoriale. Fa parte della piccola schiera degli INTJ.

3 pensieri riguardo “Mal di testa vettoriale”

  1. La tecnologia che hai descritto è molto interessante, anche se un po’ acerba.
    Bisogna litigare un po’ per verificare la compatibilità con browser differenti e con quelli “datati” non funziona.

    Ma offre possibilità ancora maggiori: ogni elemento all’interno dell’immagine può essere utilizzato per triggerare eventi (onClick, onMouseOver) con javascript (o meglio Jquery 🙂 ) dando la possibilità di sviluppare pagine ad alta interattività come mappe, cataloghi interattivi etc…

    E visto che l’immagine è a tutti gli effetti XML, può essere facilmente generata dinamicamente.

    Ce’ però una controindicazione: se è molto complicata il browser impegna molta CPU per renderizzarla rallentando il “caricamento” della pagina.

    1. Certamente io mi sono permesso il lusso di guardare alla compatibilità solo con la coda dell’occhio: come giustamente dici tu, il mio codice avrà problemi con browser particolarmente vecchi.
      Il fatto che un utente riesca a vedere o meno il mio sito non mi cambia la vita, mentre ovviamente una azienda dovrebbe porsi il problema con una prospettiva diversa.
      Mi sembra che a volte la volontà di supportare sistemi ormai obsoleti a tutti i costi sia più una moda più che una scelta consapevole (lo fanno gli altri, quindi sarà meglio che lo faccia anch’io): mi piacerebbe vedere uno studio approfondito sul rapporto costi/benefici del supportare TUTTO scrivendo più codice e più complesso, impiegando quindi più risorse in progettazione, realizzazione e manutenzione. Ma questa è un’altra storia che esula dal discorso, magari la affronteremo in futuro su questo blog.

      Per quanto riguarda la generazione programmatica dell’immagine hai ragione: apre le porte a un mondo intero che, sfortunatamente, io non ho avuto (ancora) tempo di esplorare. Per chi fosse interessato all’argomento, segnalo questo articolo sulla MSDN http://msdn.microsoft.com/en-us/magazine/cc164114.aspx che introduce l’argomento.

      Sulla quantità di risorse computazionali per rendere un SVG in confronto a un PNG (o similia) onestamente non ho trovato grandi risorse online, ma ammetto di aver fatto solo una ricerca superficiale. Se qualcuno ne sa di più, sarebbe forse interessante riparlarne in un post separato.

      1. Non mi sembra che la moda di supportare tutti i sistemi obsoleti sia cosi` diffusa, in realta`…

        L’approccio corretto sarebbe quello di usare solo cio` che e` standard, e possibilmente fare qualcosa che sia compatibile anche con standard antichi, non con browser antichi.

        Se ti limiti a standard antichi, farai sicuramente qualcosa di compatibile anche con lettori vocali, dispositivi mobili, e chi piu` ne ha piu` ne metta…

Spazio per un commento