Léon  Peltier

Léon Peltier

1657599240

Un Ensemble D'outils Unique Et Puissant : Les Filtres SVG

Les filtres sont extrêmement populaires en photographie. Vous pouvez les trouver sur presque toutes les applications ou sites Web de retouche photo, et certains appareils photo ont des options de filtre intégrées pour que vous n'ayez pas à éditer les photos plus tard.

CSS a plusieurs filtres qui aident à améliorer les aspects visuels d'un site Web. Vous pouvez les appliquer directement à un élément Web à l'aide de la filterpropriété, ainsi qu'à la zone derrière l'élément avec la backdrop-filterpropriété.

Avec ces filtres, vous pouvez flouter une image, régler le contraste et la saturation, modifier la teinte, réduire l'opacité, et bien plus encore !

Dans cet article, nous allons en savoir plus sur un ensemble d'outils unique et puissant : les filtres SVG. Mais avant de continuer, faisons une petite introduction aux SVG.

Que sont les SVG ?

Les SVG, ou Scalable Vector Graphics, sont un format d'image vectorielle basé sur XML pour afficher des graphiques en deux dimensions. XML est un autre acronyme sophistiqué qui signifie Extensible Markup Language. XML est utilisé pour stocker et transmettre des données, et définir vos balises.

Retour aux SVG. Un SVG sert à la fois de format d'image et de document. Les formats d'image standard tels que JPEG et PNG sont constitués de pixels qui perdent généralement en qualité lorsqu'ils sont agrandis.

Ce qui rend les SVG différents, c'est qu'ils conservent leur qualité, quel que soit l'ampleur du zoom. C'est possible parce qu'ils sont constitués de formules mathématiques.

Voyons ce qu'il y a sous le capot d'un SVG.

Commencez par ouvrir une image SVG dans un éditeur de code. Voici une capture d'écran de ce que vous pourriez trouver :

Capture d'écran de l'éditeur de code

 

Ce code constitue une forme complexe. Nous pouvons contrôler la couleur, la taille et d'autres caractéristiques de l'image dans les lignes de code. Créons une forme plus simple, un cercle :

<body>
  <svg width="400" height="400">
    <circle cx="200" cy="200" r="100" fill="#553c9a">
  </svg>
</body>

Et nous avons un cercle violet !

Cercle violet

Nous pouvons transformer ce cercle en anneau en ajoutant une strokevaleur. Un trait est la bordure et nous pouvons définir la fillcouleur sur transparent.

<body>
  <svg width="400" height="400">
    <circle cx="200" cy="200" r="100" fill="transparent"
    stroke="#553c9a" stroke-width="20px">
  </svg>
</body>

Le résultat est celui-ci :

Cercle violet avec milieu vierge

Des images complexes peuvent être créées en combinant différents SVG. Les SVG sont utilisés pour les icônes, les logos ou comme images d'arrière-plan. Ils peuvent aussi être animés !

Utiliser des filtres CSS avec des SVG

Les filtres CSS sont principalement limités aux images et sont assez faciles à utiliser. Les filtres SVG, en revanche, peuvent être appliqués aux images (à la fois SVG et autres formats), au texte et à tous les autres éléments HTML. Les filtres CSS sont en fait un sous-ensemble de filtres SVG.

Les filtres SVG fonctionnent avec l' <filter>élément et un ensemble de fonctions appelées primitives de filtre. Ces fonctions sont des éléments enfants qui créent des effets.

L' <filter>élément sera référencé par la filterpropriété CSS via un fichier id.

Filtrer les primitives

Pour commencer, créez un svgélément avec un filterélément imbriqué à l'intérieur. Ensuite, ajoutez les primitives avant l'image (ou tout autre élément auquel vous souhaitez appliquer le filtre).

Il y a 17 primitives de filtre, et ce sont :

  1. feGaussianBlur
  2. feDropShadow
  3. feMorphology
  4. feTurbulence
  5. feDisplacementMap
  6. feColorMatrix
  7. feConvolveMatrix
  8. feComponentTransfer
  9. feOffset
  10. feMerge
  11. feFlood
  12. feComposite
  13. feImage
  14. feBlend
  15. feDiffuseLighting
  16. feSpecularLighting
  17. feTile

"fe" signifie effet de filtre. D'après les noms, nous pouvons avoir une idée des effets qu'ils produiront. Examinons une syntaxe de filtre SVG de base :

<svg>
   <filter id="">
   <!--Filter Primitives go in here-->
   </filter>
</svg>

Chaque primitive SVG possède son propre ensemble unique d'attributs utilisés pour créer les effets. Certaines de ces primitives de filtrage fonctionnent bien par elles-mêmes, mais certaines doivent être combinées avec d'autres primitives.

Il y a beaucoup à couvrir, alors commençons.

feGaussianBlur

Les SVG sont basés sur des formules mathématiques, il est donc normal de faire avancer les choses avec un filtre de flou gaussien. Ce filtre porte le nom du regretté mathématicien Carl Friedrich Gauss et applique une fonction mathématique pour brouiller l'image.

Tout d'abord, vous aurez besoin d'une image. En voici un de freepik.com :

Fusée à image originale

Ensuite, nous allons créer la syntaxe SVG dans le fichier HTML :

<svg>
  <filter id="blur">
    <feGaussianBlur stdDeviation="5" in="SourceGraphic" result="BLUR"></feGaussianBlur>
  </filter>
    <image
       xlink:href="2833.jpg" filter="url(#blur)"></image>
</svg>

Maintenant, nous aurons la primitive de filtre SVG, feGaussianBlur, dans l' filterélément. Certains attributs à l'intérieur de la primitive auront un effet sur le flou produit.

Le premier attribut est stdDeviation, qui régule la quantité de flou.

Vient ensuite in, pour l'entrée, qui définit où le filtre sera appliqué. Dans ce cas, c'est le SourceGraphic, qui est notre image. Il SourceGraphicpeut également s'agir de texte.

Le dernier attribut de cet exemple est result. Nous l'utilisons pour nommer le filtre. Ceci est utile comme référence inlorsque vous travaillez avec plusieurs filtres.

Voici l'image résultante avec le filtre appliqué :

Image avec filtre de flou

Comme mentionné précédemment, les filtres SVG peuvent être appliqués en externe en utilisant la filterpropriété et un urlpointant vers un id:

<svg>
    <filter id="blur">
      <feGaussianBlur stdDeviation="5"></feGaussianBlur>
    </filter>
</svg>

Enfin, appliquez-le avec la filterpropriété CSS :

