Outils pour utilisateurs

Outils du site


issue140:inkscape

Last time, I showed you how you can use a fragment identifier in the URL that points to your SVG file in order to make a browser show only a small part of the whole image. With a suitably crafted string, you can precisely identify a rectangular section of the image to display by specifying the x and y coordinates of the top left of the rectangle, together with its width and height. I also demonstrated how you could create named views so that the coordinates are entirely contained within the SVG file and the enclosing web page doesn’t need to know the gory details; all it needs to know is the ID of the view to display. Through this technique, you can effectively turn a single image into a number of named tiles, spread out along the x and y plane. This month, you’ll discover that it’s possible to perform a similar trick in the z-axis. In other words, you can stack several sub-images on top of each other, and then choose to show only one of them by putting its ID into the fragment identifier.

La dernière fois, je vous ai montré comment vous pouvez utiliser un identificateur de fragment dans l'URL qui pointe vers votre fichier SVG de façon à obliger un navigateur à n'afficher qu'une petite partie de toute l'image. Avec une chaîne bien ficelée, vous pouvez identifier précisément une section rectangulaire de l'image à afficher en spécifiant des coordonnées x et y de l'angle haut gauche du rectangle, associées à sa hauteur et sa largeur. J'ai aussi montré comment vous pouvez créer des vues nommées de sorte que les coordonnées soient toutes contenues dans le fichier SVG et que la page Web réceptrice n'ait pas besoin de connaître tous ces petits détails : elle n'a besoin de connaître que l'identifiant de la vue à afficher.

Par cette technique, vous pouvez effectivement transformer une simple image en quantité de tuiles nommées, réparties sur la surface en x et y. Ce mois-ci, vous découvrirez qu'il est possible de réaliser une astuce similaire sur l'axe z. En d'autres termes, vous pouvez empiler plusieurs sous-images les unes sur les autres, puis choisir de n'en montrer qu'une en mettant son identifiant dans l'identificateur de fragment.

The starting point for this technique isn’t actually SVG, but HTML. The way this trick works relies heavily on inheriting certain behaviours from the HTML and CSS world that can be manipulated into doing something useful in SVG. Let’s start with a simple HTML file (shown top right). Allowing for the requirement to keep magazine listings short, try to imagine that this page has a lot of text in each paragraph, a lot of paragraphs in each section, and more sections than I’ve included in the sample. If you’re trying out the code yourself, make sure to include enough content for you to have to scroll quite a lot to get to the bottom section. With a lengthy page of text, it would be nice to be able to jump straight to a section via a list of links at the top of the page – a table of contents. To do that, we use the <a> tag in two different forms: around each section to “name” the link target, and in the table of contents to create a link that will jump straight to the named target. Skipping the boilerplate code and the content of the <p> tags we get the code shown on the previous page (bottom right).

Le point de départ de cette technique n'est pas vraiment le SVG, mais le HTML. Pour fonctionner, cette astuce s'appuie fortement sur la récupération de certains comportements des mondes du HTML et du CSS qui peuvent être manipulés pour les rendre utiles dans SVG. Commençons par un fichier HTML simple (montré en haut à droite).

Compte tenu du fait que les listings du magazine doivent rester courts, essayez d'imaginer que cette page a beaucoup de texte dans chaque paragraphe, beaucoup de paragraphes dans chaque section, et plus de sections que j'en ai inclus dans cet échantillon. Si vous testez le code par vous-même, assurez-vous d'inclure assez de contenu pour que vous ayez beaucoup de défilement à opérer pour atteindre la section du bas.

Avec une longue page de texte, il serait sympa de pouvoir sauter directement vers une section via une liste de liens en haut de page - un sommaire. Pour le faire, nous utilisons la balise <a> sous deux formes différentes : autour de chaque section pour « nommer » la cible du lien, et dans le sommaire pour créer un lien qui sautera directement à la cible nommée. En laissant tomber le code standard et le contenu des balises <p>, nous obtenons le code montré sur la page précédente (en bas à droite).

A quick trip to a “lorem ipsum” generator to fill out the content, and the web page looks something like this when loaded into a browser: Clicking the links in the Table of Contents will scroll the browser so that the target of the link is visible on screen. The “href” attribute in those links is essentially just the fragment identifier part of the full URL. Indeed, if we modify the full URL in the browser to append “#sec3” to the end of the URL, the browser will also jump to the third section. Okay, so appending the ID of an <a> element to the URL will make the page scroll to that target. What’s that got to do with SVG? To answer that we need to introduce another part of this puzzle: the CSS “:target” selector. Here’s a section of CSS that should be added to our test page: <style> :target { color: red; }

