Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
issue194:inkscape [2023/07/03 09:22] – d52fr | issue194:inkscape [2023/07/03 17:30] (Version actuelle) – andre_domenech |
---|
Our aim here is to make it easier to access all the pages of an Inkscape document via a web browser. One thing browsers do, which Inkscape doesn’t, is to run JavaScript. So, by adding a small JS function that will be executed when the file is opened in a browser, we can automatically create <view> elements from each of the <inkscape:page> elements, without the need to manually copy-and-paste coordinates. This is obviously useful when there are a lot of pages to consider, but even for files with just a couple of pages, the ability to just paste the same snippet of code into any file without having to modify it each time makes this approach arguably simpler than manually creating the <view> elements yourself.** | Our aim here is to make it easier to access all the pages of an Inkscape document via a web browser. One thing browsers do, which Inkscape doesn’t, is to run JavaScript. So, by adding a small JS function that will be executed when the file is opened in a browser, we can automatically create <view> elements from each of the <inkscape:page> elements, without the need to manually copy-and-paste coordinates. This is obviously useful when there are a lot of pages to consider, but even for files with just a couple of pages, the ability to just paste the same snippet of code into any file without having to modify it each time makes this approach arguably simpler than manually creating the <view> elements yourself.** |
| |
Au cours des derniers numéros, j'ai étudié la nouvelle fonctionnalité multi-pages d'Inkscape, avec en point d'orgue l'analyse du mois dernier sur la façon dont elle est implémentée dans le fichier SVG. J'ai découvert que les détails de chaque page sont stockés dans un élément propriétaire « page » de l'espace de noms Inkscape - apparaissant dans l'éditeur XML sous la forme <inkscape:page> - plutôt que dans un élément SVG standard <view>. C'est un choix étrange, à mon avis, car l'utilisation de ce dernier aurait rendu les pages supplémentaires plus accessibles via un navigateur Web. | Au cours des derniers numéros, j'ai étudié la nouvelle fonctionnalité multi-pages d'Inkscape, avec en point d'orgue l'analyse du mois dernier sur la façon dont elle est implémentée dans le fichier SVG. J'ai découvert que les détails de chaque page sont stockés dans un élément propriétaire « page » de l'espace de noms Inkscape - apparaissant dans l'éditeur XML comme <inkscape:page> - plutôt que dans un élément SVG standard <view>. C'est un choix étrange, à mon avis, car l'utilisation de ce dernier aurait rendu les pages supplémentaires plus accessibles via un navigateur Web. |
| |
Le mois dernier, j'ai décrit deux méthodes permettant d'inciter un navigateur à afficher les pages supplémentaires. La première utilise une version peu connue de l'identificateur de fragment d'URL pour cibler chaque page par ses valeurs viewBox. Il n'est pas nécessaire de modifier le fichier, mais il faut fouiller dans le XML pour extraire les chiffres pertinents. La seconde approche consiste à modifier le fichier pour ajouter manuellement des éléments <view>, ce qui demande plus de travail mais permet d'utiliser une URL plus sémantique. Si vous n'avez pas lu l'article précédent, je vous conseille vivement de le faire avant de continuer, car celui-ci s'appuie directement sur ces informations. | Le mois dernier, j'ai décrit deux méthodes permettant d'inciter un navigateur à afficher les pages supplémentaires. La première utilise une version peu connue de l'identificateur de fragment d'URL pour cibler chaque page par ses valeurs viewBox. Il n'est pas nécessaire de modifier le fichier, mais il faut fouiller dans le XML pour extraire les chiffres pertinents. La seconde approche consiste à modifier le fichier pour ajouter manuellement des éléments <view>, ce qui demande plus de travail, mais permet d'utiliser une URL plus sémantique. Si vous n'avez pas lu l'article précédent, je vous conseille vivement de le faire avant de continuer, car celui-ci s'appuie directement sur les informations données alors. |
| |
Notre objectif ici est de faciliter l'accès à toutes les pages d'un document Inkscape via un navigateur Web. Une chose que les navigateurs font, et qu'Inkscape ne fait pas, est d'exécuter JavaScript. Ainsi, en ajoutant une petite fonction JS qui sera exécutée lorsque le fichier est ouvert dans un navigateur, nous pouvons créer automatiquement des éléments <view> à partir de chacun des éléments <inkscape:page>, sans qu'il soit nécessaire de copier/coller les coordonnées à la main. C'est évidemment utile lorsqu'il y a beaucoup de pages à prendre en compte, mais même pour des fichiers ne comportant que quelques pages, la possibilité de coller le même bout de code dans n'importe quel fichier sans avoir à le modifier à chaque fois rend cette approche sans doute plus simple que de créer manuellement les éléments <view> soi-même. | Notre objectif ici est de faciliter l'accès à toutes les pages d'un document Inkscape via un navigateur Web. Une chose que les navigateurs font, et qu'Inkscape ne fait pas, est d'exécuter JavaScript. Ainsi, en ajoutant une petite fonction JS qui sera exécutée lorsque le fichier est ouvert dans un navigateur, nous pouvons créer automatiquement des éléments <view> à partir de chacun des éléments <inkscape:page>, sans devoir copier/coller les coordonnées à la main. C'est évidemment utile lorsqu'il y a beaucoup de pages à prendre en compte, mais même pour des fichiers ne comportant que quelques pages, la possibilité de coller le même bout de code dans n'importe quel fichier sans avoir à le modifier à chaque fois rend cette approche sans doute plus simple que de créer manuellement les éléments <view> soi-même. |
| |
| |
••Vous devriez voir apparaître une nouvelle entrée dans la liste avec un ID quelconque. | ••Vous devriez voir apparaître une nouvelle entrée dans la liste avec un ID quelconque. |
••Assurez-vous que l'entrée est sélectionnée. | ••Assurez-vous que l'entrée est sélectionnée. |
••Écrivez votre code dans la case « Contenu » ci-dessous. | ••Écrivez votre code dans la case « Contenu » en dessous. |
••Vous pouvez enregistrer (Ctrl-S) au fur et à mesure que vous développez, sans avoir à fermer la boîte de dialogue. | ••Vous pouvez enregistrer (Ctrl-S) au fur et à mesure que vous développez, sans devoir fermer la boîte de dialogue. |
••Chaque fois que vous enregistrez le fichier, rechargez-le manuellement dans le navigateur (F5) pour en voir l'effet. | ••Chaque fois que vous enregistrez le fichier, rechargez-le manuellement dans le navigateur (F5) pour en voir l'effet. |
| |
The forEach() method expects to have one parameter, and that parameter should be a function.** | The forEach() method expects to have one parameter, and that parameter should be a function.** |
| |
Il n'est pas indispensable de bien comprendre le fonctionnement de ce code pour pouvoir l'utiliser, mais je vais quand même le décrire pour ceux que cela intéresse. Les deux premières lignes définissent simplement des variables pour les espaces de noms dont nous aurons besoin. Nous n'utiliserons pas encore l'espace de noms SVG, mais nous en aurons bientôt besoin, c'est donc le bon moment pour l'introduire. La troisième ligne utilise l'une des fonctions intégrées du navigateur pour trouver tous les éléments « page » dans l'espace de noms Inkscape, et les assigner à une variable en tant que « collection ». | Il n'est pas indispensable de bien comprendre le fonctionnement de ce code pour pouvoir l'utiliser, mais je vais quand même le décrire pour ceux que cela intéresse. Les deux premières lignes définissent simplement des variables pour les espaces de noms dont nous aurons besoin. Nous n'utiliserons pas encore l'espace de noms SVG, mais nous en aurons bientôt besoin et c'est donc le bon moment pour l'introduire. La troisième ligne utilise l'une des fonctions intégrées du navigateur pour trouver tous les éléments « page » dans l'espace de noms Inkscape, et les assigner à une variable en tant que « collection ». |
| |
Pour des raisons historiques et techniques, une « collection » est très similaire à un tableau JS, mais ce n'est pas tout à fait la même chose. De nos jours, les fonctions de tableau de JavaScript sont très puissantes, et nous aimerions donc créer un tableau à partir du contenu de notre collection afin de pouvoir utiliser ces fonctions. C'est exactement ce que fait la partie « array.from(pages) », en itérant sur chaque entrée de la collection pour construire un tableau temporaire. Nous pouvons ensuite utiliser la méthode « forEach » pour exécuter un bloc de code pour chaque entrée du tableau. | Pour des raisons historiques et techniques, une « collection » est très similaire à un tableau JS, mais ce n'est pas tout à fait la même chose. De nos jours, les fonctions de tableau de JavaScript sont très puissantes, et nous aimerions donc créer un tableau à partir du contenu de notre collection afin de pouvoir utiliser ces fonctions. C'est exactement ce que fait la partie « array.from(pages) », en itérant par-dessus chaque entrée de la collection pour construire un tableau temporaire. Nous pouvons ensuite utiliser la méthode « forEach » pour exécuter un bloc de code pour chaque entrée du tableau. |
| |
La méthode forEach() s'attend à avoir un paramètre, et ce paramètre doit être une fonction. | La méthode forEach() s'attend à avoir un paramètre, et ce paramètre doit être une fonction. |
If you’re not very familiar with JavaScript, then do take a few minutes to try to understand the code above. It’s particularly useful to examine where each pair of brackets (‘(…)’) and braces (‘{…}’) start and end, and what content is inside each one.** | If you’re not very familiar with JavaScript, then do take a few minutes to try to understand the code above. It’s particularly useful to examine where each pair of brackets (‘(…)’) and braces (‘{…}’) start and end, and what content is inside each one.** |
| |
Nous pourrions créer une fonction ailleurs et lui passer son nom ici, mais il est plus courant en JS de voir des fonctions « anonymes » utilisées pour de petites tâches comme celle-ci. Dans ce cas, la fonction anonyme est appelée une fois pour chaque élément du tableau et, à chaque fois qu'elle est appelée, on lui passe l'élément courant (dans une variable que nous avons appelée « page ») et l'index de cet élément dans le tableau (« idx »). La syntaxe « => » est utilisée pour les fonctions dites « flèches » et peut être considérée comme une alternative au mot-clé « function » qui vous est peut-être plus familier si vous n'avez pas approché JS depuis un certain temps. | Nous pourrions créer une fonction ailleurs et passer son nom ici, mais il est plus courant en JS de voir des fonctions « anonymes » utilisées pour de petites tâches comme celle-ci. Dans ce cas, la fonction anonyme est appelée une fois pour chaque élément du tableau et, à chaque fois qu'elle est appelée, on lui passe l'élément courant (dans une variable que nous avons appelée « page ») et l'index de cet élément dans le tableau (« idx »). La syntaxe « => » est utilisée pour les fonctions dites « flèches » et peut être considérée comme une alternative au mot-clé « function » qui vous est peut-être plus familier si vous n'avez pas approché JS depuis un certain temps. |
| |
À l'intérieur des accolades ('{...}') se trouve le corps de la fonction - une seule ligne qui utilise la fonction console.log() pour imprimer les valeurs idx et pages sur la console du développeur. Enfin, la dernière ligne ferme non seulement le corps de la fonction, mais aussi la fin de la méthode forEach(). | À l'intérieur des accolades (« {...} ») se trouve le corps de la fonction - une seule ligne qui utilise la fonction console.log() pour imprimer les valeurs idx et pages sur la console du développeur. Enfin, la dernière ligne ferme non seulement le corps de la fonction, mais aussi la fin de la méthode forEach(). |
| |
Si vous n'êtes pas très familier avec JavaScript, prenez quelques minutes pour essayer de comprendre le code ci-dessus. Il est particulièrement utile d'examiner où chaque paire de crochets ('(...)') et d'accolades ('{...}') commence et se termine, et quel contenu se trouve à l'intérieur de chacune d'entre elles. | Si vous n'êtes pas très familier avec JavaScript, prenez quelques minutes pour essayer de comprendre le code ci-dessus. Il est particulièrement utile d'examiner où chaque paire de crochets (« (...) ») et d'accolades (« {...} ») commence et se termine, et quel contenu se trouve à l'intérieur de chacune d'entre elles. |
| |
| |
| |
| |
Une fois ce code en place, enregistrez le fichier et rechargez-le dans le navigateur Web, et vous devriez voir quelque chose dans la console qui ressemble à ceci : | Une fois ce code en place, enregistrez le fichier et rechargez-le dans le navigateur Web. Vous devriez voir quelque chose dans la console qui ressemble à ceci : |
| |
Les nombres verts sont les valeurs idx, qui commencent à zéro parce que... eh bien, il y a de bonnes raisons, mais ce n'est pas l'endroit pour en parler. Il suffit de dire que la plupart des langages de programmation utilisent l'indexation basée sur zéro pour des choses comme les tableaux, et Javascript ne fait pas exception. | Les chiffres verts sont les valeurs idx, qui commencent à zéro parce que... eh bien, il y a de bonnes raisons, mais ce n'est pas l'endroit pour en parler. Il suffit de dire que la plupart des langages de programmation utilisent l'indexation basée sur zéro pour des choses comme les tableaux, et Javascript ne fait pas exception. |
| |
Après chaque chiffre vert, vous pouvez voir une représentation XML de chaque élément SVG dans le tableau - les quatre nœuds <inkscape:page> qui nous intéressent. Chaque nœud est également associé à tout un tas d'autres bagages dans le monde JS, et vous pouvez en voir une grande partie en agrandissant le petit triangle à côté de chacun d'entre eux. En pratique, nous n'avons besoin de rien de tout cela pour notre tâche, alors n'hésitez pas à laisser ce triangle sans l'agrandir, ou à le réduire à nouveau si la curiosité prend le dessus. | Après chaque chiffre vert, vous pouvez voir une représentation XML de chaque élément SVG dans le tableau - les quatre nœuds <inkscape:page> qui nous intéressent. Chaque nœud est également associé à tout un tas d'autres choses dans le monde JS et vous pouvez en voir une grande partie en agrandissant le petit triangle à côté de chacun d'entre eux. En pratique, nous n'avons besoin de rien de tout cela pour notre tâche, alors n'hésitez pas à laisser ce triangle sans l'agrandir, ou à le réduire à nouveau si la curiosité prend le dessus. |
| |
| |
console.log(viewBox);** | console.log(viewBox);** |
| |
Jusqu'à présent, notre code n'a pas accompli grand-chose - juste imprimer l'index, et les mêmes nœuds que nous pouvons voir dans l'éditeur XML d'Inkscape. Mais maintenant que nous avons un moyen d'accéder à chaque élément <page>, nous pouvons commencer à les séparer pour obtenir les détails individuels dont nous avons besoin. Nous allons vouloir extraire les valeurs x, y, width et height. Ces valeurs sont stockées en tant qu'« attributs » de l'élément et peuvent être récupérées à l'aide de la méthode getAttribute(). Ajoutons quatre lignes après console.log() pour récupérer ces valeurs et les assigner à une variable JS (x, y, w, h). | Jusqu'ici, notre code n'a pas accompli grand-chose - juste imprimer l'index et les mêmes nœuds que nous pouvons voir dans l'éditeur XML d'Inkscape. Mais maintenant que nous avons un moyen d'accéder à chaque élément <page>, nous pouvons commencer à les séparer pour obtenir les détails individuels dont nous avons besoin. Nous allons vouloir extraire les valeurs x, y, width et height (largeur et hauteur). Ces valeurs sont stockées en tant qu'« attributs » de l'élément et peuvent être récupérées à l'aide de la méthode getAttribute(). Ajoutons quatre lignes après console.log() pour récupérer ces valeurs et les assigner à une variable JS (x, y, w, h). |
| |
const x = page.getAttribute('x') ; | const x = page.getAttribute('x') ; |
view.setAttribute('viewBox', viewBox) ; | view.setAttribute('viewBox', viewBox) ; |
| |
Il ne reste plus qu'une chose à faire. Bien que nous ayons créé notre nouvel élément <view>, il vit actuellement comme un objet dans le monde JS, et doit être inséré dans le modèle interne du navigateur du document. Nous allons insérer chaque <view> en tant qu'enfant de l'élément <inkscape:page> correspondant afin de garder les choses bien en ordre. Cette dernière ligne fera l'affaire : | Il ne reste plus qu'une chose à faire. Bien que nous ayons créé notre nouvel élément <view>, il vit actuellement comme un objet dans le monde JS et doit être inséré dans le modèle interne du document du navigateur. Nous allons insérer chaque <view> en tant qu'enfant de l'élément <inkscape:page> correspondant afin de garder les choses bien en ordre. Cette dernière ligne fera l'affaire : |
| |
page.appendChild(view) ; | page.appendChild(view) ; |
Quite a bit as it happens. This code is good, but it suffers from a significant limitation: in order for the browser to execute it, the SVG file has to be loaded directly (or within an <object> tag). Most common ways of including SVG files in a web page – via an <img> tag or a CSS url() function – are deliberately prevented from executing JavaScript. This significantly limits the usefulness of this code – at least as it stands.** | Quite a bit as it happens. This code is good, but it suffers from a significant limitation: in order for the browser to execute it, the SVG file has to be loaded directly (or within an <object> tag). Most common ways of including SVG files in a web page – via an <img> tag or a CSS url() function – are deliberately prevented from executing JavaScript. This significantly limits the usefulness of this code – at least as it stands.** |
| |
Vous pouvez éventuellement supprimer les lignes console.log() si vous le voulez, car elles ne sont là que dans un but éducatif et de mise au propre, et elles n'ont aucun effet dans les fonctionnement réel du code. Maintenant que le code est réalisé, comment vraiment l'utiliser ? Chargez simplement le fichier SVG directement dans le navigateur, et ajoutez « #page-2 » à la fin de l'URL pour voir la seconde page. Je suis sûr que vous pouvez trouver la syntaxe pour les autres pages. La saisie d'un ID invalide (par ex., ‘#page-22’) amène simplement le navigateur à afficher la première page. | Vous pouvez éventuellement supprimer les lignes console.log() si vous le voulez, car elles ne sont là que dans un but éducatif et de mise au propre ; elles n'ont aucun effet dans le fonctionnement réel du code. Maintenant que le code est réalisé, comment vraiment l'utiliser ? Chargez simplement le fichier SVG directement dans le navigateur, et ajoutez « #page-2 » à la fin de l'URL pour voir la seconde page. Je suis sûr que vous pouvez trouver la syntaxe pour les autres pages. La saisie d'un ID invalide (par ex., ‘#page-22’) amène simplement le navigateur à afficher la première page. |
| |
Nous l'avons donc : un simple bout de code JS que nous pouvons ajouter à un fichier Inkscape mutipage pour rendre les pages additionnelles disponibles dans un navigateur Web. Qu'est-il possible de faire en plus ? | Et voilà : un simple bout de code JS que nous pouvons ajouter à un fichier Inkscape mutipage pour rendre les pages additionnelles disponibles dans un navigateur Web. Que voulez-vous de plus ? |
| |
Il se trouve qu'il y en a beaucoup. Ce code est bon, mais il souffre d'une limitation importante : de façon à ce que le nnavigateur l'exécute, le fichier SVG doit être chargé directement (ou dans une balise <object>). Les façons le plus habituelles d'inclure des fichiers SVG dans une page Web – via une balise <img> ou une fonction CSS url() – sont délibérément empêchées d'exécuter du Javascript. Ça limite grandement l'utilité de ce code - au moins tel qu'il est. | Beaucoup, en fait. Ce code est bon, mais il souffre d'une limitation importante : de façon à ce que le navigateur l'exécute, le fichier SVG doit être chargé directement (ou dans une balise <object>). Les façons les plus habituelles d'inclure des fichiers SVG dans une page Web – via une balise <img> ou une fonction CSS url() – sont expressément empêchées d'exécuter du Javascript. Ça limite grandement l'utilité de ce code - au moins tel qu'il est. |
| |
| |
Next month, I’ll extend this code a little further to address both these issues. It still won’t give the simple, seamless experience that we could have had if Inkscape natively created named views, but it’s better than being stuck with multi-page files that can display only the first page!** | Next month, I’ll extend this code a little further to address both these issues. It still won’t give the simple, seamless experience that we could have had if Inkscape natively created named views, but it’s better than being stuck with multi-page files that can display only the first page!** |
| |
Un autre problème est que nous avons donné à chaque page un identifiant plutôt générique. Dans Inkscape, il est possible de nommer chaque page - ne serait-il pas plus agréable d'utiliser ces noms pour faire référence à chaque page, plutôt que de se contenter de page-1 et page-2 ? | Un autre problème est que nous avons donné à chaque page un identifiant plutôt générique. Puisque, dans Inkscape, il est possible de nommer chaque page, ne serait-il pas plus agréable d'utiliser ces noms pour faire référence à chaque page, plutôt que de se contenter de page-1 et page-2 ? |
| |
Le mois prochain, j'étendrai ce code un peu plus loin pour résoudre ces deux problèmes. Cela ne donnera toujours pas l'expérience simple et transparente que nous aurions pu avoir si Inkscape avait créé nativement des vues nommées, mais c'est mieux que d'être coincé avec des fichiers multi-pages qui ne peuvent afficher que la première page ! | Le mois prochain, j'étendrai ce code un peu plus loin pour résoudre ces deux problèmes. Cela ne donnera toujours pas l'expérience simple et transparente que nous aurions pu avoir si Inkscape avait créé nativement des vues nommées, mais c'est mieux que d'être coincé avec des fichiers multi-pages qui ne peuvent afficher que la première page ! |
| |