img{
  width: 1000px;
  height: auto;
  filter: url(#blur);
}

feDropShadow

Ce filtre est assez simple et ajoute une ombre portée derrière un élément.

Commencez par la syntaxe :

<svg >
  <filter id="blur">
    <feDropShadow in="SourceGraphic" dx="10" dy="10"></feDropShadow>
  </filter>
</svg>

Les attributs dxet dydéfinissent la position de l'ombre le long des axes x et y, respectivement. Le résultat est une ombre vraiment sombre derrière l'image :

Filtre FeDropShadow

feMorphology

La morphologie est l'étude de la forme, de la forme et de la structure. La feMorphologyprimitive est utilisée pour changer, ou transformer, la forme des éléments.

Il fonctionne avec l' operatorattribut qui accepte l'une des deux valeurs, dilateou erode, et a radiusqui définit la quantité de dilatation ou d'érosion. Pour dilate, les pixels du SourceGraphicsont étalés vers l'extérieur. erodefait le contraire.

Comparons les deux. Tout d'abord c'est dilate:

<svg>
  <filter id="blur">
   <feMorphology in="SourceGraphic" operator="dilate" radius="5">
   </feMorphology>    
  </filter>
</svg>

Le résultat:

Filtre FeMorphologie avec dilatation

Voyons maintenant erode:

<svg>
  <filter id="blur">
   <feMorphology in="SourceGraphic" operator="erode" radius="5">
   </feMorphology>    
  </filter>
</svg>

Le résultat:

Filtre FeMorphologie avec érosion

Où sont passées toutes les étoiles ?🤔

D'après ces résultats, nous pouvons voir que dilateproduit une image plus vibrante par rapport à l'image assombrie et atténuée de erode. La luminosité est due à l'expansion des pixels de l'image et vice versa.

feTurbulence

La seule véritable explication de l'effet de cette primitive de filtre est juste là dans son nom : la turbulence. Il utilise deux attributs : baseFrequencyet numOctaves.

<feTurbulence in="SourceGRaphic" baseFrequency="0.01 0.02" 
              numOctaves="1" result="NOISE">
</feTurbulence>

Le résultat est un effet de bruit sur l'image :

FeTurbulence Filter

Expliquons les attributs.

Le baseFrequencycontrôle la quantité de distorsion, ou de bruit, dans les directions x et y. Une baseFrequencyvaleur élevée réduit la taille du motif de distorsion. Il peut contenir deux valeurs, et si une seule valeur est utilisée, elle couvre à la fois les axes x et y.

Fréquence de base FeTurbulence

numOctavesest également une fonction de bruit et contrôle le nombre d'octaves dans l'effet de filtre. En utilisant un baseFrequencyde "0.01 0.02", nous obtenons ce qui suit :

FeTurbulence Nombre d'octaves

En fin de compte, c'est à vous de décider du nombre d'octaves et de la quantité de fréquence. Jouez avec les valeurs et voyez ce que vous proposez. Gardez à l'esprit qu'ils n'acceptent pas les valeurs négatives.

feDisplacementMap

Une carte de déplacement est une image utilisée pour modifier le contenu d'un autre élément. La texture d'un élément peut être appliquée à un autre.

Pour cette primitive de filtre SVG, nous aurons besoin de deux entrées : inet in2. L'un contiendra le graphique original et l'autre sera l'image servant de carte de déplacement.

<svg>
 <filter id="turbulence">
   <feTurbulence type="turbulence" baseFrequency="0.01 0.02" numOctaves="1" result="NOISE"></feTurbulence>
   <feDisplacementMap in="SourceGraphic" in2="NOISE" scale="50">
   </feDisplacementMap>
 </filter>
</svg>

Maintenant pour le résultat. L'image suit le motif de distorsion créé par le feTurbulencefiltre :

Distorsion FeTurbulence

Nous pouvons aller plus loin en ajoutant une animation ondulée pour compléter le look aqueux :

<svg>
  <filter id="wavy">
  <feTurbulence id="turbulence" type="turbulence" numOctaves="1" 
  result="NOISE"></feTurbulence>
   <feDisplacementMap in="SourceGraphic" in2="NOISE" scale="50">
   </feDisplacementMap>
  <animate xlink:href="#turbulence" attributeName="baseFrequency" dur="60s" keyTimes="0;0.5;1"
values="0.01 0.02;0.02 0.04;0.01 0.02" repeatCount="indefinite"></animate>
 </filter>
</svg>

Notez que la première primitive de filtre a maintenant un id. C'est ce que nous animons.

Ensuite, nous utiliserons l' <animate>élément pour définir l'animation. Cet élément contiendra xlink:href, pointant vers le filtre qui sera animé. Après c'est attributeName, et l'attribut primitif que nous animons est le baseFrequency.

Ensuite, nous fixons la durée avec duret le keyTimes. Ce sont essentiellement @keyframes.

valuescontiennent les nouvelles baseFrequencyvaleurs des points d'arrêt définis avec keyTimes.

Enfin, nous avons repeatCountréglé pour indefiniteque l'effet tourne en boucle.

Et voici le résultat :

 


Nous pouvons également utiliser les propriétés régulières animationet transitionCSS ou du JavaScript pour l'animation.

feColorMatrix

Ce filtre SVG permet de modifier la teinte et la saturation d'un élément. Il fonctionne avec un typeattribut et quatre valeurs possibles : matrix, saturate, hueRotateet luminaceToAlpha.

Pour matrix, l'effet de filtre est appliqué à l'aide d'une matrice de couleurs RVBA, ou grille, pour son value.

Matrice de couleurs Rgba

<svg>
<filter>
  <feColorMatrix in="SourceGraphic" type="matrix" 
                   values="1 0 0 0 0
                           0 1 0 0 0
                           0 0 1 0 0
                           0 0 0 1 0">
</filter>
</svg>

La syntaxe ci-dessus ne changera pas la couleur de l'image. Regardons chaque canal de couleur.

Canaux de couleur FeColorMatrix

Jouez avec les valeurs et voyez quelles teintes, nuances et teintes vous pouvez trouver !

Ensuite, nous avons saturate. Cela utilise valuesentre 0 et 1 pour contrôler la quantité de noir et blanc dans l'image.

<svg>
  <filter id="saturate">
      <feColorMatrix in="SourceGraphic" type="saturate" values="0.5"/>
    </filter>
</svg>

Le résultat:

FeColorMatrix

La prochaine étape est hueRotate. Cet attribut fait pivoter les couleurs de l'image autour de la roue chromatique selon un angle spécifique. Commençons par vous montrer la roue chromatique :

Palette de couleurs

Utilisons maintenant l'attribut :

<feColorMatrix in="SourceGraphic" type="hueRotate" values="60"/>

Le navigateur détecte toutes les couleurs de l'image et les fait pivoter de 60 degrés le long de la roue chromatique. Ce sera l'image résultante :

FeColorMatrix avec rotation des couleurs à soixante degrés

La finale typeest luminaceToAlpha. Cela transforme essentiellement l'image en un négatif translucide en supprimant le canal alpha.

FeColorMatrix Sans Alpha

Le matrixpeut obtenir les mêmes effets que les autres si on leur donne les bonnes valeurs pour la grille.

feConvolveMatrix

D'une matrice à l'autre ! Cette primitive de filtre ajoute un effet de convolution, ou noyau, à une image. Il est utilisé pour le flou, la détection des contours, la netteté, le gaufrage et le biseautage à l'aide d'une combinaison de pixels.

Nous pouvons démontrer un subtil effet de pépin en utilisant des valeurs aléatoires dans la grille :

<svg>
      <filter id="convolve">
        <feConvolveMatrix kernelMatrix
        ="1 -4 1 
          1 0 -8 
          1 0 -4" />
    </filter>
</svg>

Le résultat:

FeConvolveMatrix

Comparons avec l'original pour bien voir les effets :

Filtre FeConvolveMatrix et pas de comparaison de filtre

feComponentTransfer

Cette primitive est similaire à feColorMatrix, mais, à la place d'une grille, chaque canal de couleur (RGBA) est une fonction distincte. Et tout comme avec la matrice, nous pouvons ajuster le contraste de l'image en manipulant l'intensité de la couleur sur ces canaux.

Voici à quoi cela ressemble :

FeComponentTransfer Table

Et voici comment cela fonctionne en utilisant les valeurs données dans cet exemple :

Exemple de valeurs FeComponentTransfer

Dans le canal rouge, par exemple, l'intensité de la couleur varie de 0 à 1. Nous sommes partis avec quatre valeurs, donc 1 est divisé par 4. Nous avons maintenant quatre plages égales de rouge : 0–0,25, 0,25–0,5, 0,5 –0,75 et 0,75–1.

Toute valeur de rouge comprise entre 0 et 0,25 se voit attribuer la première valeur dans tableValueset ainsi de suite. Le même principe est utilisé jusqu'à 10 valeurs.

Il existe diverses fonctions qui peuvent être utilisées avec cette primitive de filtre, et la première que nous allons examiner est discrete. Cela réduit la quantité de couleur dans une image.

<svg>
      <filter id="discrete">
        <feComponentTransfer>
          <feFuncR type="discrete" tableValues="0 0.5 0 1"/>
          <feFuncG type="discrete" tableValues="0 0.5 0 1"/>
          <feFuncB type="discrete" tableValues="0 0.5 0 1"/>
          <feFuncA type="discrete" tableValues="0 0.5 0 1"/>
      </feComponentTransfer>
    </filter>
</svg>

Le résultat:

FeComponentTransfer Result

Le suivant typeest table, qui apporte des modifications plus subtiles au contraste de l'image. Donc, en utilisant la même chose tableValuesque ci-dessus…

<svg>
   <filter id="convolve">
      <feComponentTransfer>
          <feFuncR type="table" tableValues="0 0.5 0 1" />
          <feFuncG type="table" tableValues="0 0.5 0 1" />
          <feFuncB type="table" tableValues="0 0.5 0 1" />
          <feFuncA type="table" tableValues="0 0.5 0 1" />
      </feComponentTransfer>
   </filter>
</svg>

… nous obtenons ceci :

Résultat FeComponentTransfer avec les valeurs du tableau

Nous pouvons créer un effet de bichromie en utilisant cette primitive. Duo signifie deux, nous utilisons donc deux valeurs de couleur pour chaque canal dans tableValues.

Nous avons besoin de deux couleurs, allons-y avec #A91C93et #8EE3FF. Maintenant, nous avons besoin des valeurs de couleur RVB — #A91C93est équivalent à (169,28,147)et #8EE3FFest équivalent à (255,142,227).

Ensuite, nous devons diviser les valeurs des canaux rouge, vert et bleu par 255 pour obtenir une valeur comprise entre 0 et 1. Cela va dans tableValues.

<svg>
    <filter id="duotone">
       <feComponentTransfer>
          <feFuncR type="table" tableValues="0.662745098 1" />
          <feFuncG type="table" tableValues="0.109803922 0.556862745" />
          <feFuncB type="table" tableValues="0.576470588 0.890196078" />
       </feComponentTransfer>
    </filter>
</svg>

Et on obtient ceci :

FeComponentTransfer Result

Il existe une troisième façon de contrôler le contraste de l'image, et c'est le type, gamma. Cela vient avec trois autres attributs : exponent, amplitudeet offset.

L'augmentation de exponentrend les zones sombres de l'image encore plus sombres. C'est le contraire avec amplitude, éclaircissant les zones déjà claires de l'image.

offsetajoute une teinte blanche à l'image et ses valeurs sont comprises entre 0 et 1.

<svg>
  <filter id="amplify">
    <feComponentTransfer>
       <feFuncR type="gamma" exponent="1.9" amplitude="1.9" offset="0" />
       <feFuncG type="gamma" exponent="1.9" amplitude="1.9" offset="0" />
       <feFuncB type="gamma" exponent="1.9" amplitude="1.9" offset="0" />
    </feComponentTransfer>
   </filter>
</svg>

Comparons avec l'image d'origine :

Filtre FeComponentTransfer et aucun tableau de comparaison de filtre à partir de valeurs

Essayez d'autres valeurs pour trouver d'autres façons de pimenter un élément. Il y a tellement de possibilités à portée de main avec cette primitive de filtre SVG !

feOffset

Cette primitive est assez simple. Nous décalons l'image le long des directions x et y, comme nous l'avons fait avec l'ombre portée.

<svg>
    <filter id="convolve">
      <feOffset in="SourceGraphic" dx="10" dy="10"></feOffset>
    </filter>
</svg>

feMerge

Ce filtre SVG nous permet de superposer deux ou plusieurs éléments. Chaque couche fait partie de la primitive feMergeNodeprincipale .feMerge

C'est maintenant le moment idéal pour présenter le SourceAlpha, une copie noire du SourceGraphic. Donc, en utilisant notre image, le SourceAlphaest un rectangle noir avec les mêmes dimensions que l'image. Nous pouvons l'utiliser pour créer une meilleure ombre portée.

On commencera par décaler SourceAlpha:

<svg>
    <filter id="drop-shadow">
      <feOffset in="SourceAlpha" dx="10" dy="10"></feOffset>
    </filter>
</svg>

Ensuite, nous allons appliquer un flou et réduire l'opacité en utilisant feColorMatrix:

<svg>
    <filter id="drop-shadow">
      <feOffset in="SourceAlpha" dx="10" dy="10"></feOffset>
      <feGaussianBlur stdDeviation="10" result="BLUR"></feGaussianBlur>
      <feColorMatrix
          type="matrix"
          in="BLUR"
          result="DROPSHADOW"
          values="1 0 0 0 0
                  0 1 0 0 0
                  0 0 1 0 0
                  0 0 0 0.5 0"></feColorMatrix>
    </filter>
</svg>

À ce stade, nous avons un rectangle translucide flou :

FeMergeBlur Rectangle flou

Maintenant, nous allons superposer notre image au-dessus de cette ombre en utilisant feMerge. Le premier feMergeNodesera la couche supérieure et les autres suivront dans cet ordre.

<feMerge>
    <feMergeNode in="FINALSHADOW"></feMergeNode>
    <feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>

FeFusionnerFlou

Maintenant, nous avons une meilleure ombre portée en combinant quatre filtres SVG !

feFlood

Avec cette primitive de filtre, nous inondons simplement la zone de filtre de couleur.

<svg>
      <filter id="convolve">
        <feflood flood-color="#00c2cb" flood-opacity="0.1" />
      </filter>
</svg>

Le résultat:

FeFlood Blue Image

feComposite

Ce filtre combine une image avec son arrière-plan. Nous allons passer au texte pour démontrer l'effet de cette primitive de filtre.

Nous allons également travailler avec deux autres filtres SVG, feFloodet feMorphology, pour créer du texte knock-out.

Voici notre h1texte :

FeComposite Knockout Original

Et voici la syntaxe SVG :

<body>
  <svg>
    <filter id="knockout">
      <feMorphology operator="dilate" radius="2" in="sourceGraphic" 
      result="DILATE" />
      <feFlood flood-color="#301934" flood-opacity="0.5" result="FLOOD" />
        <feComposite operator="out" in="FLOOD" in2="DILATE" />
      </filter>
  </svg>
    <h1>HELLO! I'M A KNOCKOUT...</h1>
</body>

Voici le résultat :FeComposite Out

Tout d'abord, nous avons utilisé feMorphologyavec le operatoras dilatepour étendre le texte. Ensuite, nous avons inondé la zone de texte avec la couleur. Et enfin, nous avons utilisé feCompositepour mélanger le texte avec le fond blanc.

Nous avons utilisé outcomme valeur pour le composite operator. Pouvez-vous deviner ce qui se passe lorsque nous utilisons in?

Voyons voir:

FeComposite Knockout In

ça fait le contraire ! Cette fois, la couleur d'inondation reste dans les lettres du texte.

feImage

Cette primitive remplit la zone de filtre avec une image. C'est exactement ce que nous avons fait avec feFlood. Nous nous en tenons à l'exemple de texte, alors voyons comment fonctionne ce filtre SVG.

<feImage xlink:href="2833.jpg" x="0" y="0"
        width="100%" height="100%"
        preserveAspectRatio="none" result="IMAGE">
</feImage>

Pour l'instant, voici le résultat :

FeComposite

Maintenant, nous pouvons utiliser feCompositepour ajouter cette image au texte.

<svg>
  <filter id="knockout">
    <feImage xlink:href="2833.jpg" x="0" y="0"
       width="100%" height="100%"
       preserveAspectRatio="none" result="IMAGE"></feImage>
    <feComposite operator="in" in="IMAGE" in2="SourceGraphic" /> 
  </filter>
</svg>

FeComposite Knockout Final

feBlend

Comme son nom l'indique, cette primitive mélange l'image avec son arrière -plan . Pour le démontrer, nous allons créer un effet de bruit avec feTurbulenceet le combiner avec l'image.

<svg>
  <filter id="blend">
     <feTurbulence in="SourceGraphic" type="turbulence" 
     baseFrequency="0.01 0.02" numOctaves="1" result="NOISE">
     </feTurbulence>
    <feBlend in="SourceGraphic" in2="NOISE" mode="multiply" result="BLEND">     </feBlend>
  </filter>
</svg>

Le résultat est une image trouble :

FeBlend

Regardons une démo animée :

 

 

feDiffuseLighting

L'éclairage diffus est la lumière provenant d'une grande source extérieure. Il utilise le canal alpha de l'image comme carte en relief. Le bump mapping est une méthode graphique d'ajout de texture à une image.

Trois sources lumineuses fonctionnent avec cette primitive : feDistantLight, fePointLightet feSpotLight.

feDistantdéfinit une source de lumière qui vient d'une certaine distance.

<svg>
  <filter id="knockout">
     <feDiffuseLighting in="SourceGraphic" lighting-color="#00c2cb" 
     diffuseConstant="2">
      <feDistantLight azimuth="100" elevation="15" />
     </feDiffuseLighting>
     <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
  </filter>
</svg>

À partir de cet extrait, la source de lumière est bleue. diffuseConstantdéfinit la constante de réflexion de diffusion de la lumière, et c'est ainsi que la lumière se réfléchit sur la surface. Des valeurs inférieures atténueront la lumière.

Pour les feDistantLightattributs, azimuthest le sens horaire de la lumière sur le plan xy et elevationest la direction de l'angle sur l'axe z.

Voici l'effet résultant en utilisant le code ci-dessus :

FeÉclairage Diffus

Ensuite, fePointLight. Nous pointons essentiellement la lumière sur un point particulier de l'image. En regardant notre image, la lune semble être le meilleur endroit pour éclairer.

Pour obtenir cela, nous déplaçons la lumière le long des axes x, y et z.

<svg>
<filter id="point">
  <feDiffuseLighting in="SourceGraphic" lighting-color="#00c2cb" diffuseConstant="2">
     <fePointLight x="580" y="100" z="40"/>
  </feDiffuseLighting>
  <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
</filter>
</svg>

Maintenant, nous avons une belle lune bleue dans le ciel étoilé :

FeDiffuseLighting Moon Highlight

Enfin, pour ce filtre SVG, nous avons feSpotLight. C'est juste là dans le nom, il y a un projecteur invisible pointant un faisceau vers l'image. Quant à nous, nous pouvons contrôler la position, l'angle et l'intensité.

<svg>
<filter id="point">
 <feDiffuseLighting in="SourceGraphic" lighting-color="#00c2cb" 
 diffuseConstant="5">
    <feSpotLight x="680" y="20" z="30" 
              limitingConeAngle="60" 
              pointsAtX="100" pointsAtY="100"
              pointsAtZ="0" />
        </feDiffuseLighting>
  <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
</filter>
</svg>

Le limitingConeAnglecontrôle la largeur du projecteur. pointsAtX, pointsAtY, et pointsAtZcontrôlent la direction dans laquelle pointe le projecteur.

Le résultat:

FeDiffuseLighting Final

feSpecularLighting

La lumière spéculaire est utilisée pour la mise en évidence. Cette primitive de filtre utilise les mêmes sources lumineuses que feDiffuseLighting.

<svg>
<filter id="point">
<feSpecularLighting specularExponent="5" lighting-color="#00c2cb"
          surfaceScale="1" in="SourceGraphic" specularConstant="1.5">
          <fePointLight x="570" y="100" z="200" />
        </feSpecularLighting>
  <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
</filter>
</svg>

Regardons les attributs. specularExponentcontrôle la luminosité de la surbrillance et surfaceScalecorrespond à la hauteur de la surface de l'image. specularConstantfait la même chose que diffuseConstantet éclaircit ou atténue la couleur de la lumière.

Le résultat:

FeSpéculaireÉclairage

Nous avons utilisé fePointLight, mais essayez-le avec d'autres et voyez ce que vous pouvez trouver !

feTile

Nous sommes arrivés à la fin, le dernier filtre SVG qui est feTile. Cette primitive de filtre crée un motif répétitif sur un élément, tout comme les carreaux au sol.

<svg>
  <filter id="tiles">
     <feTile in="SourceGraphic" x="50" y="50" width="50" height="50" />
      <feTile />
  </filter>
</svg>

Dans cet extrait, nous sélectionnons la partie de l'image sur l'axe x et y qui sera affichée sur chaque tuile. Tout ce que nous avons à faire est de définir le widthet heightdes tuiles.

Et voila !

FeTile

Voilà, nous l'avons, les 17 primitives de filtre SVG. Qui a besoin de Photoshop lorsque vous pouvez éditer en déplacement ? Vous pouvez combiner de nombreuses primitives pour obtenir des effets plus complexes.

Prise en charge du navigateur

Les filtres SVG sont bien pris en charge par tous les navigateurs modernes. Voici une capture d'écran de caniuse montrant leur gamme de compatibilité.

Prise en charge du navigateur

Conclusion

Les SVG peuvent faire beaucoup de choses incroyables, et nous venons de voir comment améliorer les images, ainsi que d'autres éléments graphiques, avec des filtres SVG.

Nous avons également démontré les 17 primitives disponibles avec les filtres SVG. Distorsion, manipulation des couleurs, flou, inversion des couleurs - vous l'appelez, vous pouvez obtenir ces effets en quelques touches !

Maintenant, quelques éléments à retenir :

  • Soyez prudent avec le lettrage camel case
  • Les attributs sont sensibles à la casse, alors faites attention aux fautes d'orthographe
  • resultles valeurs doivent être entièrement en majuscules pour les distinguer des attributs primitifs

Allez de l'avant et créez un code magique, une ligne, un pixel à la fois !

 Source : https://blog.logrocket.com/complete-guide-using-css-filters-svgs/

#css 

What is GEEK

Buddha Community

Un Ensemble D'outils Unique Et Puissant : Les Filtres SVG
Léon  Peltier

Léon Peltier

1657599240

Un Ensemble D'outils Unique Et Puissant : Les Filtres SVG

Les filtres sont extrêmement populaires en photographie. Vous pouvez les trouver sur presque toutes les applications ou sites Web de retouche photo, et certains appareils photo ont des options de filtre intégrées pour que vous n'ayez pas à éditer les photos plus tard.

CSS a plusieurs filtres qui aident à améliorer les aspects visuels d'un site Web. Vous pouvez les appliquer directement à un élément Web à l'aide de la filterpropriété, ainsi qu'à la zone derrière l'élément avec la backdrop-filterpropriété.

Avec ces filtres, vous pouvez flouter une image, régler le contraste et la saturation, modifier la teinte, réduire l'opacité, et bien plus encore !

Dans cet article, nous allons en savoir plus sur un ensemble d'outils unique et puissant : les filtres SVG. Mais avant de continuer, faisons une petite introduction aux SVG.

Que sont les SVG ?

Les SVG, ou Scalable Vector Graphics, sont un format d'image vectorielle basé sur XML pour afficher des graphiques en deux dimensions. XML est un autre acronyme sophistiqué qui signifie Extensible Markup Language. XML est utilisé pour stocker et transmettre des données, et définir vos balises.

Retour aux SVG. Un SVG sert à la fois de format d'image et de document. Les formats d'image standard tels que JPEG et PNG sont constitués de pixels qui perdent généralement en qualité lorsqu'ils sont agrandis.

Ce qui rend les SVG différents, c'est qu'ils conservent leur qualité, quel que soit l'ampleur du zoom. C'est possible parce qu'ils sont constitués de formules mathématiques.

Voyons ce qu'il y a sous le capot d'un SVG.

Commencez par ouvrir une image SVG dans un éditeur de code. Voici une capture d'écran de ce que vous pourriez trouver :

Capture d'écran de l'éditeur de code

 

Ce code constitue une forme complexe. Nous pouvons contrôler la couleur, la taille et d'autres caractéristiques de l'image dans les lignes de code. Créons une forme plus simple, un cercle :

<body>
  <svg width="400" height="400">
    <circle cx="200" cy="200" r="100" fill="#553c9a">
  </svg>
</body>

Et nous avons un cercle violet !

Cercle violet

Nous pouvons transformer ce cercle en anneau en ajoutant une strokevaleur. Un trait est la bordure et nous pouvons définir la fillcouleur sur transparent.

<body>
  <svg width="400" height="400">
    <circle cx="200" cy="200" r="100" fill="transparent"
    stroke="#553c9a" stroke-width="20px">
  </svg>
</body>

Le résultat est celui-ci :

Cercle violet avec milieu vierge

Des images complexes peuvent être créées en combinant différents SVG. Les SVG sont utilisés pour les icônes, les logos ou comme images d'arrière-plan. Ils peuvent aussi être animés !

Utiliser des filtres CSS avec des SVG

Les filtres CSS sont principalement limités aux images et sont assez faciles à utiliser. Les filtres SVG, en revanche, peuvent être appliqués aux images (à la fois SVG et autres formats), au texte et à tous les autres éléments HTML. Les filtres CSS sont en fait un sous-ensemble de filtres SVG.

Les filtres SVG fonctionnent avec l' <filter>élément et un ensemble de fonctions appelées primitives de filtre. Ces fonctions sont des éléments enfants qui créent des effets.

L' <filter>élément sera référencé par la filterpropriété CSS via un fichier id.

Filtrer les primitives

Pour commencer, créez un svgélément avec un filterélément imbriqué à l'intérieur. Ensuite, ajoutez les primitives avant l'image (ou tout autre élément auquel vous souhaitez appliquer le filtre).

Il y a 17 primitives de filtre, et ce sont :

  1. feGaussianBlur
  2. feDropShadow
  3. feMorphology
  4. feTurbulence
  5. feDisplacementMap
  6. feColorMatrix
  7. feConvolveMatrix
  8. feComponentTransfer
  9. feOffset
  10. feMerge
  11. feFlood
  12. feComposite
  13. feImage
  14. feBlend
  15. feDiffuseLighting
  16. feSpecularLighting
  17. feTile

"fe" signifie effet de filtre. D'après les noms, nous pouvons avoir une idée des effets qu'ils produiront. Examinons une syntaxe de filtre SVG de base :

<svg>
   <filter id="">
   <!--Filter Primitives go in here-->
   </filter>
</svg>

Chaque primitive SVG possède son propre ensemble unique d'attributs utilisés pour créer les effets. Certaines de ces primitives de filtrage fonctionnent bien par elles-mêmes, mais certaines doivent être combinées avec d'autres primitives.

Il y a beaucoup à couvrir, alors commençons.

feGaussianBlur

Les SVG sont basés sur des formules mathématiques, il est donc normal de faire avancer les choses avec un filtre de flou gaussien. Ce filtre porte le nom du regretté mathématicien Carl Friedrich Gauss et applique une fonction mathématique pour brouiller l'image.

Tout d'abord, vous aurez besoin d'une image. En voici un de freepik.com :

Fusée à image originale

Ensuite, nous allons créer la syntaxe SVG dans le fichier HTML :

<svg>
  <filter id="blur">
    <feGaussianBlur stdDeviation="5" in="SourceGraphic" result="BLUR"></feGaussianBlur>
  </filter>
    <image
       xlink:href="2833.jpg" filter="url(#blur)"></image>
</svg>

Maintenant, nous aurons la primitive de filtre SVG, feGaussianBlur, dans l' filterélément. Certains attributs à l'intérieur de la primitive auront un effet sur le flou produit.

Le premier attribut est stdDeviation, qui régule la quantité de flou.

Vient ensuite in, pour l'entrée, qui définit où le filtre sera appliqué. Dans ce cas, c'est le SourceGraphic, qui est notre image. Il SourceGraphicpeut également s'agir de texte.

Le dernier attribut de cet exemple est result. Nous l'utilisons pour nommer le filtre. Ceci est utile comme référence inlorsque vous travaillez avec plusieurs filtres.

Voici l'image résultante avec le filtre appliqué :

Image avec filtre de flou

Comme mentionné précédemment, les filtres SVG peuvent être appliqués en externe en utilisant la filterpropriété et un urlpointant vers un id:

<svg>
    <filter id="blur">
      <feGaussianBlur stdDeviation="5"></feGaussianBlur>
    </filter>
</svg>

Enfin, appliquez-le avec la filterpropriété CSS :

img{
  width: 1000px;
  height: auto;
  filter: url(#blur);
}

feDropShadow

Ce filtre est assez simple et ajoute une ombre portée derrière un élément.

Commencez par la syntaxe :

<svg >
  <filter id="blur">
    <feDropShadow in="SourceGraphic" dx="10" dy="10"></feDropShadow>
  </filter>
</svg>

Les attributs dxet dydéfinissent la position de l'ombre le long des axes x et y, respectivement. Le résultat est une ombre vraiment sombre derrière l'image :

Filtre FeDropShadow

feMorphology

La morphologie est l'étude de la forme, de la forme et de la structure. La feMorphologyprimitive est utilisée pour changer, ou transformer, la forme des éléments.

Il fonctionne avec l' operatorattribut qui accepte l'une des deux valeurs, dilateou erode, et a radiusqui définit la quantité de dilatation ou d'érosion. Pour dilate, les pixels du SourceGraphicsont étalés vers l'extérieur. erodefait le contraire.

Comparons les deux. Tout d'abord c'est dilate:

<svg>
  <filter id="blur">
   <feMorphology in="SourceGraphic" operator="dilate" radius="5">
   </feMorphology>    
  </filter>
</svg>

Le résultat:

Filtre FeMorphologie avec dilatation

Voyons maintenant erode:

<svg>
  <filter id="blur">
   <feMorphology in="SourceGraphic" operator="erode" radius="5">
   </feMorphology>    
  </filter>
</svg>

Le résultat:

Filtre FeMorphologie avec érosion

Où sont passées toutes les étoiles ?🤔

D'après ces résultats, nous pouvons voir que dilateproduit une image plus vibrante par rapport à l'image assombrie et atténuée de erode. La luminosité est due à l'expansion des pixels de l'image et vice versa.

feTurbulence

La seule véritable explication de l'effet de cette primitive de filtre est juste là dans son nom : la turbulence. Il utilise deux attributs : baseFrequencyet numOctaves.

<feTurbulence in="SourceGRaphic" baseFrequency="0.01 0.02" 
              numOctaves="1" result="NOISE">
</feTurbulence>

Le résultat est un effet de bruit sur l'image :

FeTurbulence Filter

Expliquons les attributs.

Le baseFrequencycontrôle la quantité de distorsion, ou de bruit, dans les directions x et y. Une baseFrequencyvaleur élevée réduit la taille du motif de distorsion. Il peut contenir deux valeurs, et si une seule valeur est utilisée, elle couvre à la fois les axes x et y.

Fréquence de base FeTurbulence

numOctavesest également une fonction de bruit et contrôle le nombre d'octaves dans l'effet de filtre. En utilisant un baseFrequencyde "0.01 0.02", nous obtenons ce qui suit :

FeTurbulence Nombre d'octaves

En fin de compte, c'est à vous de décider du nombre d'octaves et de la quantité de fréquence. Jouez avec les valeurs et voyez ce que vous proposez. Gardez à l'esprit qu'ils n'acceptent pas les valeurs négatives.

feDisplacementMap

Une carte de déplacement est une image utilisée pour modifier le contenu d'un autre élément. La texture d'un élément peut être appliquée à un autre.

Pour cette primitive de filtre SVG, nous aurons besoin de deux entrées : inet in2. L'un contiendra le graphique original et l'autre sera l'image servant de carte de déplacement.

<svg>
 <filter id="turbulence">
   <feTurbulence type="turbulence" baseFrequency="0.01 0.02" numOctaves="1" result="NOISE"></feTurbulence>
   <feDisplacementMap in="SourceGraphic" in2="NOISE" scale="50">
   </feDisplacementMap>
 </filter>
</svg>

Maintenant pour le résultat. L'image suit le motif de distorsion créé par le feTurbulencefiltre :

Distorsion FeTurbulence

Nous pouvons aller plus loin en ajoutant une animation ondulée pour compléter le look aqueux :

<svg>
  <filter id="wavy">
  <feTurbulence id="turbulence" type="turbulence" numOctaves="1" 
  result="NOISE"></feTurbulence>
   <feDisplacementMap in="SourceGraphic" in2="NOISE" scale="50">
   </feDisplacementMap>
  <animate xlink:href="#turbulence" attributeName="baseFrequency" dur="60s" keyTimes="0;0.5;1"
values="0.01 0.02;0.02 0.04;0.01 0.02" repeatCount="indefinite"></animate>
 </filter>
</svg>

Notez que la première primitive de filtre a maintenant un id. C'est ce que nous animons.

Ensuite, nous utiliserons l' <animate>élément pour définir l'animation. Cet élément contiendra xlink:href, pointant vers le filtre qui sera animé. Après c'est attributeName, et l'attribut primitif que nous animons est le baseFrequency.

Ensuite, nous fixons la durée avec duret le keyTimes. Ce sont essentiellement @keyframes.

valuescontiennent les nouvelles baseFrequencyvaleurs des points d'arrêt définis avec keyTimes.

Enfin, nous avons repeatCountréglé pour indefiniteque l'effet tourne en boucle.

Et voici le résultat :

 


Nous pouvons également utiliser les propriétés régulières animationet transitionCSS ou du JavaScript pour l'animation.

feColorMatrix

Ce filtre SVG permet de modifier la teinte et la saturation d'un élément. Il fonctionne avec un typeattribut et quatre valeurs possibles : matrix, saturate, hueRotateet luminaceToAlpha.

Pour matrix, l'effet de filtre est appliqué à l'aide d'une matrice de couleurs RVBA, ou grille, pour son value.

Matrice de couleurs Rgba

<svg>
<filter>
  <feColorMatrix in="SourceGraphic" type="matrix" 
                   values="1 0 0 0 0
                           0 1 0 0 0
                           0 0 1 0 0
                           0 0 0 1 0">
</filter>
</svg>

La syntaxe ci-dessus ne changera pas la couleur de l'image. Regardons chaque canal de couleur.

Canaux de couleur FeColorMatrix

Jouez avec les valeurs et voyez quelles teintes, nuances et teintes vous pouvez trouver !

Ensuite, nous avons saturate. Cela utilise valuesentre 0 et 1 pour contrôler la quantité de noir et blanc dans l'image.

<svg>
  <filter id="saturate">
      <feColorMatrix in="SourceGraphic" type="saturate" values="0.5"/>
    </filter>
</svg>

Le résultat:

FeColorMatrix

La prochaine étape est hueRotate. Cet attribut fait pivoter les couleurs de l'image autour de la roue chromatique selon un angle spécifique. Commençons par vous montrer la roue chromatique :

Palette de couleurs

Utilisons maintenant l'attribut :

<feColorMatrix in="SourceGraphic" type="hueRotate" values="60"/>

Le navigateur détecte toutes les couleurs de l'image et les fait pivoter de 60 degrés le long de la roue chromatique. Ce sera l'image résultante :

FeColorMatrix avec rotation des couleurs à soixante degrés

La finale typeest luminaceToAlpha. Cela transforme essentiellement l'image en un négatif translucide en supprimant le canal alpha.

FeColorMatrix Sans Alpha

Le matrixpeut obtenir les mêmes effets que les autres si on leur donne les bonnes valeurs pour la grille.

feConvolveMatrix

D'une matrice à l'autre ! Cette primitive de filtre ajoute un effet de convolution, ou noyau, à une image. Il est utilisé pour le flou, la détection des contours, la netteté, le gaufrage et le biseautage à l'aide d'une combinaison de pixels.

Nous pouvons démontrer un subtil effet de pépin en utilisant des valeurs aléatoires dans la grille :

<svg>
      <filter id="convolve">
        <feConvolveMatrix kernelMatrix
        ="1 -4 1 
          1 0 -8 
          1 0 -4" />
    </filter>
</svg>

Le résultat:

FeConvolveMatrix

Comparons avec l'original pour bien voir les effets :

Filtre FeConvolveMatrix et pas de comparaison de filtre

feComponentTransfer

Cette primitive est similaire à feColorMatrix, mais, à la place d'une grille, chaque canal de couleur (RGBA) est une fonction distincte. Et tout comme avec la matrice, nous pouvons ajuster le contraste de l'image en manipulant l'intensité de la couleur sur ces canaux.

Voici à quoi cela ressemble :

FeComponentTransfer Table

Et voici comment cela fonctionne en utilisant les valeurs données dans cet exemple :

Exemple de valeurs FeComponentTransfer

Dans le canal rouge, par exemple, l'intensité de la couleur varie de 0 à 1. Nous sommes partis avec quatre valeurs, donc 1 est divisé par 4. Nous avons maintenant quatre plages égales de rouge : 0–0,25, 0,25–0,5, 0,5 –0,75 et 0,75–1.

Toute valeur de rouge comprise entre 0 et 0,25 se voit attribuer la première valeur dans tableValueset ainsi de suite. Le même principe est utilisé jusqu'à 10 valeurs.

Il existe diverses fonctions qui peuvent être utilisées avec cette primitive de filtre, et la première que nous allons examiner est discrete. Cela réduit la quantité de couleur dans une image.

<svg>
      <filter id="discrete">
        <feComponentTransfer>
          <feFuncR type="discrete" tableValues="0 0.5 0 1"/>
          <feFuncG type="discrete" tableValues="0 0.5 0 1"/>
          <feFuncB type="discrete" tableValues="0 0.5 0 1"/>
          <feFuncA type="discrete" tableValues="0 0.5 0 1"/>
      </feComponentTransfer>
    </filter>
</svg>

Le résultat:

FeComponentTransfer Result

Le suivant typeest table, qui apporte des modifications plus subtiles au contraste de l'image. Donc, en utilisant la même chose tableValuesque ci-dessus…

<svg>
   <filter id="convolve">
      <feComponentTransfer>
          <feFuncR type="table" tableValues="0 0.5 0 1" />
          <feFuncG type="table" tableValues="0 0.5 0 1" />
          <feFuncB type="table" tableValues="0 0.5 0 1" />
          <feFuncA type="table" tableValues="0 0.5 0 1" />
      </feComponentTransfer>
   </filter>
</svg>

… nous obtenons ceci :

Résultat FeComponentTransfer avec les valeurs du tableau

Nous pouvons créer un effet de bichromie en utilisant cette primitive. Duo signifie deux, nous utilisons donc deux valeurs de couleur pour chaque canal dans tableValues.

Nous avons besoin de deux couleurs, allons-y avec #A91C93et #8EE3FF. Maintenant, nous avons besoin des valeurs de couleur RVB — #A91C93est équivalent à (169,28,147)et #8EE3FFest équivalent à (255,142,227).

Ensuite, nous devons diviser les valeurs des canaux rouge, vert et bleu par 255 pour obtenir une valeur comprise entre 0 et 1. Cela va dans tableValues.

<svg>
    <filter id="duotone">
       <feComponentTransfer>
          <feFuncR type="table" tableValues="0.662745098 1" />
          <feFuncG type="table" tableValues="0.109803922 0.556862745" />
          <feFuncB type="table" tableValues="0.576470588 0.890196078" />
       </feComponentTransfer>
    </filter>
</svg>

Et on obtient ceci :

FeComponentTransfer Result

Il existe une troisième façon de contrôler le contraste de l'image, et c'est le type, gamma. Cela vient avec trois autres attributs : exponent, amplitudeet offset.

L'augmentation de exponentrend les zones sombres de l'image encore plus sombres. C'est le contraire avec amplitude, éclaircissant les zones déjà claires de l'image.

offsetajoute une teinte blanche à l'image et ses valeurs sont comprises entre 0 et 1.

<svg>
  <filter id="amplify">
    <feComponentTransfer>
       <feFuncR type="gamma" exponent="1.9" amplitude="1.9" offset="0" />
       <feFuncG type="gamma" exponent="1.9" amplitude="1.9" offset="0" />
       <feFuncB type="gamma" exponent="1.9" amplitude="1.9" offset="0" />
    </feComponentTransfer>
   </filter>
</svg>

Comparons avec l'image d'origine :

Filtre FeComponentTransfer et aucun tableau de comparaison de filtre à partir de valeurs

Essayez d'autres valeurs pour trouver d'autres façons de pimenter un élément. Il y a tellement de possibilités à portée de main avec cette primitive de filtre SVG !

feOffset

Cette primitive est assez simple. Nous décalons l'image le long des directions x et y, comme nous l'avons fait avec l'ombre portée.

<svg>
    <filter id="convolve">
      <feOffset in="SourceGraphic" dx="10" dy="10"></feOffset>
    </filter>
</svg>

feMerge

Ce filtre SVG nous permet de superposer deux ou plusieurs éléments. Chaque couche fait partie de la primitive feMergeNodeprincipale .feMerge

C'est maintenant le moment idéal pour présenter le SourceAlpha, une copie noire du SourceGraphic. Donc, en utilisant notre image, le SourceAlphaest un rectangle noir avec les mêmes dimensions que l'image. Nous pouvons l'utiliser pour créer une meilleure ombre portée.

On commencera par décaler SourceAlpha:

<svg>
    <filter id="drop-shadow">
      <feOffset in="SourceAlpha" dx="10" dy="10"></feOffset>
    </filter>
</svg>

Ensuite, nous allons appliquer un flou et réduire l'opacité en utilisant feColorMatrix:

<svg>
    <filter id="drop-shadow">
      <feOffset in="SourceAlpha" dx="10" dy="10"></feOffset>
      <feGaussianBlur stdDeviation="10" result="BLUR"></feGaussianBlur>
      <feColorMatrix
          type="matrix"
          in="BLUR"
          result="DROPSHADOW"
          values="1 0 0 0 0
                  0 1 0 0 0
                  0 0 1 0 0
                  0 0 0 0.5 0"></feColorMatrix>
    </filter>
</svg>

À ce stade, nous avons un rectangle translucide flou :

FeMergeBlur Rectangle flou

Maintenant, nous allons superposer notre image au-dessus de cette ombre en utilisant feMerge. Le premier feMergeNodesera la couche supérieure et les autres suivront dans cet ordre.

<feMerge>
    <feMergeNode in="FINALSHADOW"></feMergeNode>
    <feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>

FeFusionnerFlou

Maintenant, nous avons une meilleure ombre portée en combinant quatre filtres SVG !

feFlood

Avec cette primitive de filtre, nous inondons simplement la zone de filtre de couleur.

<svg>
      <filter id="convolve">
        <feflood flood-color="#00c2cb" flood-opacity="0.1" />
      </filter>
</svg>

Le résultat:

FeFlood Blue Image

feComposite

Ce filtre combine une image avec son arrière-plan. Nous allons passer au texte pour démontrer l'effet de cette primitive de filtre.

Nous allons également travailler avec deux autres filtres SVG, feFloodet feMorphology, pour créer du texte knock-out.

Voici notre h1texte :

FeComposite Knockout Original

Et voici la syntaxe SVG :

<body>
  <svg>
    <filter id="knockout">
      <feMorphology operator="dilate" radius="2" in="sourceGraphic" 
      result="DILATE" />
      <feFlood flood-color="#301934" flood-opacity="0.5" result="FLOOD" />
        <feComposite operator="out" in="FLOOD" in2="DILATE" />
      </filter>
  </svg>
    <h1>HELLO! I'M A KNOCKOUT...</h1>
</body>

Voici le résultat :FeComposite Out

Tout d'abord, nous avons utilisé feMorphologyavec le operatoras dilatepour étendre le texte. Ensuite, nous avons inondé la zone de texte avec la couleur. Et enfin, nous avons utilisé feCompositepour mélanger le texte avec le fond blanc.

Nous avons utilisé outcomme valeur pour le composite operator. Pouvez-vous deviner ce qui se passe lorsque nous utilisons in?

Voyons voir:

FeComposite Knockout In

ça fait le contraire ! Cette fois, la couleur d'inondation reste dans les lettres du texte.

feImage

Cette primitive remplit la zone de filtre avec une image. C'est exactement ce que nous avons fait avec feFlood. Nous nous en tenons à l'exemple de texte, alors voyons comment fonctionne ce filtre SVG.

<feImage xlink:href="2833.jpg" x="0" y="0"
        width="100%" height="100%"
        preserveAspectRatio="none" result="IMAGE">
</feImage>

Pour l'instant, voici le résultat :

FeComposite

Maintenant, nous pouvons utiliser feCompositepour ajouter cette image au texte.

<svg>
  <filter id="knockout">
    <feImage xlink:href="2833.jpg" x="0" y="0"
       width="100%" height="100%"
       preserveAspectRatio="none" result="IMAGE"></feImage>
    <feComposite operator="in" in="IMAGE" in2="SourceGraphic" /> 
  </filter>
</svg>

FeComposite Knockout Final

feBlend

Comme son nom l'indique, cette primitive mélange l'image avec son arrière -plan . Pour le démontrer, nous allons créer un effet de bruit avec feTurbulenceet le combiner avec l'image.

<svg>
  <filter id="blend">
     <feTurbulence in="SourceGraphic" type="turbulence" 
     baseFrequency="0.01 0.02" numOctaves="1" result="NOISE">
     </feTurbulence>
    <feBlend in="SourceGraphic" in2="NOISE" mode="multiply" result="BLEND">     </feBlend>
  </filter>
</svg>

Le résultat est une image trouble :

FeBlend

Regardons une démo animée :

 

 

feDiffuseLighting

L'éclairage diffus est la lumière provenant d'une grande source extérieure. Il utilise le canal alpha de l'image comme carte en relief. Le bump mapping est une méthode graphique d'ajout de texture à une image.

Trois sources lumineuses fonctionnent avec cette primitive : feDistantLight, fePointLightet feSpotLight.

feDistantdéfinit une source de lumière qui vient d'une certaine distance.

<svg>
  <filter id="knockout">
     <feDiffuseLighting in="SourceGraphic" lighting-color="#00c2cb" 
     diffuseConstant="2">
      <feDistantLight azimuth="100" elevation="15" />
     </feDiffuseLighting>
     <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
  </filter>
</svg>

À partir de cet extrait, la source de lumière est bleue. diffuseConstantdéfinit la constante de réflexion de diffusion de la lumière, et c'est ainsi que la lumière se réfléchit sur la surface. Des valeurs inférieures atténueront la lumière.

Pour les feDistantLightattributs, azimuthest le sens horaire de la lumière sur le plan xy et elevationest la direction de l'angle sur l'axe z.

Voici l'effet résultant en utilisant le code ci-dessus :

FeÉclairage Diffus

Ensuite, fePointLight. Nous pointons essentiellement la lumière sur un point particulier de l'image. En regardant notre image, la lune semble être le meilleur endroit pour éclairer.

Pour obtenir cela, nous déplaçons la lumière le long des axes x, y et z.

<svg>
<filter id="point">
  <feDiffuseLighting in="SourceGraphic" lighting-color="#00c2cb" diffuseConstant="2">
     <fePointLight x="580" y="100" z="40"/>
  </feDiffuseLighting>
  <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
</filter>
</svg>

Maintenant, nous avons une belle lune bleue dans le ciel étoilé :

FeDiffuseLighting Moon Highlight

Enfin, pour ce filtre SVG, nous avons feSpotLight. C'est juste là dans le nom, il y a un projecteur invisible pointant un faisceau vers l'image. Quant à nous, nous pouvons contrôler la position, l'angle et l'intensité.

<svg>
<filter id="point">
 <feDiffuseLighting in="SourceGraphic" lighting-color="#00c2cb" 
 diffuseConstant="5">
    <feSpotLight x="680" y="20" z="30" 
              limitingConeAngle="60" 
              pointsAtX="100" pointsAtY="100"
              pointsAtZ="0" />
        </feDiffuseLighting>
  <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
</filter>
</svg>

Le limitingConeAnglecontrôle la largeur du projecteur. pointsAtX, pointsAtY, et pointsAtZcontrôlent la direction dans laquelle pointe le projecteur.

Le résultat:

FeDiffuseLighting Final

feSpecularLighting

La lumière spéculaire est utilisée pour la mise en évidence. Cette primitive de filtre utilise les mêmes sources lumineuses que feDiffuseLighting.

<svg>
<filter id="point">
<feSpecularLighting specularExponent="5" lighting-color="#00c2cb"
          surfaceScale="1" in="SourceGraphic" specularConstant="1.5">
          <fePointLight x="570" y="100" z="200" />
        </feSpecularLighting>
  <feComposite in="SourceGraphic" operator="arithmetic" k1="1" k2="0"
          k3="0" k4="0" />
</filter>
</svg>

Regardons les attributs. specularExponentcontrôle la luminosité de la surbrillance et surfaceScalecorrespond à la hauteur de la surface de l'image. specularConstantfait la même chose que diffuseConstantet éclaircit ou atténue la couleur de la lumière.

Le résultat:

FeSpéculaireÉclairage

Nous avons utilisé fePointLight, mais essayez-le avec d'autres et voyez ce que vous pouvez trouver !

feTile

Nous sommes arrivés à la fin, le dernier filtre SVG qui est feTile. Cette primitive de filtre crée un motif répétitif sur un élément, tout comme les carreaux au sol.

<svg>
  <filter id="tiles">
     <feTile in="SourceGraphic" x="50" y="50" width="50" height="50" />
      <feTile />
  </filter>
</svg>

Dans cet extrait, nous sélectionnons la partie de l'image sur l'axe x et y qui sera affichée sur chaque tuile. Tout ce que nous avons à faire est de définir le widthet heightdes tuiles.

Et voila !

FeTile

Voilà, nous l'avons, les 17 primitives de filtre SVG. Qui a besoin de Photoshop lorsque vous pouvez éditer en déplacement ? Vous pouvez combiner de nombreuses primitives pour obtenir des effets plus complexes.

Prise en charge du navigateur

Les filtres SVG sont bien pris en charge par tous les navigateurs modernes. Voici une capture d'écran de caniuse montrant leur gamme de compatibilité.

Prise en charge du navigateur

Conclusion

Les SVG peuvent faire beaucoup de choses incroyables, et nous venons de voir comment améliorer les images, ainsi que d'autres éléments graphiques, avec des filtres SVG.

Nous avons également démontré les 17 primitives disponibles avec les filtres SVG. Distorsion, manipulation des couleurs, flou, inversion des couleurs - vous l'appelez, vous pouvez obtenir ces effets en quelques touches !

Maintenant, quelques éléments à retenir :

  • Soyez prudent avec le lettrage camel case
  • Les attributs sont sensibles à la casse, alors faites attention aux fautes d'orthographe
  • resultles valeurs doivent être entièrement en majuscules pour les distinguer des attributs primitifs

Allez de l'avant et créez un code magique, une ligne, un pixel à la fois !

 Source : https://blog.logrocket.com/complete-guide-using-css-filters-svgs/

#css 

Diego  Elizondo

Diego Elizondo

1652926080

Cómo Construir Un Analizador En Rust Por Diversión Y Ganancias

Un viernes por la mañana, holgazaneando, estás pensando en los nuevos programas de Netflix para ver. Su jefe viene y le pide que escriba un analizador para un archivo de unidad de Systemd .

Lo necesita para el lunes.

Cada vez que pensabas que el fin de semana estaba disponible

Estás nervioso.

La última vez que se le pidió que escribiera un analizador, se metió en la madriguera del conejo de la web, copiando y pegando fórmulas Regex hasta que funcionó™.

Básicamente lo que todos los desarrolladores habían hecho (sangre en la mano)

Tomas un sorbo de tu té de boba para calmarte. Buscas Systemd en Google y te gusta... no, no es tan simple como pensabas.

Ese sentimiento cuando estás tan desesperado porque te quitan el fin de semana

Tu buen truco de copiar y pegar expresiones regulares sale volando por la ventana. Las posibilidades de pasar un fin de semana sin interrupciones para atracones de programas se acercan rápidamente null.

#PEG al rescate

No pierdas la esperanza todavía. Permítame presentarle Parse Expression Grammer (PEG) , una manera fácil de familiarizarse con los analizadores y ahorrar su valioso fin de semana.

PEG es una forma legible de escribir reglas de sintaxis y es bastante similar a las expresiones regulares, que es diferente de una contraparte de gramática libre de contexto como Backus-Naur Form (BNF) en la que las expresiones deben reducirse a símbolos más pequeños. Lo siento, Noam Chomsky , quizás otros días de trabajo.

Usaré una biblioteca de análisis de Rust PEG llamada Pest , que es bastante impresionante. Si aún no lo has hecho, esperaré mientras instalas Rust .

En serio, ¿quién no se oxida en estos días?

#Empezando

Comencemos con una gramática simple para analizar una declaración de declaración de variable similar a JavaScript. Comenzaremos pensando en un conjunto de reglas para entradas válidas.

#Una declaración de declaración:

  • comienza con una palabra clave var, seguida de uno o más identificadores.
  • es insensible al espacio en blanco
  • termina con un punto y coma ( ;)

#Un grupo de identificadores:

  • está precedido por una varpalabra clave
  • está delimitado por comas
  • es insensible al espacio en blanco

#Un identificador:

  • puede contener cualquier número de dígitos, caracteres y guiones bajos en mayúsculas y minúsculas
  • no puede comenzar con un dígito
  • no puede contener ningún espacio

Un identificador es un término , lo que significa que es una pieza irrompible del token. También lo son las varpalabras clave y los puntos y comas.

Regresa un poco al lado BNF, usando Extended Backus-Naur Grammar (EBNF) , podrías definir formalmente la gramática anterior de esta manera:

<alpha>  := 'a' | 'b' | 'c' | 'd' | 'e' | /* ... */ 'z'
         |  'A' | 'B' | 'C' | 'D' | 'E' | /* ... */ 'Z'

<digit>  := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

<Decl>   := 'var' <Idents> '\n'? ';'
<Idents> := <Ident> ('\n'? ',' <Ident>)*
<Ident>  := <alpha>+ (<alpha> | <digit> | '_')*

El nombre de la regla en mayúsculas representa un símbolo que no termina (es decir, se puede dividir en términos más pequeños). El nombre en minúscula representa un término.

En aras de la brevedad, omitimos los espacios en blanco implícitos de las reglas. Básicamente, pueden existir uno o más espacios en blanco entre cada símbolo que ve.

¡Vamos a profundizar en ello! Las reglas <alpha>y <digit>se explican por sí mismas, por lo que dejaremos que lo adivines.

<Decl>es la regla más compleja para una instrucción de declaración, que presenta una varpalabra clave, un <Idents>símbolo, una nueva línea opcional y termina con un punto y coma. Básicamente, esta regla dice: "Cualquier entrada de cadena que comience con var, seguida de uno o más espacios, luego una subregla <Idents>, seguida de uno o más espacios y finalmente termine con un solo punto y coma es válida y felizmente la masticaré. "

<Idents>puede ser un solo <Ident>símbolo, seguido de cero o más pares de comas y <Ident>.

Finalmente, un <Ident>debe comenzar con uno o más caracteres, seguido de cero o más caracteres, dígitos o guiones bajos.

#Ok, código por favor

¡Espera, joven Anakin! Cabeza caliente, eres. He aquí que, con la gramática definida, podremos analizar estas declaraciones:

var foo, bar, baz;

var   foo_1, baRamYu,baz99;

var foo_x
  , baroo
  , bazoo
  ;

No, no me olvidé de formatear mi código. ¡Es JS válido, y también es para nuestro analizador! Aquí hay algo que nuestras reglas no soportarán:

var 99Problems

¿Alguien quiere adivinar qué está mal aquí? ✋ Deja tu respuesta en el comentario. (psss, si tu respuesta es correcta, te sigo + 3 me gusta en tu publicación 👍)

#Entra el óxido y las plagas

Ok, espero que ya tengas Rust instalado (En tu terminal, intenta escribir which cargoy ver si aparece). Comience creando un nuevo proyecto binario de Rust con

$ cargo new --bin maybe-js; cd maybe-js

Dentro de la carpeta del proyecto, abra el Cargo.tomlarchivo y agregue lo siguiente en dependencies, y ejecútelo cargo updatepara instalarlo.

[dependencies]
pest = "2.0"
pest_derive = "2.0"

Una vez hecho esto, cdingrese srcy cree un archivo llamado grammar.pesty pegue lo siguiente en él:

alpha = { 'a'..'z' | 'A'..'Z' }
digit = { '0'..'9' }
underscore = { "_" }
newline = _{ "\n" | "\r" }
WHITESPACE = _{ " " }

declaration = { "var" ~ !newline ~ idents ~ newline? ~ ";" }
idents = { ident ~ (newline? ~ "," ~ ident)* }
ident = @{ !digit ~ (alpha | digit | underscore)+ }

Ahora bien, si he tenido su atención durante los últimos minutos, no debería ser difícil adivinar lo que está sucediendo aquí. (Oh, ¿no lo he hecho? De todos modos... aquí vamos)

Los cinco primeros son todos términos. Son conjuntos de valores válidos. el | se llama Choice Operator , que es como "o-si no".

first | or_else

Al hacer coincidir una expresión de elección, firstse intenta. Si first coincide con éxito, la expresión completa se realiza correctamente de inmediato. Sin embargo, si firstfalla, or_elsese intenta a continuación.

La newlineregla tiene un peculiar _antes del corchete, que en Pest habla significa "silencioso": simplemente no lo queremos como parte de nuestros tokens analizados, pero de todos modos es parte de una sintaxis válida.

La WHITESPACEregla tiene un lugar especial en Pest. Si lo definió, Pest insertará automáticamente espacios en blanco opcionales implícitos (de acuerdo con la WHITESPACEregla que defina) entre cada símbolo. Nuevamente, _dice que queremos silenciarlo, ya que no queremos toneladas de espacios en blanco como parte de nuestro árbol de sintaxis.

La declarationregla es muy similar a la contraparte de EBNF que aprendimos antes. Las tildes ("~") simplemente significan "y luego". La regla comienza con una palabra clave "var", seguida de cualquier cosa que no sea un salto de línea (el "!" hace lo que hubiera adivinado intuitivamente: negar una regla), seguida de una subregla idents, un salto de línea opcional y finaliza con un punto y coma.

La identsregla es nuevamente similar al ejemplo EBNF. Es un solo ident, seguido de cero o más idents separados por comas.

La identregla es un poco especial. La "@", conocida como Atomic , delante del corchete está ahí para decir: "No quiero que se apliquen espacios en blanco implícitos a esta regla". Seguro que no queremos incluir ningún espacio en nuestro nombre de variable. Además, marcar una regla como atómica de esta manera trata la regla como un término, silenciando las reglas internas de coincidencia. Cualquier regla interna se descarta.

string_lit = { "\"" ~ inner ~ "\"" }
inner = { ASCII_ALPHANUMERIC* }

Tenga en cuenta que ASCII_ALPHANUMERICes una regla incorporada conveniente en Pest para cualquier carácter y dígito ASCII.

Si analizamos una cadena "hola" con esta regla, esto generará primero un string_litnodo, que a su vez tiene un innernodo que contiene la cadena "hola", sin comillas.

Árbol de regla no atómica

Agregar un sigilo "@" delante del string_litcorchete:

string_lit = @{ "\"" ~ inner ~ "\"" }
inner = { ASCII_ALPHANUMERIC* }

string_litTerminaremos con un nodo plano que contiene ""hola"".

Árbol de la regla atómica

Un sigilo similar "$" conocido como Compound Atomic , protege los espacios en blanco implícitos dentro de la regla. La diferencia es que permite que las reglas de coincidencia internas se analicen normalmente.

La !digitparte evita que la regla avance si comienza con un número. Si no es así, una o más combinaciones de caracteres, números y guiones bajos están bien.

#Pero espera, ¿dónde está el código?

¡Dang, mi inteligente explorador! Pareces arrinconarme en cada movimiento. Sí, eso no era código en absoluto, sino una definición de gramática de Pest. Ahora tenemos que escribir un código de Rust para analizar un texto. Inicie src/main.rsy agregue lo siguiente:

/// You need to do this to use macro
extern crate pest;                                                                                                                                                                                   
#[macro_use]                                                                                                                                                                                         
extern crate pest_derive;                                                                                                                                                                            

/// 1. Import modules                                                                                                                                                                                            
use std::fs;                                                                                                                                                                                         
use pest::Parser;                                                                                                                                                                                    
use pest::iterators::Pair;                                                                                                                                                                           

/// 2. Define a "marker" struct and add a path to our grammar file.                                                                                                                                                                                                 
#[derive(Parser)]                                                                                                                                                                                    
#[grammar = "grammar.pest"]                                                                                                                                                                            
struct IdentParser; 

/// 3. Print the detail of a current Pair and optional divider
fn print_pair(pair: &Pair<Rule>, hard_divider: bool) {
    println!("Rule: {:?}", pair.as_rule());
    println!("Span: {:?}", pair.as_span());
    println!("Text: {:?}", pair.as_str());
    if hard_divider {
        println!("{:=>60}", "");
    } else {
        println!("{:->60}", "");
    }
}

fn main() {
    /// 4. Parse a sample string input
    let pair = IdentParser::parse(Rule::declaration, "var foo1, bar_99, fooBar;")
        .expect("unsuccessful parse")
        .next().unwrap();

    print_pair(&pair, true);
    
    /// 5. Iterate over the "inner" Pairs
    for inner_pair in pair.into_inner() {
 
        print_pair(&inner_pair, true);

        match inner_pair.as_rule() {
            /// 6. If we match an idents rule...
            Rule::idents =>  {
                /// 7. Iterate over another inner Pairs
                for inner_inner_pair in inner_pair.into_inner() {
                    match inner_inner_pair.as_rule() {
                        /// 8. The term ident is the last level
                        Rule::ident => {
                            print_pair(&inner_inner_pair, false);
                        }
                        _ => unreachable!(),
                    }
                }
            }
            _ => unreachable!(),
        }
    }
}

Está bien si no entiendes la mayoría de las cosas aquí. Ejecutémoslo cargo runen el directorio de su proyecto y miremos la salida impresa.

Rule: declaration
Span: Span { str: "var foo1, bar_99, fooBar;", start: 0, end: 28 }
Text: "var foo1, bar_99, fooBarBaz;"
============================================================
Rule: idents
Span: Span { str: "foo1, bar_99, fooBar", start: 4, end: 27 }
Text: "foo1, bar_99, fooBarBaz"
============================================================
Rule: ident
Span: Span { str: "foo1", start: 4, end: 8 }
Text: "foo1"
------------------------------------------------------------
Rule: ident
Span: Span { str: "bar_99", start: 10, end: 16 }
Text: "bar_99"
------------------------------------------------------------
Rule: ident
Span: Span { str: "fooBar", start: 18, end: 27 }
Text: "fooBarBaz"
------------------------------------------------------------

El concepto más importante aquí es un Pair. Representa un par de tokens coincidentes o, de manera equivalente, el texto distribuido que una regla con nombre coincidió correctamente.

A menudo usamos Pairs para:

Determinar qué regla produjo elPair

Usar el Paircomo materia prima&str

Inspeccionar las sub-reglas internas nombradas que produjeron elPair

let pair = Parser::parse(Rule::enclosed, "(..6472..) and more text")
    .unwrap().next().unwrap();

assert_eq!(pair.as_rule(), Rule::enclosed);
assert_eq!(pair.as_str(), "(..6472..)");

let inner_rules = pair.into_inner();
println!("{}", inner_rules); // --> [number(3, 7)]

A Pairpuede tener cero, una o más reglas internas. Para máxima flexibilidad, Pair::into_inner()devuelve Pairs, que es un tipo de iterador sobre cada par.

💡 Pair::into_inner()es un idioma muy común cuando se trabaja con Pest. Asegúrate de entender qué Paires a.

#Vamos a analizar Systemd

Si has llegado hasta aquí, te mereces este gatito.

Ahora es el momento de poner el trabajo. Aquí hay un ejemplo de un archivo de unidad Systemd:

[Unit]
Description=Nginx
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/home/ec2-user/.local/bin
Environment=LD_LIBRARY_PATH=/usr/local/lib
Environment=PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
ExecStart=/usr/local/sbin/nginx-runner.sh
Restart=on-failure
RestartSec=0
KillMode=process

[Install]
WantedBy=multi-user.target

El archivo está agrupado en secciones, cada una con un nombre entre corchetes. Cada sección contiene cero o más pares de nombre y valor de propiedad, separados por un signo igual "=".

Tratemos de desarrollar un conjunto de reglas. Cree un nuevo proyecto de óxido con cargo new --bin systemd-parser, luego cree un archivo con el nombre src/grammar.pestcon las siguientes reglas:


/// Implicit white spaces are ok.
WHITESPACE = _{ " " }

/// Set of characters permited 
char = { ASCII_ALPHANUMERIC | "." | "_" | "/" | "-"  }

/// name is one or more chars. Note that white spaces are allowed.
name = { char+ }

// value can be zero or more char, plus = and : for path variables.
value = { (char | "=" | ":" )* }

/// section is a name, enclosed by square brackets.
section = { "[" ~ name ~ "]" }

/// property pair is a name and value, separated by an equal sign.
property = { name ~ "=" ~ value }

/// A Systemd unit file structure
file = {
    SOI ~
    ((section | property)? ~ NEWLINE)* ~
    EOI
}

En el main.rsarchivo, comience con lo siguiente

extern crate pest;
#[macro_use]
extern crate pest_derive;

use std::fs;
use std::env::current_dir;
use std::collections::HashMap;
use pest::Parser;

#[derive(Parser)]
#[grammar = "grammar.pest"]
struct SystemdParser;

/// Implement a simple AST representation
#[derive(Debug, Clone)]
pub enum SystemdValue {
    List(Vec<String>),
    Str(String),
}

// ...

Como primer paso, después de las importaciones y la configuración iniciales, definimos una SystemdValueenumeración como una representación simple del tipo de datos en un archivo Systemd. SystemdValue::Str(String)capturará un solo valor de propiedad y SystemdValue::List(Vec<String>)capturará varios valores de propiedad con un nombre de clave de propiedad duplicado. Por ejemplo, en el nginx.servicearchivo anterior hay varias Environmentpropiedades.

Aquí está la mainfunción:


fn main() {
    // Read and parse the unit file.
    let unparsed_file = fs::read_to_string("nginx.service")
        .expect("cannot read file");
    let file = SystemdParser::parse(Rule::file, &unparsed_file).expect("fail to parse")
        .next()
        .unwrap();

    // Create a fresh HashMap to store the data.
    let mut properties: HashMap<String, HashMap<String, SystemdValue>> = HashMap::new();

    // These two mutable variables will be used to store
    // section name and property key name.
    let mut current_section_name = String::new();
    let mut current_key_name = String::new();

    // Iterate over the file line-by-line.
    for line in file.into_inner() {
		match line.as_rule() {
			Rule::section => {
                // Update the current_section_name
                let mut inner_rules = line.into_inner();
                current_section_name = inner_rules.next().unwrap().as_str().to_string();
			}
			Rule::property => {
                let mut inner_rules = line.into_inner();
                // Get a sub map of properties with the current_section_name key, or create new.
                let section = properties.entry(current_section_name.clone()).or_default();

                // Get the current property name and value.
                let name = inner_rules.next().unwrap().as_str().to_string();
                let value = inner_rules.next().unwrap().as_str().to_string();

                // If the property name already exists...
                if name == current_key_name {
                    // Get the section of the map with the key name, or insert a new SytemdValue::List.
                    let entry = section.entry(current_key_name.clone()).or_insert(SystemdValue::List(vec![]));
                    // Push the value onto the inner vector of SystemdValue::List.
                    if let SystemdValue::List(ent) = entry {
                        ent.push(value);
                    }
                } else {
                    // Create a new SystemdValue::List and save it under name key.
                    let entry = section.entry(name.clone()).or_insert(SystemdValue::List(vec![]));
                    // Push the current value onto the vector, then set the
                    // current_key_name to the current name.
                    if let SystemdValue::List(ent) = entry {
                        ent.push(value);
                    }
                    current_key_name = name;
                }
			}
			Rule::EOI => (),
			_ => unreachable!(),
		}
    }
}

Todo esto está bien, pero no usamos SystemdValue::Strninguna parte del código. Para mantener limpio el código, decidimos tratar cada propiedad como HashMap<String, SystemdValue::List(Vec<String>), donde la clave del mapa es la clave de propiedad y el vector String almacena la lista de valores de propiedad. Si no hay valor, el vector está vacío. Si hay un valor, este vector contiene ese único valor, y así sucesivamente.

Para que la API sea un poco más fácil de usar, escribiremos una pequeña función auxiliar para procesar todos los correos electrónicos de un solo valor Systemd::List(Vec<String>)y convertirlos en archivos Systemd::Str(String).

// Iterate over the nested maps, and convert empty and 
// single-element `SystemdValue::List<Vec<String>>` to 
// `SystemdValue::Str(String)`.
fn pre_process_map(map: &mut HashMap<String, HashMap<String, SystemdValue>>) {
    for (_, value) in map.into_iter() {
		for (_, v) in value.into_iter() {
			if let SystemdValue::List(vs) = v {
				if vs.len() == 0 {
					let v_ = SystemdValue::Str(String::new());
					*v = v_.clone();
				} else if vs.len() == 1 {
					let v_ = SystemdValue::Str((vs[0]).clone());
					*v = v_.clone();
				}
			}
		}
    }
}

¡Ahora estamos listos para imprimirlo para que el mundo lo vea!

fn main() {

    // Our main code 

    pre_process_map(properties);

    println!("{:#?}", properties);
}

¡Auge! ¡Felicidades! Acaba de escribir un analizador de archivos Systemd, además de uno mini JS. 🤯 Ahora tendrás algo de tiempo libre para divertirte el viernes por la noche. Con otra tarde, es posible que incluso descubras cómo serializar el archivo de tu unidad Systemd en JSON para impresionar a tu jefe el lunes.

Puede consultar el código del analizador implementado como biblioteca en [este repositorio] (https://github.com/jochasinga/systemd-parser)

Fuente: https://hackernoon.com/how-to-build-a-parser-in-rust-for-fun-and-profit

#rust 

Annalise  Hyatt

Annalise Hyatt

1601575800

SVG in React: Building a Game

After my partner and I built our first Ruby program in the first module of our Bootcamp, I was so excited by the accomplishment that the following weekend I decided to take my programming skills a step further and make a command-line game.

The result was Badgers and Gyms, a game where you kill badgers with grenades:

Image for post

&: User | %: Badger

After I had graduated from the Bootcamp and was building a portfolio site for my projects, I wanted to incorporate this game into the site somehow. I looked around for ways to embed a terminal on the site that could run Ruby, but I couldn’t find anything. So, I decided to adapt the game into React.

Wiring Up SVG

The first problem I faced was how to display the game with moving parts and animations. When first learning JavaScript, I had played around with moving <div> elements on the page, but that didn’t seem like the best way to handle this.

I had used SVG before, but not with moving parts. I started experimenting with some different things and discovered the <circle> tag, which has a cx and cy attribute for positioning the circle within the <svg> tag. This seemed like a straightforward way to start.

I found an SVG graphic of a basketball court on Wikimedia Commons and wrapped its paths in their own <g> layer. I then added a second layer on top for the moving parts:

If you look at the bottom <g> layer, you’ll see I’ve controlled the cx and cy attributes and pointed them to values on a user object. The next task is to change those values to move the objects around within the boundaries of the basketball court.

If you look at the bottom <g> layer, you’ll see I’ve controlled the cx and cy attributes and pointed them to values on a user object. The next task is to change those values to move the objects around within the boundaries of the basketball court.

Functional Programming To The Rescue

There are three types of moving objects in this game: the user, the badgers, and the grenades. While these three objects might move at different speeds, they all need to know how to move about the <svg> basketball court.

#svg-animation #game-development #svg #react #javascript

Tyshawn  Braun

Tyshawn Braun

1602788400

Advanced Ensemble Learning Techniques

In my previous post about ensemble learning, I have explained what is ensemble learning, how it relates with Bias and Variance in machine learning and what are the simple techniques of ensemble learning. If you haven’t read the post, please refer here.

In this post I will cover ensemble learning types, advanced ensemble learning methods — Bagging, Boosting, Stacking and Blending with code samples. At the end I will explain some pros and cons of using ensemble learning.

Ensemble Learning Types

Ensemble learning methods can be categorized into two groups:

1. Sequential Ensemble Methods

In this method base learners are dependent on the results from previous base learners. Every subsequent base model corrects the prediction made by its predecessor fixing the errors in it. Hence the overall performance can be increased via improving the weight of previous labels.

2. Parallel Ensemble Methods

In this method there is no dependency between the base learners and all base learners execute in parallel and the results of all base models are combined in the end (using averaging for regression and voting for classification problems).

Parallel Ensemble methods are divided in two categories-

**1. Homogeneous Parallel Ensemble Methods- **In this method a single machine learning algorithm is used as a base learner.

2. Heterogeneous Parallel Ensemble Methods- In this method multiple machine learning algorithms are used as base learners.

Advanced Ensemble Techniques

Bagging

Bagging or Bootstrap Aggregation is a parallel ensemble learning technique to reduce the variance in the final prediction.

The Bagging process is very similar to averaging, only difference is that bagging uses random sub-samples of the original dataset to train same/multiple models and then combines the prediction, whereas in averaging the same dataset is used to train models. Hence the technique is called Bootstrap Aggregation as it combines both Bootstrapping (or Sampling of data) and Aggregation to form an ensemble model.

#artificial-intelligence #ensemble-learning #ensemble #data-science #machine-learning

Liam Hurst

Liam Hurst

1597288897

SVG 101: What Is SVG?

Learn why SVG is superior to pixel graphics in terms of scalability, responsiveness, interactivity, programmability, performance, and accessibility.

Though it was conceived back in the late 1990s, SVG is in many ways the “ugly duckling” file format that grew up to become a swan. Poorly supported and largely ignored for most of the 2000s, since around 2017 all modern web browsers have been rendering SVG without serious issues, and most vector drawing programs have been offering the option to export SVG, which has unquestionably become a widely used graphic format on the Web.

This hasn’t happened by chance. Although traditional raster graphic file formats like JPGs and PNGs are perfect for photographs or very complex images, it turns out that SVG is the one graphic format that most closely meets current web development demands of scalability, responsiveness, interactivity, programmability, performance, and accessibility.

SVG 101 Header

So, What Is SVG and Why Should You Use It?

SVG is an eXtensible Markup Language (XML)-based vector graphic format for the Web and other environments. XML uses tags like HTML, although it’s stricter. You cannot, for example, omit a closing tag since this will make the file invalid and the SVG will not be rendered.

To give you a taste of what SVG code looks like, here’s how you would draw a white circle with a black border:

<circle cx="100" cy="100" r="50" stroke-width="4" stroke="#000" fill="#fff" />

As you can see, under the hood, SVG documents are nothing more than simple plain text files that describe lines, curves, shapes, colors, and text. As it’s human-readable, easily understandable and modifiable, when embedded in an HTML document as an inline SVG, SVG code can be manipulated via CSS or JavaScript. This gives SVG a flexibility and versatility that can’t ever be matched by traditional PNG, GIF or JPG graphic formats.

SVG is a W3C standard, which means that it can inter-operate easily with other open standard languages and technologies including JavaScript, DOM, CSS, and HTML. As long as the W3C sets the global industry standards, it’s likely that SVG will continue to be the de facto standard for vector graphics in the browser.

The awesomeness of SVG is that it can solve many of the most vexing problems in modern web development. Let’s breeze through some of them.

#svg #ux #web-development #developer