Un passage rapide dans un générateur de « lorem ipsum » pour remplir le contenu et la page Web ressemble à quelque chose comme ceci quand elle est chargée dans un navigateur :

En cliquant sur les liens du sommaire, le navigateur fera défiler le texte pour rendre la cible du lien visible à l'écran. L'attribut « href » dans ces liens n'est que la partie d'identificateur de fragment de l'URL complète. Bien sûr, si vous modifiez l'URL complète dans le navigateur pour ajouter « #sec3 » à la fin de l'URL, le navigateur sautera aussi à la troisième section.

Ainsi, l'ajout de l'identifiant d'un élément <a> à l'URL, fera défiler la page jusqu'à cette cible. Mais qu'est-ce que ça a à voir avec SVG ? Répondre à ceci nécessite que nous introduisions une nouvelle pièce du puzzle : le sélecteur « :target » du CSS. Voici un extrait du CSS qui pourrait être ajouté à notre page de test :

<style>

:target {
	color: red;
}

This tells the browser to run this little algorithm: • Does the URL have a fragment identifier? • If so, does it match a target ID in the page? • If it does, apply the “color: red” property to the matching element (in addition to the default behaviour of scrolling the element into view). Now, as you click the entries in the table of contents or manipulate the URL by hand, the target section is rendered with red text, rather than black. We’ve got a way to apply a style to only the element specified in the fragment identifier. Which means we can instead do something like this: <style> a { display: none; } :target { display: initial; } </style>

Ceci dit au navigateur de lancer ce petit algorithme : • L'URL a-t-elle un identificateur de fragment ? • Si oui, correspond-il à un identifiant cible de la page ? • Si oui, appliquer la propriété « color: red » à l'élément correspondant (en plus du comportement par défaut qui fait afficher l'élément à l'écran).

Maintenant, quand vous cliquez sur les lignes du sommaire ou que vous bricolez l'URL à la main, la section cible est rendue avec le texte en rouge, plutôt qu'en noir. Nous avons trouvé une façon d'appliquer un style au seul élément spécifié dans l'identificateur de fragment. Ce qui signifie qu'à la place, nous pouvons faire quelque chose comme ceci :

<style>

a { display: none; }
:target {
	display: initial;
}

</style>

This will hide all the <a> elements, and their descendants, then only show the one that is being targeted by the fragment identifier. As a side-effect, it also hides the links in the Table of Contents. A more fine-grained rule could deal with that, but I just deleted the whole table from my document as it’s not needed any more. Now, when manually adding, for example, “#sec2” to the end of the URL we will see only the specified section on screen. So we’ve now got a way to show only a single element (and its descendants), based on a label in a fragment identifier. All we need to do is transplant that same logic to the world of SVG, and the browser, using the same CSS rules as it does for an HTML page, will show only the element we’ve chosen. The first thing we’ll need, therefore, is a type of element that can act as a container for the content we want to show and hide. In SVG terms, that would be a <g>, which in Inkscape is exposed as a group, but is also used for layers (as noted in previous instalments, layers are just groups with extra metadata). There are minor pros and cons to each: considering that we need each <g> to have an ID, groups have a small advantage in that the Object Properties dialog (from the context menu) can be used to set the value. Although you can rename layers, doing so doesn’t affect their ID, requiring a trip to the XML editor instead.

Ceci cachera tous les éléments <a>, et leurs descendants, et ne montrera que celui qui est ciblé par l'identificateur de fragment. Effet collatéral : cela cache aussi les liens du sommaire. Une règle plus fine pourrait gérer cela, mais j'ai simplement effacé la table complète dans mon document, car je n'en avais plus du tout besoin. Maintenant, en ajoutant manuellement, par exemple, « #sec2 » en fin d'URL, nous ne voyons à l'écran que la section spécifiée.

Ainsi, nous avons trouvé une façon de ne montrer qu'un élément unique (et ses descendants), basée sur une étiquette dans un identificateur de fragment. Nous n'avons qu'à transposer la même logique au monde du SVG, et le navigateur, utilisant les mêmes règles du CSS que dans une page HTML, ne montrera que la section spécifiée à l'écran.

