PhōsPixel

Nuages

Des exercices originaux intégrant différentes techniques pour valider ma compréhension des filtres, des masques, du morphing par animation et des notions de trait et de remplissage.

PhōsPixel

Dessin au scroll

Une variation avec la technique d’animation utilisant la propriété CSS stroke-dashoffset pour animer les traits. Ici, les traits apparaissent lorsque l’utilisateur fait défiler la page.

En gros, par JavaScript, on va chercher la longueur du trait avec la fonction getTotalLength() puis on mesure l’emplacement de la fenêtre active sur la page en comparant les éléments clientHeight et scrollHeight pour trouver le haut et le bas du viewport et ainsi faire apparaitre ou disparaitre les traits. Je vérifie aussi le type d’appareil ; si c’est un téléphone, la dimension des dessins est réduite de 50%. Chaque SVG est autonome et comprend donc sont propre script personnalisé.

Dessin au scroll 01 Dessin au scroll 02 Dessin au scroll 03

Le bruit fractal pour faire du grain

Pour mon exploration du grain (bruit) en SVG, je me suis inspiré du tutoriel Grainy Gradients découvert sur css-tricks. Si j’aime l’effet, je ne l’ai pas suivi car ce n’est pas fait pour être dans un seul SVG autonome, mon objectif premier pour le moment. Le grain est bien créé avec un filtre SVG mais il devient ensuite un fichier externe qui sera appliqué comme background-image à un div HTML. Ainsi, j’ai plutôt expérimenté par moi-même, ce qui demande plus de temps mais m’a aussi permis de mieux comprendre et revoir des notions nouvelles et apprises récemment.

Différentes variations

Variation #1

Bruit fractal pour faire du grain 01 feTurbulence type=’fractalNoise’ baseFrequency=’2′ numOctaves=’3′ stitchTiles=’stitch’

Variation #2

Bruit fractal pour faire du grain 02 feTurbulence animate baseFrequency values=3;2;3;2 dur=10s

Variation #3

Bruit fractal pour faire du grain 03 Meilleur effet avec ce paramètre sur les filtres : color-interpolation-filters=sRGB Sans cela, le filtre feGaussianBlur sur le cercle, crée beaucoup de bandes disgrâcieuses

Variation #4

Bruit fractal pour faire du grain 04 baseFrequency values=1;0.5 NB : feColorMatrix type=saturate values=0 Le cercle est déplacé en cx avec animate Initiation au KeySpline et KeyTimes équivalents (complexes) au cubic bézier

Extrait du code pour visualiser l'équivalant SVG d'animation-timing-function

<circle id="cercle-1-25022024" cx="125" cy="112" r="100"  
        fill="url(#degrade-4-250224)" filter="url(#cercle-flou-2-25022024)">      <animate attributeName="cx" from="125" to="375" begin="0s" dur="10s"         values="125;150;175;200;250;300;375"
      keySplines="
	0.1 0.8 0.2 1;
	0.1 0.8 0.2 1;
	0.1 0.8 0.2 1;
	0.1 0.8 0.2 1;
	0.1 0.8 0.2 1;
	0.1 0.8 0.2 1" 
      keyTimes="0;0.22;0.33;0.55;0.88;0.92;1"       
      calcMode="spline" repeatCount="indefinite"/>
  </circle>

Jouer avec les paramètres : masque, filtres feTurbulence, feDisplacementMap et feDiffuseLighting

Bruit fractal pour faire du grain 05

feComponentTransfer pour travailler le contraste et la luminosité

Bruit fractal pour faire du grain 06 v2

Un Gif animé comme masque !

Notes

Extrait du code – visualisation du <mask>

 <defs>
    <mask id="masque-1-25022024" maskunits="userSpaceOnUse" maskcontentunits="userSpaceOnUse">
      <image xlink:href="https://phospixel.com/wp-content/uploads/2024/02/3b04.gif" width="500" height="280"></image>
    </mask>

    <linearGradient id="gr-1-25022024" x1="0" y1="0" x2="100%" y2="100%">
      <stop offset="15%" class="stop-color-1-22022024  stop-color--1" />
      <stop offset="45%" class="stop-color-1-22022024  stop-color--2" />
      <stop offset="55%" class="stop-color-1-22022024  stop-color--2" />
      <stop offset="85%" class="stop-color-1-22022024  stop-color--3" />
    </linearGradient>

    <linearGradient id="gr-2-25022024" x1="0" y1="100%" x2="100%" y2="0%">
      <stop offset="15%" class="stop-color-1-22022024  stop-color--4" />
      <stop offset="45%" class="stop-color-1-22022024  stop-color--5" stop-opacity="0" />
      <stop class="stop-color-1-22022024  stop-color--5" stop-opacity="0" />
      <stop offset="85%" class="stop-color-1-22022024  stop-color--6" />
    </linearGradient>
  </defs>

  <g mask="url(#masque-1-25022024)" class="mouvement-1-22022024">
    <rect fill="url(#gr-1-25022024)" width="100%" height="100%"></rect>
    <rect fill="url(#gr-2-25022024)" width="100%" height="100%"></rect>
  </g>

