Outils pour utilisateurs

Outils du site


issue135:inkscape

Having looked at the four main ways of including an SVG file in a web page, we’re going to start examining what you can actually do with SVG files that you can’t achieve with simple raster graphics. Speaking of simple raster graphics, that’s the first of our four ways of including an image, and it’s one that I’m going to dismiss immediately. Once you convert your SVG to a raster graphic, be it a png, jpeg, or gif, it becomes no different in capability to a photo from a digital camera. You can display it in your web page, but that’s about it. Sure, with modern CSS and JavaScript you can make it respond to mouse events, and can use some SVG-style techniques such as masking, clipping and (basic) filtering – but none of those abilities come from the image itself. Your raster image is essentially a rectangle that can only be modified as a single entity, losing all notion of the individual objects in your original SVG file.

Ayant regardé les quatre façons principales d'inclure un fichier SVG dans une page Web, nous allons commencer à examiner ce que vous pouvez faire avec ces fichiers SVG et que vous ne pouvez pas faire avec de simples fichiers raster (bitmap).

À propos des images graphiques simples raster, c'est la première des quatre manières d'inclure une image, et c'en est une que nous allons écarter immédiatement. Une fois que votre SVG est converti en image raster, que ce soit en png, jpeg ou gif, il n'est plus différent d'une photo venant d'un appareil numérique. Vous pouvez l'afficher dans votre page Web, mais c'est tout. Bien sûr, avec les modernes CSS et Javascript, vous pouvez lui faire répondre aux évènements de la souris, et vous pouvez utiliser des techniques de style SVG tels que le masquage, la découpe et le filtrage (basique), mais aucune de ces possibilités ne vient avec l'image elle-même. Votre image raster est en gros un rectangle qui peut seulement être modifié comme une entité unique, en perdant toute notion des objets individuels de votre fichier SVG original.

So let’s move on to the second way of including an image: by linking directly to the SVG file. For this example, we’re going to use the following simple HTML page, which just contains a link to our SVG file in an <img> tag: <!DOCTYPE html> <html> <head> <title>SVG in HTML</title> </head> <body> <img src=“square.svg”></img> </body> </html> As for the SVG file, it’s just a simple square, drawn in Inkscape, and centered in a square page.

Aussi, passons à la deuxième façon d'inclure une image : en se reliant directement au fichier SVG. Pour cet exemple, nous allons utiliser la simple page HTML suivante, qui contient juste un lien vers notre fichier SVG dans une balise <tag> :

<!DOCTYPE html>

<html> <head>

<title>SVG in HTML</title>

</head>

<body>

<img src="square.svg"></img>

</body> </html>

Quant au fichier SVG, ce n'est qu'un simple carré, dessiné dans Inkscape et centré dans une page carrée.

I’m going to wade in and add some handwritten CSS to this file, so, for the sake of clarity (not to mention space), I’ve saved the image as an Optimized SVG. Everything I’m going to do would also work on an Inkscape SVG, but if you’re not familiar with editing XML files, it’s probably worth using optimized files, at least at first, so that you don’t have a load of extra elements and namespaces getting in the way. My optimized file looks like the codew shown below (with a few line breaks added for clarity – they won’t affect the image). A hand-coded version of this image could be even smaller – there would be no need for a <g> with a transform when the x and y coordinates of the <rect> could be adjusted directly. But this is, after all, an Inkscape column, so I’ll work with the output it gives me.