Ainsi donc, la première chose dont nous avons besoin est un type d'élément qui peut agir comme un conteneur pour le contenu que nous voulons montrer et cacher. En termes du SVG, ce serait un <g>, qui, dans Inkscape, est vu comme un groupe, mais qui est aussi utilisé pour les calques (comme indiqué dans des articles précédents, les calques ne sont que des groupes avec des méta-données supplémentaires). Il y a des petits avantages et inconvénients pour chacun : en considérant qu'il faut un identifiant pour chaque <g>, les groupes ont un petit avantage car le dialogue des Propriétés de l'Objet (dans le menu contextuel) peut être utilisé pour paramétrer la valeur. Bien que vous puissiez renommer les calques, ceci ne change pas leur identifiant, qui, à la place, nécessite une visite dans le XML.

But layers have one big advantage: they’re much easier to show and hide when working in Inkscape. Given that this workflow requires each image to be stacked upon the others, this advantage becomes invaluable for anything more than a couple of groups. For the rest of this tutorial, therefore, I’ll be using layers. Continuing from last month’s instalment, I’m going to stack the same four objects I used previously – a circle, a star, a spiral and some text – putting them into individual layers. It’s worth reiterating at this point that each layer could contain more than a single element – I just didn’t want to clutter up the screenshots too much by introducing more content. In practice, each layer would typically be an SVG image in its own right, potentially containing multiple elements, groups, clones and filters. In a more complex situation, you can clearly see how the ability to hide and lock individual layers makes this method generally superior to just using Inkscape groups.

Mais les calques ont un gros avantage : dans Inkscape, ils se montrent et se cachent bien plus facilement. Étant donné que notre déroulé de programme nécessite que chaque image soit placée au-dessus des autres, cet avantage devient inestimable pour celui qui a besoin de plus d'une paire de groupes. Aussi, pour le reste de ce tutoriel, j'utiliserai les calques. En pousuivant l'article du mois dernier, je vais empiler les mêmes quatre objets que j'ai déjà utilisés - un cercle, une étoile, une spirale et du texte - en les mettant chacun dans un calque.

Je me permets de redire ici que chaque calque peut contenir plus d'un élément - je souhaitais juste ne pas trop encombrer les copies d'écran en ajoutant plus d'éléments. En pratique, chaque calque peut typiquement être une image SVG de plein droit, contenant potentiellement plusieurs éléments, groupes, clones et filtres. Dans une situation plus complexe, vous pouvez voir clairement que la capacité à cacher et à verrouiller individuellement les calques rend cette méthode généralement supérieure aux simples groupes de Inkscape.

With my layers created, the next step is to open the XML Editor (Edit > XML Editor) and set the IDs for the layers. In the screenshot, you can see that I’ve already set the IDs for “circle”, “star” and “spiral”, and I’m about to change “layer1” to “text”. While you’ve got the XML editor open, it’s worth noting what happens when you show and hide a layer. Each layer has a “style” attribute which contains “display: inline” if it’s visible, or “display: none” if it’s hidden. We’ll come back to this later but, for now, just remember that there’s a “style” attribute that holds the “display” property directly on each layer. Once your stack of drawings is complete, and your layer IDs have all been set, you’ll need to save the file and open it in a text editor. It’s time to add a block of CSS that will turn off the layers, then turn on only the layer specified in the fragment identifier. The placement of the CSS in the file doesn’t matter too much, but I usually put it just after the opening <svg …> tag (shown below).

Mes calques étant créés, l'étape suivante est l'ouverture de l'éditeur XML (Édition > Éditeur XML) et le paramétrage des identifiants des calques. Dans la copie d'écran, vous pouvez voir que j'ai déjà réglé les identifiants du « circle » (cercle), « star » (étoile) et « spiral » (spirale) et que je vais changer « layer1 » (calque1) en « text » (texte).

Pendant que l'éditeur XML est ouvert, il est intéressant de voir ce qui se passe quand on montre ou cache un calque. Chaque calque a un attribut « style » qui contient « display: inline » s'il est affiché ou « display: none » s'il est caché. Nous y reviendrons plus loin, mais, pour le moment, souvenez-vous simplement qu'il y a un attribut « style » qui contient directement la propriété « display » de chaque calque.