Les masques (et un début de solution aux problèmes de dessin)

1. Quatre variations avec un masque animé

Expérimentation avec un masque comportant un dégradé

Masque animé dégradé

Exercice de base faisant parti du tutoriel Learn SVG Animation – With HTML, CSS & Javascript sur Udemy.

Base

Masque animé 1

Technique de l’élément SVG <mask>

Extrait de code pour visualiser qu’il faut déboubler les <path>s dans l’élément <mask>, et ensuite les afficher. Ici, on applique le masque au tube (#devoile) alors que le cercle reçoit une animation CSS (#demasque-1-2102024).

<defs>
  <mask id="devoile">
    <path class="tube" fill="#020202" d="M136.07 ..." />
    <circle id="demasque-1-2102024" fill="#fff" cx="66.836" cy="50.356" r="34" />
  </mask>
</defs>

<path mask="url(#devoile)" fill="#020202"class="tube" fill="gray"d="M136.07 ..." />
<circle id="demasque-1-2102024" fill="none" cx="66.836" cy="50.356" r="34" />
</svg>

Un avancement pour la préparation des SVG dans Adobe Illustrator

Pour l’exercice de masque, le mot EXPERIMENT en SVG était fourni. J’ai voulu faire mon propre mot et comme les tutos ne montrent pas comment préparer les fichiers SVG, j’ai eu à chercher comment faire pour créer un seul et unique path dans Adobe Illustrator car mon exercice ne fonctionnait pas 🙁 C’est en ouvrant le fichier fournit que j’ai remarqué dans les calques qu’il s’agissait d’un compound path et non pas d’un path!

Enfin, ceci pourrait régler, en partie, les problèmes de dessin rencontré jusqu’à présent, notament avec les signatures, pour avoir un seul path et donc une seule animation continue. Pour ce, il faut faire un Compound path (Object > Coumpound Path > Make).

Variation #1

J’ai voulu rendre l’effet de dévoiler quelque chose de flou avec un verre ou une loupe, en plus d’ajouter un trait autour du cercle.

Masque animé 2

Variation #2

Je n’ai pas aimé que le flou reste lorsque l’animation de dévoilement passe. J’ai donc retravaillé pour rendre l’effet souhaité.

Masque animé 3

Comprendre la variation #2 : deux masques et 4 cercles animés

Un cercle qui dévoile le texte et un cercle qui masque le texte flou, et chacun d’eux ont un deuxième cercle avec le contour noir (stroke) qui les suivent.

Masque animé 4

2. Masque avec un png externe

Texture de grain, masque, png dans WP, defs Texture type Alpha

Je l’avais déjà fait lorsque je testais du grain pour une première fois. Cette fois-ci l’image est externe, dans les <defs>, et ensuite appliqué comme un masque. Le résultat est pas mal mieux que celui obtenu avec un filtre de grain dans Adobe Illustrator.

  <defs>
    <mask id="masque-1-20022024">
      <image height="400" width="600" x="0" y="0"
        xlink:href="https://phospixel.com/
              wp-content/uploads/2024/02/photos....png"
    </mask>
</defs>
<text x="22" y="100" class="texte-01-20022024" 
        mask="url(#masque-1-20022024)">Texture type Alpha
</text>

image height="400" weight="600" : un problème à régler pour l’adaptabilité ?

Mask vs clipPath et clip-path

Même si je n’ai pas encore tester les clipPath (SVG) ou clip-path (CSS), je sais qu’ils permettent d’afficher ou non une partie d’une image. Je me demandais par contre le contexte d’utilisation par rapport aux masques et cet article très imagé aborde très bien la question.

En gros, les masques sont beaucoup plus puissant car on peut faire des dégradés. Les clipPath c’est noir ou blanc, ça passe ou pas, c’est visible ou non, il n’y a pas d’entre-deux.

Nouvelle signature, nouveaux problèmes de dessin

J’ai voulu refaire ma signature car je n’étais pas satisfaite du résultat de ma première version. Au lieu d’utiliser ma tablette, son crayon et Clip Studio Pro, j’ai suivi à la lettre la technique présentée dans le tutoriel de Code with Sam sur udemy : avec Adobe Illustrator, écrire avec le crayon et un trait de 1pt. Voici le résultat :

Après optimisation avec SVG OMG, je reporte le code obtenu dans VS Code et anime le stroke-dashoffset. Le résultat est loin d’être celui recherché! On dirait que ce n’est pas le même code SVG que le premier ci-haut mais oui, c’est bien pareil. La technique d’animation du trait ne fonctionne donc pas encore car le trait est double.

Une capture d’écran montrant le trait dans Illustrator. Ceci n’est donc pas un trait pour le SVG même si ce l’est pour Adobe : il n’y a aucun remplissage, ce n’est qu’un trait de 1pt.

Pour m’approcher de l’objectif souhaité, j’ai éliminé du code des <path>s directement dans VS Code. L’animation ne jouerait pas en boucle normalement mais elle est en continu pour observation. Remarquez que lorsqu’il y a des rondeurs, le trait remonte ensuite sur le chemin d’où il venait.

Noémie

Post

Je n’ai pas encore découvert comment régler le problème pour une signature manuscrite, en utilisant Adobe Illustrator. Par contre, en lisant un autre tutoriel, sur un autre sujet mais qui utilise aussi la technique d’animation avec le stroke-dashoffset, l’auteur, Louis Hoebregts, donne ces informations :

Ainsi, il semble bien possible de pouvoir le faire de manière manuscrite. Ses indication sur le trait unique éclaire. Peut-être serait-ce plus simple avec Inkscape. J’ai toujours voulu l’essayer (et m’affranchir d’Adobe 😉 ).

La balise defs et où appliquer les styles

L’élément <defs> sert à définir des propriétés supplémentaires de type XML. Dans le contexte d’un SVG, on l’utilise souvent pour y circoncir des propriétés souvent stylistiques non CSS. Par exemple, un dégradé <linearGradient> devrait être définit à l’intérieur d’une balise <defs>, de même qu’un <mask> et un <filter> .

Defs et degradé linearGradient PhōsPixel
<defs>
   <linearGradient id="insta-1-20022024">
      <stop offset="0%" stop-color="#f8ED34"/>
      <stop offset="50%" stop-color="#FF3966"/>
      <stop offset="100%" stop-color="#33207f"/>
   </linearGradient>
</defs>

<text fill="url(#insta-1-20022024)" style="font-family:&quot;Roboto&quot;,&quot;Arial&quot;,sans-serif;font-weight:700;font-size:2.6rem;pointer-events:none" transform="translate(91.545 64.47)">PhōsPixel
</text>

Le fill est déinit ici inline mais il pourrait être appliqué dans le style. Il semble toutefois que ce soit plus optimal inline, pour la publication. SVG OMG, l’optimiseur de code, replace la majorité des styles inline, à l’exception des @keyframe, ou si un même style s’adresse à plusieurs éléments.

Ma règle pour les styles

transform et transform

Il y a des situations où on doit absolument utiliser le inline. Par exemple, il est impossible d’envoyer le tranform dans le <style> car le CSS ne comprend pas comment appliquer la translation. Par rapport à quoi? On n’est pas en HTML et le SVG lui-même n’est pas positionné dans la page. Or, ce que je comprends ici, c’est que le transform inline est une propriété SVG qui applique la translation par rapport à l’élément lui-même, ce n’est pas un transform de mise-en-page (CSS) lié au conteneur, à un parent ou au viewport.

Exploration d’une signature animée et problèmes de dessin

1. Signature faite au crayon sur une tablette

Animer le trait avec animation CSS – signature tablette vectorisée

2. Animer le remplissage?

Animer le remplissage avec propriétés SVG animate et linearGradient
  <defs>
    <linearGradient id="gauche-a-droite-1-170224">
      <stop offset="0" stop-color="#00a98c">
        <animate attributeName="offset" from="0" to="1" dur="3s" repeatCount="indefinite" />
      </stop>
      <stop offset=" 0" stop-color="#b4eae1">
        <animate attributeName="offset" from="0" to="1" dur="3s"/>
      </stop>
    </linearGradient>
  </defs>

  <path fill="url(#gauche-a-droite-1-170224)"

3. Visualiser le problème en apprenant à animer un cercle sur le path de la signature avec <animateMotion>

Animer un cercle sur le path d’un autre SVG
  <circle r="5" fill="red">
    <animateMotion dur="30s" repeatCount="indefinite"
      path="M115.9 241.4c3.9-15.8 7.7-31.6 11.8-47.3 [...]

4. Nouvelle signature faite au crayon, un trait simple, dans Illustrator

Exploration de la signature, faite dans Illustrator, un seul trait (pas de remplissage)

Au niveau d’Illustrator, j’en conclus qu’un calque = un path. Bien logique! Mais dans le cas d’une écriture ce n’est pas si simple à contrôler.

5. Dessin au crayon dans Illustrator, 3 calques, 3 paths & 3 animations dont 2 avec délais

Résultat final 3 traits, 3 calques, 3 paths et 3 animations

J’ai opté pour une signature toute en lettres attachées, afin de vérifier ma conclusion. Cela fonctionne en effet.

Plus de traits, de remplissages, d’animations et de problèmes de design

Dessin et animation – par remplissage ou par trait

Un mauvais design de loupe pour une animation avec une seule itération

Un mauvais design de loupe animée

Une loupe mieux conçue vectoriellement pour une seule animation dans le code

Un meilleur design de loupe animée

Morphing sans animation, url interne, les balises g et foreignObject

Tous les exemples sur cette page sont sans animation, sans JS au niveau de la transformation de la forme, ils ne contiennent donc qu’une transition CSS entre deux propriétés d: path("").

J’ai été ravie de voir ce truc sur css-tricks dans l’articles sur les propriétés et j’ai voulu l’essayer et voir comment il pourrait fonctionner dans diverses situations.

:hover pour souris

Morphing sans animation + hover

Pour que le morphing fonctionne, les deux formes doivent avoir le même nombres de points. Dans cet autre article sur css-tricks, on explique une autre technique, avec animation et JS, mais la partie pour les formes est bien expliquée.

Si les deux formes n’ont pas le même nombre de points, JavaScript devrait pouvoir le faire car j’ai vu que c’est aussi faisable avec la librairie d’animations GSAP.

Tenir la position du morphing avec onClick

Morphing sans animation + onClick

Le onClick serait très intéressant pour des icônes réutisables, comprenant leur 2 états à même un seul SVG. C’est une chose que je compte exploré. Mais attention à la règle du nombre de points, ou trouver une solution JS!

Faire apparaître un <text> et des <circle> avec onClick

Morphing sans animation + onClick Bonne fête! Bonne fête !

Je me suis mise à penser aux cartes de fêtes virtuelles et au annonces et bannières. Oui c'est bien faisable à même un seul SVG!

Du HTML dans un SVG avec <foreignObject>

foreignObject = inclure du HTML

Contenu HTML dans un SVG

Un <foreignObject> est un élément SVG qui permet d'intégrer du contenu HTML dans un document SVG. Cela permet d'inclure des éléments HTML tels que du texte, des formulaires, des images, etc.. L'utilisation de <foreignObject> permet de combiner les fonctionnalités de SVG et HTML dans un même document. En savoir plus : MDN

Une case à cocher dans un SVG !

J'ai voulu essayer une case à cocher pour vérifier l'ampleur des possibilités avec <foreignObject>. Cela fonctionne mais pour récupérer ensuite le label, et atteindre le path à l'extérieur du <foreignObject>, je n'y suis pas arrivée. À ce moment là, il faudrait mettre le SVG à atteindre à l'intérieur même du HTML, donc : <svg>, <foreignObject>, HTML, <svg></svg>, </foreignObject>, </svg>.

Étant donné que je ne voulais pas m'attarder sur cette curiosité, je n'ai pas poussé plus loin mais j'ai su ce que je voulais savoir : les SVG, c'est presque infini côté possiblilités!

Morphing sans animation +Case à cocher

Extrait du code pour visualiser la transition CSS


<!--Les chemins SVG qui se transforment l'un en l'autre doivent avoir les mêmes 
commandes et le même nombre de points, sinon la transformation ne fonctionnera pas.-->
<style type="text/css">
    .morphing-path path {
	d: path("M150, 10 L40, 200 L260, 200 L260, 200Z");
	fill: url(#SVGID_1_);
	transition: all 0.35s ease;
	cursor: pointer;
     }
    .morphing-path path:hover {
	d: path("M220, 10 L40, 10 L40, 220 L220, 220Z");
	fill: url(#SVGID_2_);
     } 
</style>

<!-- On attribue la classe à un groupe et on ne fait 
     que déclarer la balise <path />  -->
    <g class="morphing-path">
	<path />
    </g>
</svg>