Je vais intervenir pour ajouter un peu de CSS à la main dans ce fichier ; aussi, pour plus de clarté (pour ne pas citer l'espace), j'ai sauvegardé l'image comme SVG optimisé. Tout ce que je vais faire fonctionnerait aussi avec un SVG d'Inkscape, mais, si vous n'êtes pas habitué à la modification des fichiers XML, c'est probablement mieux d'utiliser des fichiers optimisés, au moins au début, afin d'éviter toute une charge d'éléments et d'espaces nommés supplémentaires qui vous gênent. Mon fichier optimisé ressemble au code montré ci-dessous (avec quelques retours à la ligne pour la clarté, ils n'ont pas d'effet sur l'image).

Une version codée à la main de cette image pourrait même être plus petite, il n'y aurait aucun besoin d'un <g> avec une transformation si les coordonnées x et y du <rect> peuvent être ajustées directement. Mais, après tout, c'est un article sur Inkscape ; aussi, je travaillerai avec la sortie qu'il me donne.

With my SVG file created and saved into the same directory as the HTML document, loading the latter into a web browser gives exactly the result you would expect: a web page with a square in it. So far, we haven’t really gained a lot over using a bitmap. Yes, technically it retains a better quality when scaled, and SVG files are often (though not always) smaller than their raster equivalents – but in many cases those are modest benefits at best. But, even when used in an <img>, there are some things we can do with an SVG file that can’t be done with a raster image. Unlike a raster image, an SVG file can include its own CSS code. Let’s begin by making our red square blue (note, I’ve abbreviated the <svg> element for space – in practice the file still contains the full element from the previous example). Code is shown top right.

Mon fichier SVG étant créé et sauvegardé dans le même répertoire que le document HTML, charger ce dernier dans un navigateur Web donne exactement le résultat auquel vous vous attendez : une page Web avec un carré dedans. Pour l'instant, nous n'avons pas vraiment gagné grand chose par rapport à l'utilisation d'un bitmap. Oui, techniquement, il conserve une meilleure qualité lors d'un changement d'échelle, et les fichiers SVG sont souvent (mais pas toujours) plus petits que leurs équivalents en raster, mais, dans beaucoup de cas, ce sont au mieux de petits gains.

Mais, même lors d'une utilisation dans un <img>, il y a des choses que nous pouvons faire avec un fichier SVG qui ne peuvent pas être réalisées avec une image raster. Contrairement à celle-ci, un fichier SVG peut inclure son propre code CSS. Commençons par rendre bleu notre carré rouge (notez que j'ai abrégé l'élément <svg> pour gagner de la place ; en pratique, le fichier contient encore l'élément complet de l'exemple précédent). Le code est présenté en haut à droite.

If you’re not familiar with CSS, then here’s what we’ve done: first there’s a pair of opening and closing <style> elements. The CSS code will be held within them. The CSS code itself consists of a selector that identifies what element(s) in a page the rules should apply to. In this case we’ve used a simple element selector: essentially if you just use the name of an element (in this case “rect”), the rules will apply to every instance of that element. As we’ve only got one <rect> in our file, we know that the rule won’t accidentally affect anything else. After the selector come the rules, in a block between a pair of braces (the “{” and “}” characters). We’ve got only one rule at the moment: to make the fill blue (using hexadecimal RGB syntax for the color). So, let’s reload the page and take a look at our…red square.

Si vous n'êtes pas habitué au CSS, voici donc ce nous avons fait : d'abord, il y a une paire d'éléments <style> ouvrants et fermants. Le code CSS sera contenu à l'intérieur. Le code CSS lui-même consiste en un sélecteur qui identifie quels sont les éléments d'une page auxquels sont appliquées les règles. Dans notre cas, nous avons utilisé un simple élément sélecteur : en gros, si vous utilisez simplement le nom d'un élément (ici, « rect »), les règles seront appliquées à chaque instance de cet élément. Comme nous n'avons mis qu'un <rect> dans notre fichier, nous savons que la règle n'affectera pas autre chose.

Après le sélecteur viennent les règles, dans un bloc entre deux accolades (les caractères « { » et « } »). Nous n'y avons mis qu'une seule règle pour l'instant : rendre bleu le remplissage (en utilisant la syntaxe RGB hexadécimale pour la couleur). Aussi, rechargeons la page et jetons un œil à notre carré… rouge.

As you may already know, CSS stands for “Cascading Style Sheets”, and it’s the “cascading” part that has interfered with our plans. Without going into all the gory details, it’s possible to have more than one source of CSS rules affecting an element, and the details of the cascade dictate which rule will take precedence over the others. In almost all cases, if there’s a rule directly placed on an element using a “style” attribute, that will win. So, in our case, if we just remove the “fill:#f00;” from within the style attribute of the <rect>, the rule we’ve added to the <style> block will win instead. This time if we reload the page… our square is blue.

Comme vous le savez peut-être déjà, CSS veut dire « Cascading Style Sheets » (Feuilles de style en cascade) et c'est la partie « en cascade » qui a interféré avec nos projets. Sans rentrer dans les détails, il est possible d'avoir plus d'une source de règles CSS qui affectent un élément, et les détails de la cascade dictent quelle règle aura la préséance sur les autres. Dans presque tous les cas, s'il y a une règle placée directement sur un élément en utilisant un attribut « style », elle gagnera. Dans notre cas, si nous retirons simplement le « fill:#f00 » de l'attribut de style de <rect>, la règle que nous avons ajoutée au bloc <style> gagnera à la place. Cette fois, si nous rechargeons la page…, notre carré est bleu.

That’s all well and good, but so far we haven’t really achieved anything that couldn’t have been done just by drawing a blue square in the first place. But what we have done is to move the rule that governs the color of the square from the <rect> element (where we can’t easily override it) to a separate block of CSS (where we can). Our options for how to override it, however, are rather limited. This is just an image in our web page, so mouse events aren’t propagated into the file itself. That means no color changes on clicks, or on hovering the mouse over the image. In fact there’s really only one thing we can do to modify the image in this situation: animate. And that requires more CSS.

Tout cela est bel et bien, mais, jusque-là, nous n'avons pas vraiment réalisé quelque chose qui ne pourrait pas être fait en dessinant un carré bleu tout de suite. Mais ce que nous avons fait a été de déplacer la règle qui gouverne la couleur du carré de l'élément <rect> (où nous ne pouvons pas facilement l'abroger) vers un bloc de CSS séparé (où nous le pouvons). Nos options pour comment l'abroger sont cependant plutôt limitées. C'est juste une image dans notre page Web ; ainsi, aucun événement de la souris n'est propagé dans le fichier lui-même. Ça signifie qu'aucune couleur ne change sur un clic ou lors d'un survol de l'image avec la souris. En fait, il n'y a qu'une chose que nous pouvons faire pour modifier l'image dans cette situation : l'animer. Et ceci nécessite plus de CSS.

To begin with, we have to expand our existing set of rules to also include some information about the animation we want to use. At a minimum we have to create a name for the animation (so that you can have more than one in a file), and tell it how long the animation should last. That means our rect selector now looks like this: rect { fill: #00f; animation-name: myAnimation; animation-duration: 3s; } The choice of animation name is up to you, but it has to match whatever name you use in the next section. This is where we define the keyframes – specific points in the animation when we set the values the CSS should take. Here’s a simple example for animating the fill from red to blue: @keyframes myAnimation { 0% { fill: #f00; } 100% { fill: #00f; } }

Pour commencer, nous devons étendre notre jeu de règles existant pour inclure aussi des informations sur l'animation que nous voulons utiliser. Au minimum, nous devons créer un nom pour l'animation (afin de pouvoir en avoir plus d'une dans un fichier), et dire combien de temps doit durer l'animation. Ceci veut dire que notre sélecteur rect ressemble maintenant à ceci :

rect {

fill: #00f;
animation-name: myAnimation;
animation-duration: 3s;

}

Vous avez le choix du nom de l'animation, mais il doit correspondre au nom que vous utilisez dans la section suivante. C'est là que nous définissons les « keyframes » (trames-clés), points spécifiques de l'animation où nous réglons les valeurs que le CSS doit prendre. Voici un exemple simple d'animation du remplissage du rouge au bleu :

@keyframes myAnimation {

0% { fill: #f00; }
100% { fill: #00f; }

}

The syntax is pretty straightforward. First we start with the string “@keyframes” to indicate that this is a set of keyframes, followed immediately by the name we defined earlier. Then, inside a block of code between braces, we have individual entries for each keyframe. A keyframe entry is just the same as any normal block of CSS, except that the selector is replaced with a percentage, representing how far through the animation this block should apply. You pretty much always need at least a block for the start of the animation (0%) and one for the end (100%), but you can add more in-between if you want. Because animations with just two keyframes are so common, you can also use the words “from” and “to” instead of 0% and 100%, which arguably makes the code a little more readable.

La syntaxe est assez simple. D'abord, nous commençons par la chaîne « @keyframes » pour indiquer que c'est un ensemble de trames-clés, suivies immédiatement par le nom que nous avons défini précédemment. Ensuite, dans un bloc de code entre accolades, nous affichons les entrées individuelles de chaque trame-clé.

La saisie d'une trame-clé est la même que pour n'importe quel bloc de CSS, sauf que le sélecteur est remplacé par un pourcentage représentant le moment de l'animation auquel ce bloc devra s'appliquer. Presque à chaque fois, vous aurez au moins besoin d'un bloc au début de l'animation (0 %) et un à la fin (100 %), mais vous pouvez en ajouter d'autres au milieu si vous voulez. Comme les animations avec seulement deux trames-clés sont très classiques, vous pouvez aussi utiliser les mots « from » et « to » à la place de 0 % et 100 %, ce qui rend le code peut-être un peu plus lisible.

So, taking both of the blocks above together, we’ve essentially said “create a set of keyframes called ‘myAnimation’ and run them on the <rect> over a period of 3s. At the start the fill color should be #f00 (red), at the end it should be #00f (blue).” There’s one little caveat to catch: notice that there’s still a fill value on the rect CSS block. At the end of the animation, the “normal” CSS for the element will kick in, so if we don’t also make it blue in there, the fill will change to black. Sometimes that behaviour is desirable; you want to change the style back to the defaults after the animation has run. But, more commonly, you want the style at the end of the animation to persist.

Aussi, en prenant ensemble les deux blocs ci-dessus, nous avons dit en gros « créez un ensemble de trames-clés appelées « myAnimation » et faites-les tourner sur le <rect> pendant une durée de 3 s. Au début, la couleur de remplissage doit être #f00 (rouge), à la fin, elle doit être #00f (bleu). »

Il y a un petit avertissement à prendre en compte : notez qu'une valeur de remplissage sur le bloc de CSS rect existe toujours. À la fin de l'animation, le CSS « normal » de l'élément entre en vigueur ; ainsi, si nous ne le rendons pas bleu ici, le remplissage deviendra noir. Ce comportement est parfois souhaité : vous voulez que le style revienne à la valeur par défaut quand l'animation est finie. Mais, plus souvent, vous voulez que le style de fin d'animation soit persistant.

As an alternative to duplicating the final rules for the element, we can make the last style stick by adding the “animation-fill-mode” rule to our rect block instead. The behaviour we’re seeing is equivalent to setting this to “none”, but you can also use “forwards” to make the element continue using the style from the last keyframe. There’s also “backwards” which does the same with the first keyframe for animations played in reverse, or “both” which works in either direction, and is usually the simplest option to choose. Animations played in reverse? Yes, there’s another property that will let you do that: “animation-direction”. The default value is “normal” (i.e. your animation plays forwards from 0% to 100%), but you can also set it to “reverse” (100% to 0%), “alternate” (0% to 100% then back to 0%) or “alternate-reverse” (100% to 0% then back to 100%).

Comme alternative à la duplication des règles de fin pour l'élément, nous pouvons fixer le dernier style en ajoutant la règle « animation-fill-mode » dans le bloc rect. Le comportement que nous voyons s'assimile à le régler à « none » (rien), mais vous pouvez également utiliser « forwards » pour faire en sorte que l'élément continue à utiliser le style de la dernière trame-clé. Il y a aussi « backwards » qui fait de même avec la première trame-clé pour les animations jouées à l'envers, ou « both » qui fonctionne dans les deux sens et qui est habituellement le choix d'option le plus simple.

Once you’ve decided what direction(s) your animation should run in, you might want to also determine how many times it will be performed. For that we have “animation-iteration-count” which can take the value “infinite” to make the animation run forever, or a number – to specify a particular number of cycles. Note that a single cycle goes from 0% to 100% (or vice versa), so if you set “animation-direction” to “alternate” or “alternate-reverse”, you’ll need to set the count to 2 rather than 1 to display both halves of the animation. With these values, any odd number will finish at the end of the animation, whilst an even number will return you to the start. This is also why it’s usually worth setting “animation-fill-mode” to “both” – you can then change the animation count without having to worry about a sudden change in style, regardless of whether there are an odd or even number of cycles.

Quand vous avez décidé dans quel sens votre animation fonctionnera, vous pourriez vouloir déterminer aussi combien de fois elle sera jouée. Pour ça, nous avons « animation-iteration-count » qui peut prendre la valeur « infinite » pour que l'animation tourne sans arrêt, ou un nombre, pour spécifier un nombre particulier de cycles. Notez que chaque cycle va de 0 % à 100 % (ou l'inverse) ; ainsi, si vous réglez « animation-direction » à « alternate » ou à « alternate-reverse », vous devrez mettre le compte à 2 plutôt qu'à 1 pour afficher les deux moitiés de l'animation. Avec ces valeurs, tout nombre impair terminera à la fin de l'animation, alors qu'un nombre pair vous ramenera au début de l'animation. C'est aussi pourquoi il est habituellement mieux de régler « animation-fill-mode » à « both », vous pouvez alors changer le comptage de l'animation sans avoir à vous soucier d'un changement soudain de style, que ce soit avec un nombre pair ou impair de cycles.

Let’s put all this together, and add another keyframe for good measure. I’ve also thrown in an “animation-delay” so that there’s a short pause between the file loading and the animation starting. Our <style> block now looks something like the text shown on the next page, top right. So far, we’ve animated only one property at a time. But because each keyframe carries a block of CSS, it’s possible to animate more than one property on an object. Here I’ve also animated the stroke color and width to substantially change my square over the course of the animation. The code is shown on the next page, bottom right.

Rassemblons le tout et ajoutons une autre trame-clé pour faire bonne mesure. J'ai aussi mis un « animation-delay », de sorte qu'il y a une courte pause entre le chargement du fichier et le début de l'animation. Notre bloc <style> ressemble maintenant à quelque chose comme le texte présenté à la page suivante, en haut à droite.

Jusqu'ici, nous n'avons animé qu'une propriété à la fois. Mais, parce que chaque trame-clé porte un bloc de CSS, il est possible d'animer plus d'une propriété sur un objet. Ici, j'ai aussi animé la couleur du contour et sa largeur pour changer fortement mon carré pendant la durée de l'animation. Le code est présenté sur la page suivante, en bas à droite.

The result, captured at 2s (the length of the delay, just as the animation starts), 3.5s (halfway through the animation), and 5s (the end of the animation), looks something like this – though, obviously, the real thing isn’t a series of three images, but a single image that transitions through these three states: In practice, the iteration count of 3 and direction of “alternate” means that, after a 2s delay, the square progresses through each of these states (iteration 1), then back again in the opposite direction (iteration 2), then finally through them in order again (iteration 3). At the end of the animation the square remains blue with a thick stroke, due to the presence of animation-fill-mode: both.

Les résultats, capturés à 2 s (la durée du retard, juste quand l'animation commence), 3,5 s (à mi-chemin de l'animation) et 5 s (à la fin de l'animation), ressemble à ceci, bien que, évidemment, la réalité ne soit pas une série de trois images, mais une simple image qui passe par ces trois états :

En pratique, le compte d'itération à 3 et le sens « alternate » signifient que, après un retard de 2 s, le carré progresse à travers ces trois états (itération 1), puis revient dans le sens opposé (itération 2), puis, enfin, encore une fois dans le sens normal (itération 3). À la fin de l'animation, le carré reste bleu avec son contour épais, du fait de la présence de animation-fill-mode: both.

As you can see, animating an SVG image allows for possibilities that aren’t really available with raster images – at least not in a high quality way that works on most browsers. Next time, we’ll expand on these capabilities to push our SVG animations even further.

Comme vous pouvez le voir, l'animation d'une image SVG permet des possibilités qui ne sont pas vraiment à la portée des images raster, du moins, pas d'une façon hautement qualitative qui fonctionne avec la plupart des navigateurs. La prochaine fois, nous étendrons ces possibilités pour pousser nos animations des SVG encore plus loin.

issue135/inkscape.txt · Dernière modification : 2018/08/15 17:47 de andre_domenech