Une fois que votre empilage de dessins sera terminé et que vous aurez inscrit tous les identifiants des calques, vous devrez sauvegarder votre fichier et l'ouvrir dans un éditeur de texte. C'est le moment d'ajouter un bloc de CSS qui masquera les calques, puis qui affichera uniquement le calque spécifié dans l'identificateur de fragment. La position du CSS dans le fichier n'a pas beaucoup d'importance, mais je le mets habituellement juste après la balise ouvrante <svg …> (voir ci-dessous).

The “svg > g” syntax just means “this rule should affect only <g> elements that are immediate children of an <svg> element”, so it doesn’t affect any sub-layers. Otherwise, it’s pretty similar to the HTML rules we used earlier, but with the addition of “!important” on the properties. This tells the browser that these rules should take precedence over those in the “style” attributes on the layer – without them our new block of code would be ignored. You could avoid them if you manually removed the properties from the style attributes on each layer, but as Inkscape will add them back in again if you ever need to edit the file, it quickly becomes a thankless chore. Sprinkling a few “!important” declarations around isn’t particularly good coding practice, but it’s a lot more practical. With our SVG stack set up, we can reference the images with a fragment identifier in the HTML, in a similar manner to the named views we used last time (shown top right).

La syntaxe « svg > g » signifie simplement que « cette règle ne doit affecter que les éléments <g> qui sont des enfants directs d'un élément <svg> » ; ainsi, elle n'a pas d'effet sur les sous-calques. Autrement, elle est très proche des règles du HTML que nous avons utilisées avant, mais avec l'ajout de « !important » dans les propriétés. Ceci dit au navigateur que ces règles doivent être prioritaires sur celles de l'attribut « style » du calque ; sans elles, notre nouveau bloc de code serait ignoré. Vous pouvez l'éviter en enlevant manuellement les propriétés dans l'attribut « style » de chaque calque, mais, comme Inkscape les rajoutera à nouveau si jamais vous éditez le fichier, ça devient vite une corvée. Parsemer quelques déclarations « !important » ça et là n'est pas une très bonne pratique, mais c'est beaucoup plus simple.

Notre pile SVG étant paramétrée, nous pouvons référencer les images avec un identificateur de fragment dans le HTML, de la même manière que nous l'avons utilisé la dernière fois pour les vues nommées (montré en haut à droite).

The resultant web page looks like this: With SVG stacks, it’s also possible to have another layer that sits behind all the others, but which is always visible, regardless of the fragment identifier. Consider a single background layer, with its ID set to “background”. This additional CSS selector would ensure that it’s always visible: #background { display: initial !important; } With named views and stacks giving broadly similar results, you might want to know which one is better to use. For many cases, either will work: named views arguably require more work to set up, but provide an advantage of being able to see all the individual images in Inkscape at once. Views also work better if your images are different sizes. Stacks, on the other hand, work well if your images require a single common background, or if it’s easier to draw each image by stacking it on top of the previous ones to help with alignment. As is so often the case, the real answer is to try both approaches and see which one works best for you.

La page Web résultante ressemble à ceci :

Avec les piles du SVG, il est aussi possible d'avoir un autre calque, placé sous tous les autres, mais qui est toujours visible, quel que soit l'identificateur de fragment. Considérez un simple calque de fond, avec « backgroud » (fond) comme identifiant. Ce sélecteur CSS supplémentaire assurera qu'il est toujours visible :

#background {

      display: initial !important;

}

Les vues nommées et les piles donnant en gros des résultats similaires, vous pourriez aimer savoir laquelle est la meilleure à utiliser. Dans de nombreux cas, les deux fonctionnent : les vues nommées nécessitent sans doute plus de travail pour les paramétrer, mais elles fournissent l'avantage d'être capables de montrer individuellement toutes les images d'un coup dans Inkscape. Les vues marchent mieux aussi si vos images sont de tailles différentes. En revanche, les piles fonctionnent bien si vos images ont besoin d'un seul fond unique, ou s'il est plus simple de dessiner chaque image en les empilant les unes sur les autres pour faciliter leur alignement. Comme c'est souvent le cas, le bonne réponse est d'essayer les deux approches et de voir laquelle fonctionne le mieux pour vous.

issue140/inkscape.txt · Dernière modification : 2019/01/07 15:58 de auntiee