Ceci est une ancienne révision du document !
Last time I showed you the basics of including an Inkscape image in a web page by treating it as an image object in an HTML <img> tag or via CSS, either by exporting as a PNG, or by linking directly to the original SVG image. This time I’m going to consider the other two methods of getting an Inkscape image into a web page: via the <object> tag, or through the use of inline SVG. At first glance the HTML <object> tag isn’t too dissimilar to the <img> approach. The “src” attribute is replaced with “data” and, because <object> tags can include more than just images, we have to include a “type” attribute that contains the SVG MIME type so that the tag knows what format the data will be in. <!DOCTYPE html> <html> <head> <title>SVG in HTML</title> </head> <body> <h1>OBJECT tag</h1> <object type=“image/svg+xml” data=“circle.svg”></object> </body> </html>
La dernière fois, je vous ai montré les bases de l'inclusion d'une image d'Inkscape dans une page Web en la traitant comme un objet image dans une balise HTML <img> ou via le CSS, que soit en exportant un PNG ou en se reliant directement à l'image SVG originale. Cette fois, je vais m'intéresser au deux autres méthodes permettant d'obtenir une image Inkscape dasn une page Web : via la balise <object> ou par l'utilisation du « inline SVG ».
Au premier coup d'œil, la balise HTML <object> n'est pas très différente de l'approche avec <img>. L'attribut « src » est remplacé par « data » et, comme les balises <object> peuvent contenir bien plus que des images, nous devons inclure l'attribut « type » qui contient le type MIME SVG ; ainsi, la balise sait quel sera le format des données.
<!DOCTYPE html>
<html>
<head>
<title>SVG in HTML</title>
</head>
<body>
<h1>OBJECT tag</h1>
<object type="image/svg+xml" data="circle.svg"></object>
</body>
</html>
SVG as an <img> is sandboxed by the browser such that any JavaScript in the file won’t run and no external resources can be loaded (i.e. no web fonts). Even code in the hosting page won’t be able to dig into the contents of the SVG to dynamically change the image. In fact the SVG image behaves largely the same as a rasterised version of the same picture. With the change from <img> to <object> comes vastly more power. The SVG file is treated as a complete, self-contained, document which is allowed to execute JavaScript, load external resources, and even communicate with the host page. In future instalments of this series we’ll explore some of those possibilities in more detail.
Dans un <img>, le SVG est isolé par le navigateur de telle sorte que tout le Javascript contenu dans ce fichier ne pourra pas tourner et q'aucune ressource externe ne pourra être chargée. (par ex., aucune police Web). Même du code dans la page hôte ne sera pas capable de fouiller dans le contenu du SVG pour modifier dynamiquement l'image. En fait, l'image SVG se comporte largement de la même façon que que la version bitmap de la même image.
Le passage de <img> à <object> libère une puissance plus étendue. Le fichier SVG est traité comme un document complet et autonome, ce qui permet d'exécuter du Javascript, de charger des ressources extérieures et même de communiquer avec la page hôte. Dans de futurs numéros de cette série, nous explorerons quelques unes de ses possibilités plus en détail.
The fourth and final approach to including SVG in your web page is so-called “inline SVG”. Inline, in this case, simply refers to directly intermingling the XML code of your SVG file with the HTML code of your web page. For example, here’s the code for an HTML page with an inline SVG image of a red circle with a thick black stroke: <!DOCTYPE html> <html> <head> <title>Inline SVG</title> </head> <body> <svg> <circle fill=“red” stroke=“black” stroke-width=“11” cx=“75” cy=“80” r=“60”> </circle> </svg> </body> </html>
La quatrième et dernière approche pour inclure un SVG dans votre page Web est ce qui est appelé le « inline SVG ». « Iline », dans ce cas, fait simplement référence à l'imbrication directe du code XML de votre fichier SVG avec le code HTML de votre page Web. Par exemple, voici le code d'une page en HML avec l'image « inline SVG » d'un cercle rouge avec un contour noir :
<!DOCTYPE html> <html> <head>
<title>Inline SVG</title>
</head>
<body>
<svg> <circle fill="red" stroke="black" stroke-width="11" cx="75" cy="80" r="60"> </circle> </svg>
</body>
</html>
At a glance the code looks pretty straightforward. Most of it is just the sort of content you would expect of a typical web page, except that the contents in the <body> tag consist of an <svg> block, with some SVG code inside it. The SVG itself is just a single <circle> element with a few attributes to create the desired result. It’s all very neat and tidy. Perhaps too neat and tidy, in fact. This code was hand crafted to ensure that only the bare minimum appears in the SVG block. A typical SVG file from Inkscape, on the other hand, is filled with all manner of extra content, most of which isn’t necessary when using it in this way. Here’s a screenshot from an HTML page that contains both the hand-crafted code above, and a copy of the XML created by Inkscape for the same basic shape:
À première vue, le code est plutôt simple. Majoritairement, c'est la sorte de contenu que vous attendez d'une page Web typique, sauf que le contenu de la balise <body> est un bloc <svg>, avec un peu de code SVG à l'intérieur. Le SVG lui-même est juste un élément <circle> avec quelques attributs pour créer le résultat désiré. Tout est clair, net et précis. Peut-être trop clair, net et précis, en fait.
Ce code est fait à la main pour s'assurer que seul le strict minimum apparaît dans le bloc SVG. Un fichier typique d'Inkscape, d'autre part, est rempli avec toute sorte de contenu additionnel, dont la plupart n'a pas d'utilité quand on l'utilise ainsi. Voici une copie d'écran d'une page HTML qui contient, et le code manuel du dessus, et une copie du XML créé par Inkscape pour cette même forme basique :
Can you spot the difference? No, me neither. But the top circle required SVG code amounting to 107 characters, whereas the second used 2118 – nearly twenty times as much code for the same result! Surely Inkscape can do better than that? There are two reasons for the bloated file size. The first is simply that a hand-coded SVG image always has the potential to be smaller than a computer-created equivalent. Inkscape is a general purpose tool used for all manner of tasks, so it creates general purpose files which are good enough for most circumstances, but which lack the targeted optimisations that would bring the file size down. Unless you want to shave every last byte of flab from your files it’s not usually worth worrying about this first problem. But the second issue is definitely worth looking at, as it’s responsible for far more of your file’s expanded girth: XML namespaces.
Pouvez-vous voir la différence ? Non, moi non plus. Mais le cercle du haut nécessite du code SVG comptant 107 lettres, alors que pour le second il en faut 2118 - à peu près vingt fois plus de code pour le même résultat ! Inkscape peut sûrement faire mieux que ça ?
Il y a deux raisons à cette taille boursouflée du fichier. La première est juste qu'une image SVG codée à la main a toujours la possibilité d'être plus petite que son équivalent créé par l'ordinateur. Inkscape est un outil d'usage général pour toutes sortes de tâches ; aussi, il crée des fichiers à usage général qui sont suffisamment bons pour la plupart des circonstances, mais auxquels il manque les optimisations ciblées qui réduiraient la taille du fichier. Sauf si vous voulez supprimer toute poche de graisse inutile de vos fichiers, ça ne vaut pas le coup de s'inquiéter de ce premier problème. Mais le second défaut mérite d'être vraiment étudié, car il est largement plus responsable de la panse distendue de votre fichier : les espaces nommés du XML.
XML stands for eXtensible Markup Language. Yes, I know. I can only guess it’s because “.eml” was already taken as a file extension for email files, and “X” is way cooler than “E”. But that X or, more to the point, extensibility, is at the heart of the file bloat we can see with Inkscape. One of the more sensible design decisions in XML was to allow different XML-based languages to coexist, even inside the same document. You can see the remnants of this decision in the code above, where we switch from HTML (a not-quite-but-close-to XML language) to SVG, without the browser kicking up a fuss. But in this specific case HTML has been extended to allow the inclusion of SVG elements; XML allows such inclusions in a more generic manner, without the need to extend the host language in any way.
XML veut dire « eXtensible Markup Language » (Langage de balisage extensible). Oui, je ne peux que supposer que c'est parce que eml était déjà pris comme extension de fichier pour les fichiers de mails, et X est bien mieux que E. Mais ce X, ou plus précisément, cette extensibilité, est au cœur de l'inflation du fichier que nous pouvons voir dans Inkscape. Une des décisions de conception les plus judicieuses dans XML a été de permettre à plusieurs langages basés sur XML de coexister, même au sein du même document. Vous pouvez voir les vestiges de cette décision dans le code ci-dessus, où nous passons de HTML (un langage proche du XML, mais pas tout à fait) au SVG, sans aucune réaction du navigateur. Mais dans ce cas spécifique, HTML a été étendu pour permettre l'inclusion des éléments SVG : XML permet de telles inclusions d'une manière plus générique, sans nécessité d'étendre le langage hôte d'aucune manière.
Let’s imagine that we wish to combine two XML languages in a single document. The first is our old friend SVG. The second is a new language I’ve just made up for garden designers – let’s call it GardenML. Before you cry foul, XML is explicitly intended to allow you to create your own domain-specific languages, so although my example is a little contrived, it’s not without precedent in the real world. So, back to the plot: we’ve got an SVG file, filled with <path> elements that describe lines in an image. But we want to include our GardenML content, which is filled with <path> elements that describe… well, paths in a garden. The sort you walk on, made up of bricks or stone slabs, and certainly not the same thing as a path in SVG.
Imaginons que nous voulions combiner deux langages XML dans un seul document. Le premier est notre vieil ami SVG. Le second est un nouveau langage que j'ai juste conçu pour les concepteurs de jardin (garden) - appelons-le GardenML. Avant que vous ne criiez au fou, XML est explicitement conçu pour vous permettre de créer vos propres langages spécifiques d'un domaine ; aussi, bien que mon exemple soit un petit peu artificiel, il n'est pas sans précédent dans la vraie vie. Bon, revenons au sujet : nous avons trouvé un fichier SVG, plein d'éléments <path> qui décrivent les lignes d'une image. Mais nous vous inclure notre contenu en GardenML, qui est rempli d'éléments qui décrit… disons, des allées dans un jardin. Le genre sur lequel on marche, fait de pavés de brique ou de pierre, et certainement pas la même chose que un « path » (chemin) dans SVG.
How does an XML consuming program reconcile these different uses of the same element. How does it know when you’re using an SVG <path>, and when it’s a GardenML <path>? The answer is a thing called a “namespace”. All XML elements have a namespace, but it’s usually set as a default for the whole document, then just implicitly used for each element. Here’s an SVG document which does exactly that: <svg xmlns=“http://www.w3.org/2000/svg”> <path d=“M 130,70 A 60,60 0 1,1 130,69.9 Z” fill=“red” stroke=“black” stroke- width=“11” /> </svg>
Comme fait un programme dévorant du XML pour réconcilier des différentes utilisations du même élément ? Comment sait-il quand vous utilisez une <path> SVG et quand c'est un <path> GardenML ? La réponse est dans une chose appelée « espace nommé ». Chaque élément XML a un espace nommé, il est généralement réglé par défaut pour tout le document, puis simplement utilisé implicitement par chaque élément. Voici un document SVG qui fait exactement ça :
<svg xmlns=“http://www.w3.org/2000/svg”>
<path d="M 130,70 A 60,60 0 1,1 130,69.9 Z" fill="red" stroke="black" stroke- width="11" />
</svg>
Notice the “xmlns” (XML NameSpace) attribute in the <svg> tag? That defines the default namespace for the document. The value is a URI – a Uniform Resource Identifier. It may look like a web address, also known as a URL (Uniform Resource Location), but it’s subtly different. Whereas a URL points to the location of a resource such as a web page, a URI is just a unique identifier which doesn’t have to have a corresponding resource at the specified address (though they often do). In other words, a URL is a path to a real document, whilst a URI is a unique string used to make sure that each namespace is distinct from all the others. A URI may also be a URL, but doesn’t have to be.
Avez-vous noté l'attribut « xmlns » (XML NameSpace - Espace nommé XML) dans la balise <tag> ? Ceci définit l'espace nommé par défaut pour le document. La valeur est une URI - un Uniform Resource Identifier (identifiant uniforme d'une ressource). Elle peut ressembler une adresse Web , aussi connu sous le nom URL (Uniform Resource Location - Localisation uniforme d'une ressource), mais c'est subtilement différent. Là où une URL pointe vers la localisation d'une ressource telle qu'une page Web, une URI est juste un identifiant unique qui n'a pas obligatoirement une ressource correspondante à l'adresse indiquée (bien que ce soit souvent vrai). En d'autre termes, une URL est un chemin vers une document réel, alors qu'une URI est une chaîne unique utilisée pour s'assurer que chaque espace nommé est distinct de tous les autres. Une URI peut être une URL, mais ce n'est pas obligatoire.
When a browser sees that the document’s default namespace is “http://www.w3.org/2000/svg” it knows that any <path> elements are SVG paths, not GardenML paths. But suppose we want to create a file that will both display in the browser and can be interpreted by something that understands GardenML. In that case we need to define more than one namespace in the <svg> element, give all but the default one a handy shortcut name, then prefix the elements and attributes with the shortcut as appropriate. <svg xmlns=“http://www.w3.org/2000/svg” xmlns:garden=“http://fullcirclemagazine.org/GardenML”> <path d=“M 130,70 A 60,60 0 1,1 130,69.9 Z” fill=“red” stroke=“black” stroke-width=“11” /> <garden:path start=“back door” end=“shed” type=“gravel” /> </svg>
This time the default namespace is still SVG, so the <path> element still renders in a web browser. The second <path> element, however, has a prefix of “garden”, identifying it as being from the GardenML namespace that’s defined in the <svg> tag. The browser doesn’t try to render the second path because it doesn’t know what to do with elements in that namespace – but equally it doesn’t complain about them either.
By default attributes are in the same namespace as their element – so in the previous example the “d” attribute is in the SVG namespace, whereas the “start” attribute is in the GardenML namespace. But you can prefix individual attributes as well, should you need to. In this example we’ve got an SVG path to which I’ve added some custom attributes of my own: <path d=“M 130,70 A 60,60 0 1,1 130,69.9 Z” fill=“red” stroke=“black” stroke- width=“11” garden:start=“gate” garden:end=“front door” garden:type=“paved” />
Now all of this might seem a little esoteric, but there are two reasons for explaining it. The first is that namespaces are integral to XML documents, so when we get round to manipulating Inkscape files using JavaScript a little later in this series you’ll be glad of a good grounding in the topic. The second is that it explains why our Inkscape generated files are so much larger than a hand-crafted version. Here’s the opening <svg> element of a typical Inkscape file: Notice all the different namespaces being defined, and a couple of them being used on the last two attributes. The “svg” namespace you now know about, but what of the others? The “inkscape” namespace is used to store extra attributes that hold Inkscape-specific data. Without these, Inkscape would be limited to the features defined in the SVG spec, and wouldn’t be able to provide extra capabilities such as Live Path Effects. The “sodipodi” namespace serves a similar purpose – Inkscape was forked from the Sodipodi program many years ago, but its history lives on in attributes that date from before the split.
The remaining namespaces are used for the metadata about your document that you can enter into the Document Properties dialog. There are several of them because they each refer to a different XML language. Inkscape could have just used it’s own namespace for all of them, but by referring to other well-known languages it improves the ability of the metadata to be automatically parsed and understood by indexing programs or other XML tools. It does bloat the size of the file quite considerably, though. An obvious way to reduce the file size, therefore, is to remove the additional namespaces, elements and attributes. Doing this obviously compromises the SVG file in various ways, from removing the editability of Inkscape-specific features, to loss of metadata. Inkscape does, however, provide a couple of options for doing this for you. They’re both alternative formats in the File > Save As… dialog, but in practice I recommend still saving a normal Inkscape SVG file, then creating your slimline version using File > Save A Copy…. This approach avoids the problem of forgetting to save in the full-fat format when you’ve made an edit, and losing data in the process.
Your first choice is to save as “Plain SVG”. This strips out the proprietary Inkscape and Sodipodi namespaces, and their associated elements and attributes. It still leaves the other namespaces intact, so the file will still contain any metadata you entered into the Document Properties dialog. This option is ideal for use when linking to an SVG file via the <img> or <object> tabs, as it removes the data that the browser doesn’t understand, but leaves any copyright or license information that you may have added. With my simple example file, saving as Plain SVG reduced the file size from 2.1kB to 1.3kB. The other choice is to save as “Optimised SVG”. This presents an additional dialog that lets you choose from a wide range of optimisations that can potentially reduce the file size. Be warned that this option can lead to quite extensive changes in the structure and content of your SVG file, so always test the resultant file to make sure you haven’t optimised away something important. Be particularly wary of reducing the number of significant digits too far, as this will affect the fidelity of your image.
When it comes to the additional namespace-related data, there are a couple of key fields to pay attention to. On the first tab, the “Keep editor data” checkbox determines whether the Inkscape and Sodipodi namespaces are preserved. On the second tab, the “Remove metadata” option will lose all the other namespaces, together with any metadata you may have added to the Document Properties. Also on the second tab, pay attention to the Pretty-printing options. Turning this off can reduce the size further, but if you’re trying to create a file to put inline in an HTML page, a little formatting can make it a lot easier to work with.
So how well does Optimised SVG stack up against hand-written code? It doesn’t reach the 107 characters of my carefully crafted version, but at 277 characters of fairly readable SVG it doesn’t do too bad a job. For most cases where you want to inline your image into an HTML page it will be good enough, with far less scope for errors than trying to write everything by hand. Phew! We’ve covered quite a lot this month, from <object> tags to XML namespaces. If all you want to do is to include a static image in a web page, stick with the methods described last time. But as we move on to more advanced topics, such as incorporating code into our files, the details of this article will become more relevant.