


Nous avons de nombreux types de graphiques bien connus: bar, beignet, ligne, tarte, vous l'appelez. Toutes les bibliothèques de graphiques populaires les soutiennent. Ensuite, il existe les types de graphiques qui n'ont même pas de nom. Découvrez ce tableau de rêve avec des carrés empilés (imbriqués) qui peuvent aider à visualiser les tailles relatives, ou comment les différentes valeurs se comparent les unes aux autres:
Ce que nous faisons
Sans aucune interactivité, la création de ce design est assez simple. Une façon de le faire est d'empiler des éléments (par exemple, des éléments SVG
Mais les choses deviennent plus difficiles une fois que nous avons introduit une certaine interactivité. Voici comment cela devrait être: lorsque nous déplaçons notre souris sur l'une des formes, nous voulons que les autres se fanent et s'éloignent.
Nous allons créer ces formes irrégulières à l'aide de rectangles et de masques - littéral
Maintenant, avant de commencer, vous vous demandez peut-être si une meilleure alternative au SVG à l'utilisation de formes personnalisées. C'est vraiment une possibilité! Mais des formes de dessin avec un
Par exemple, voici comment nous devrions représenter la plus grande forme bleue en utilisant un
<svg viewbox="0 0 320 320" width="320" height="320"> <chemin d="M320 0H0V56H264V320H320V0Z" fill="# 264653"></chemin> </svg>
Si le 0h0v56… n'a aucun sens pour vous, consultez «la syntaxe du chemin SVG: un guide illustré» pour une explication approfondie de la syntaxe.
Les bases du graphique
Étant donné un ensemble de données comme ceci:
type dataSetEntry = { étiquette: chaîne; valeur: numéro; }; type dataSet = dataSetEntry []; const RawDataset: DataSet = [ {label: 'bad', valeur: 1231}, {label: 'début', valeur: 6321}, {étiquette: «développement», valeur: 10028}, {label: 'accompli', valeur: 12123}, {étiquette: 'exemplaire', valeur: 2120} ]]
… Nous voulons nous retrouver avec un SVG comme ceci:
<svg viewbox="0 0 320 320" width="320" height="320"> <rect width="320" height="320" y="0" fill="..."> rect> <rect width="264" height="264" y="56" fill="..."> rect> <rect width="167" height="167" y="153" fill="..."> <rect width="56" height="56" y="264" fill="..."> rect> <rect width="32" height="32" y="288" fill="..."> rect> </rect></rect></rect></rect></rect></svg>
Déterminer la valeur la plus élevée
Cela deviendra évident dans un instant pourquoi nous avons besoin de la valeur la plus élevée. Nous pouvons utiliser le math.max () pour l'obtenir. Il accepte n'importe quel nombre d'arguments et renvoie la valeur la plus élevée dans un ensemble.
const dataSetHighestValue: Number = Math.max ( ... RawDataset.map ((Entrée: DataSeTentry) => Entry.Value) ));
Comme nous avons un petit ensemble de données, nous pouvons simplement dire que nous obtiendrons 12123.
Calcul de la dimension des rectangles
Si nous regardons la conception, le rectangle représentant la valeur la plus élevée (12123) couvre toute la zone du graphique.
Nous avons arbitrairement choisi 320 pour les dimensions SVG. Étant donné que nos rectangles sont des carrés, la largeur et la hauteur sont égales. Comment pouvons-nous faire 12123 égal à 320? Et les valeurs moins «spéciales»? Quelle est la taille du rectangle 6321?
Interrogé une autre manière, comment cartographier un nombre d'une plage ([0, 12123]) à un autre ([0, 320])? Ou, en termes plus mathématiques, comment pouvons-nous évoluer une variable à un intervalle de [a, b]?
Pour nos fins, nous allons implémenter la fonction comme celle-ci:
const RemapValue = ( Valeur: numéro, Frommin: numéro, Frommax: numéro, Tomin: numéro, Tomax: numéro ): numéro => { return ((valeur - fromin) / (Frommax - fromin)) * (tomax - tomin) tomin; }; RemapValue (1231, 0, 12123, 0, 320); // 32 RemapValue (6321, 0, 12123, 0, 320); // 167 RemapValue (12123, 0, 12123, 0, 320); // 320
Étant donné que nous cartographions les valeurs sur la même plage dans notre code, au lieu de passer les minimums et les maximums encore et encore, nous pouvons créer une fonction de wrapper:
const ValueReMapper = ( Frommin: numéro, Frommax: numéro, Tomin: numéro, Tomax: numéro ) => { return (valeur: nombre): numéro => { return remapValue (valeur, Frommin, Frommax, tomin, tomax); }; }; const RemapDatasetValuetOsvgDimension = ValueRemapper ( 0, dataSetHiGhestValue, 0, svgdimension ));
Nous pouvons l'utiliser comme ceci:
remapdatasetvalutosvgdimension (1231); // 32 remapdatasetvalutosvgdimension (6321); // 167 RemapdatasetvalutOsvgdimension (12123); // 320
Créer et insérer les éléments DOM
Ce qui reste a à voir avec la manipulation DOM. Nous devons créer les éléments
Notez que nous utilisons les CreateElementns au lieu de la création plus courante. C'est parce que nous travaillons avec un SVG. Les éléments HTML et SVG ont des spécifications différentes, donc ils relèvent d'un autre espace de noms URI. Il arrive juste que le CreateElement utilise facilement l'espace de noms HTML! Donc, pour créer un SVG, nous devons être aussi verbeux:
Document.CreateElementns ('http://www.w3.org/2000/svg', 'svg') en tant que svgsvgementment;
Nous pouvons sûrement créer une autre fonction d'assistance:
const CreateSVGNElement = (élément: String): svgement => { return document.createElementns ('http://www.w3.org/2000/svg', élément); };
Lorsque nous ajoutons les rectangles au DOM, nous devons prêter attention à leur commande. Sinon, nous devions spécifier explicitement l'indice Z. Le premier rectangle doit être le plus grand, et le dernier rectangle doit être le plus petit. Mieux vaut trier les données avant la boucle.
const data = rawdataset.sort ( (A: DataSeTentry, B: DataSeTentry) => B.Value - A.Value )); data.ForEach ((d: dataSetEntry, index: numéro) => { const REct: svGrecedElement = créeSvGnSelement («rect») comme svGrecedElement; const REctDimension: Number = remapDataSetValuetoSvgdimension (d.Value); rect.setAttribute ('width', `$ {rectdimension}`); rect.setAttribute ('height', `$ {rectdimension}`); rect.setAttribute ('y', `$ {svgdimension - rectdimension}`); SVG.APPEndChild (RECT); });
Le système de coordonnées commence par le haut à gauche; C'est là que le [0, 0] est. Nous allons toujours dessiner les rectangles du côté gauche. L'attribut x, qui contrôle la position horizontale, est par défaut à 0, nous n'avons donc pas à le définir. L'attribut Y contrôle la position verticale.
Pour donner l'impression visuelle que tous les rectangles proviennent du même point qui touche leurs coins inférieurs à gauche, nous devons pousser les rectangles vers le bas pour parler. Par combien? Le montant exact que le rectangle ne remplit pas. Et cette valeur est la différence entre la dimension du graphique et le rectangle particulier. Si nous assemblons tous les bits, nous nous retrouvons avec ceci:
Nous avons déjà ajouté le code de l'animation à cette démo à l'aide de CSS.
Découper des rectangles
Nous devons transformer nos rectangles en formes irrégulières qui ressemblent au numéro sept, ou la lettre L tourna de 180 degrés.
Si nous nous concentrons sur les «parties manquantes», nous pouvons voir qu'ils découpent les mêmes rectangles avec lesquels nous travaillons déjà.
Nous voulons cacher ces découpes. C'est ainsi que nous allons finir avec les formes L que nous voulons.
Masquage 101
Un masque est quelque chose que vous définissez et appliquez plus tard à un élément. En règle générale, le masque est incliné dans l'élément
<svg> <masque> mask> </masque></svg>
Dans la balise
<svg> <masque> mask> <rect mask="url (#MycleVerlyNamedMask)"> </rect></masque></svg>
Ce n'est pas le seul moyen de définir ou d'appliquer un masque, mais c'est le moyen le plus simple pour cette démo. Faisons un peu d'expérimentation avant d'écrire un code pour générer les masques.
Nous avons dit que nous voulons couvrir les zones de découpe qui correspondent aux tailles des rectangles existants. Si nous prenons le plus grand élément et que nous appliquons le rectangle précédent comme masque, nous nous retrouvons avec ce code:
<svg viewbox="0 0 320 320" width="320" height="320"> <masque> <rect width="264" height="264" y="56" fill=""> mask> <rect width="320" height="320" y="0" fill="# 264653" mask="url (#themask)"> </rect></rect></masque></svg>
L'élément à l'intérieur du masque a besoin d'une valeur de remplissage. Qu'est-ce que cela devrait être? Nous verrons des résultats entièrement différents en fonction de la valeur de remplissage (couleur) que nous choisissons.
Le remplissage blanc
Si nous utilisons une valeur blanche pour le remplissage, nous obtenons ceci:
Maintenant, notre grand rectangle est la même dimension que le rectangle de masquage. Pas exactement ce que nous voulions.
Le remplissage noir
Si nous utilisons à la place une valeur noire, cela ressemble à ceci:
Nous ne voyons rien. C'est parce que ce qui est rempli de noir est ce qui devient invisible. Nous contrôlons la visibilité des masques à l'aide de remplissages blancs et noirs. Les lignes en pointillés sont là comme une aide visuelle pour référencer les dimensions de la zone invisible.
Le remplissage gris
Maintenant, utilisons quelque chose entre le blanc et le noir, disons gris:
Ce n'est ni entièrement opaque ni solide; c'est transparent. Donc, maintenant, nous savons que nous pouvons contrôler le «degré de visibilité» ici en utilisant quelque chose de différent des valeurs blanches et noires, ce qui est une bonne astuce à garder dans nos poches arrière.
Le dernier bit
Voici ce que nous avons couvert et appris sur les masques jusqu'à présent:
- L'élément à l'intérieur du
contrôle la dimension de la zone masquée. - Nous pouvons rendre le contenu de la zone masquée visible, invisible ou transparent.
Nous n'avons utilisé qu'une seule forme pour le masque, mais comme pour n'importe quelle balise HTML à usage général, nous pouvons nicher autant d'éléments enfants que nous le souhaitons. En fait, l'astuce pour réaliser ce que nous voulons consulter deux éléments SVG
<svg viewbox="0 0 320 320" width="320" height="320"> <masque> <rect width="320" height="320" y="0" fill="???"> <rect width="264" height="264" y="56" fill="???"> mask> <rect width="320" height="320" y="0" fill="# 264653" mask="url (# maskw320)"> </rect></rect></rect></masque></svg>
L'un de nos rectangles de masquage est rempli de blanc; l'autre est rempli de noir. Même si nous connaissons les règles, essayons les possibilités.
<masque> <rect width="320" height="320" y="0" fill="noir"> <rect width="264" height="264" y="56" fill="white"> mask></rect></rect></masque>
Le
Maintenant, faisons tourner les choses où le rectangle noir est au-dessus:
<masque> <rect width="320" height="320" y="0" fill="white"> <rect width="264" height="264" y="56" fill="noir"> mask></rect></rect></masque>
C'est ce que nous voulons!
Tout dans le plus grand rectangle rempli de blanc est visible, mais le plus petit rectangle noir est au-dessus (plus près de nous sur l'axe Z), masquant cette partie.
Générer les masques
Maintenant que nous savons ce que nous devons faire, nous pouvons créer les masques avec une relative facilité. C'est similaire à la façon dont nous avons généré les rectangles colorés en premier lieu - nous créons une boucle secondaire où nous créons le masque et les deux rectes.
Cette fois, au lieu d'ajouter les rectes directement au SVG, nous l'ajoutons au masque:
data.ForEach ((d: dataSetEntry, index: numéro) => { const Mask: svgmaskElement = CreateSvGnSelement ('mask') comme svgmaskElement; const REctDimension: Number = remapDataSetValuetoSvgdimension (d.Value); const REct: svGrecedElement = créeSvGnSelement («rect») comme svGrecedElement; rect.setAttribute ('width', `$ {rectdimension}`); // ... définir le reste des attributs ... mask.setAttribute ('id', `maskw $ {rectdimension.tofixed ()}`); masque.ApendChild (RECT); // ... Création et définition des attributs pour le plus petit rectangle ... SVG.APPEndChild (masque); }); data.ForEach ((d: dataSetEntry, index: numéro) => { // ... notre code pour générer les rectangles colorés ... });
Nous pourrions utiliser l'index comme identifiant du masque, mais cela semble une option plus lisible, du moins pour moi:
mask.setAttribute ('id', `maskw $ {rectdimension.tofixed ()}`); // maskw320, masw240, ...
En ce qui concerne l'ajout du rectangle plus petit dans le masque, nous avons facilement accès à la valeur dont nous avons besoin car nous avons précédemment commandé les valeurs rectangulaires du plus haut au plus bas. Cela signifie que l'élément suivant de la boucle est le rectangle plus petit, celui que nous devons référencer. Et nous pouvons le faire par son index.
// ... partie précédente où nous avons créé le masque et le rectangle ... const smallErrectIndex = index 1; // il n'y a pas de prochain quand nous sommes sur le plus petit if (data [smallErrectIndex]! == Undefined) { const SmallErrectDimension: nombre = remapdatasetvaluetosvgdimension ( données [smallErrectIndex] .Value )); const smallErrect: svGrecedElement = CreateSVGNELlement ( 'rect' ) comme svGreceLelement; // ... définir les attributs du rectangle ... masque.APPEndChild (Small Earrect); } SVG.APPEndChild (masque);
Ce qui reste, c'est d'ajouter l'attribut de masque au rectangle coloré dans notre boucle d'origine. Il devrait correspondre au format que nous avons choisi:
rect.setAttribute ('mask', `url (# maskw $ {rectdimension.tofixed ()})`); // maskw320, maskw240, ...
Le résultat final
Et nous avons fini! Nous avons réussi à faire un graphique fabriqué à partir de carrés imbriqués. Il se sépare même de survoler de la souris. Et tout ce qu'il a fallu, c'était un SVG en utilisant l'élément
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

J'ai eu cette question l'autre jour. Ma première pensée est: une question étrange! La spécificité concerne les sélecteurs, et les rubriques ne sont pas des sélecteurs, donc ... non pertinents?

Oui, vous le pouvez, et cela n'a pas vraiment d'importance dans quel ordre. Un préprocesseur CSS n'est pas requis. Il fonctionne dans CSS ordinaire.

Vous devriez à coup sûr définir des en-têtes de cache éloignés sur vos actifs comme CSS et JavaScript (et des images et polices et quoi que ce soit d'autre). Cela dit au navigateur

De nombreux développeurs écrivent sur la façon de maintenir une base de code CSS, mais peu d'entre eux écrivent sur la façon dont ils mesurent la qualité de cette base de code. Bien sûr, nous avons

Avez-vous déjà eu un formulaire qui devait accepter un petit texte arbitraire? Comme un nom ou autre chose. C'est exactement à quoi sert. Il y a beaucoup de

Je suis tellement excité de me diriger vers Zurich, en Suisse pour la conférence de Front (j'adore ce nom et URL!). Je n'ai jamais été en Suisse auparavant, donc je suis excité

L'un de mes développements préférés dans le développement de logiciels a été l'avènement de Serverless. En tant que développeur qui a tendance à s'enliser dans les détails

Dans cet article, nous utiliserons une démo de magasin de commerce électronique que j'ai construit et déployé sur Netlify pour montrer comment nous pouvons faire des itinéraires dynamiques pour les données entrantes. C'est assez


Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Dreamweaver Mac
Outils de développement Web visuel

mPDF
mPDF est une bibliothèque PHP qui peut générer des fichiers PDF à partir de HTML encodé en UTF-8. L'auteur original, Ian Back, a écrit mPDF pour générer des fichiers PDF « à la volée » depuis son site Web et gérer différentes langues. Il est plus lent et produit des fichiers plus volumineux lors de l'utilisation de polices Unicode que les scripts originaux comme HTML2FPDF, mais prend en charge les styles CSS, etc. et présente de nombreuses améliorations. Prend en charge presque toutes les langues, y compris RTL (arabe et hébreu) et CJK (chinois, japonais et coréen). Prend en charge les éléments imbriqués au niveau du bloc (tels que P, DIV),

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Version Mac de WebStorm
Outils de développement JavaScript utiles

MinGW - GNU minimaliste pour Windows
Ce projet est en cours de migration vers osdn.net/projects/mingw, vous pouvez continuer à nous suivre là-bas. MinGW : un port Windows natif de GNU Compiler Collection (GCC), des bibliothèques d'importation et des fichiers d'en-tête librement distribuables pour la création d'applications Windows natives ; inclut des extensions du runtime MSVC pour prendre en charge la fonctionnalité C99. Tous les logiciels MinGW peuvent fonctionner sur les plates-formes Windows 64 bits.