Bonsoir,

Comme je ne sais pas exactement d'où vient le problème - CSS ou JS - je poste le sujet en "débutant", mais j'ai tout de même l'impression que mon problème est lié au CSS.

Il s'agit de la compatibilité avec Chrome v111 ou inférieur pour une animation SVG.

Tout est partit de cet article posté sur CSS-Tricks où il s'agit de simuler le dessin de SVGs avec les propriétés CSS stroke-dasharray et stroke-dashoffset. Cet article m'a inspiré et j'ai eu envie d'aller jusqu'au bout en créant un script permettant d'animer n'importe quel SVG, même s'il est très complexe.

Vous pourrez vous donner une idée du résultat obtenu en consultant cette page 404 : Page 404 avec une animation sur le SVG.
Ça fonctionne aussi au scroll, lorsque vous arrivez au niveau de chaque SVG animable, comme sur cette page, grâce à un `IntersectionObserver`.

Ça fonctionne aussi sur les Sprites SVG car j'injecte préalablement le contenu du symbole du sprite en SVG en ligne grâce à une fonction `svgSpriteToInline()` de mon cru (pour info voir la fonction ici : Github).

Donc j'étais bien content du résultat obtenu avant de voir que j'ai un bug sur un Chrome v111 que j'ai au boulot : le SVG n'est pas colorisé, il est donc invisible pour l'utilisateur.

Je n'ai pas d'erreur JavaScript, à priori les SVG sont tous bien retournés en inline, si besoin est, par la fonction `svgSpriteToInline()`, j'ai donc l'impression que ça pêche côté CSS mais sans trouver pourquoi. Un problème de compatibilité avec une règle CSS ? Mais alors laquelle ? J'ai fais le tour et il me semble qu'elles sont toutes supportées :
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .invisible-if-animation {
    visibility: hidden;
  }

  .svg-animation.active {
    & :where(path, circle, ellipse, line, polygon, polyline, rect, text, textPath, tref, tspan) {
      stroke-width: 1;
      fill: transparent;
      stroke: var(--colorG38);
      animation: anim-svg var(--anim-svg, 5s) cubic-bezier(0.5, 0, 1, 0) forwards;
    }
  }

  @keyframes anim-svg {
    90% {
      stroke: var(--colorG38);
    }
    to {
      stroke-dashoffset: 0;
      stroke: var(--colorT2);
    }
  }
}

Le JavaScript qui calcule la longueur des paths - et qui donc permet l'animation correcte via les styles CSS - est un peu conséquent ; je vous le met en lien : svgAnimation.js (Github).

Si l'un d'entre-vous y voit plus clair que moi... Merci à lui.
Modifié par Olivier C (03 Sep 2024 - 01:00)
Modérateur
Bonsoir Olivier,

Ce qui m'embête, c'est que sur ma machine, je n'ai pas de chrome. Juste un FF, Chromium et opera sur ma Debian. Sur le win10, il y a un FF, edge et opera. (Chrome, c'est pas ma tasse de thé)

Bref, est-ce que par hasard, ça ne viendrait pas de là ?

@keyframes anim-svg {
    90% {
      stroke: var(--colorG38);
    }
    to {
      stroke-dashoffset: 0;
      stroke: var(--colorT2);
    }
  }


Si je ne dis pas de bêtise, ton anim passe de 90% à 100%. (j'ai tendance à écrire en % mes anims). Pour moi, tu déclares à 90%, stroke-dashoffset: 0; et à 100% tu redéclares stroke-dashoffset: 0; . Sachant que la valeur par défaut de stroke-dashoffset est de 0.

Aussi, tu parles d'un bug sur chrome, mais quel est le comportement qu'il te sort ?

Je viens d'inspecter ta 404. (Pas sexy à lire la minification du html).

<figure class="xs-center">
            <svg class="size xs-scale decorative-svg sprite-to-inline svg-animation invisible-if-animation" role="img" focusable="false" style="--size:35em;--xs-scale:90%">
              <use href="/sprites/silos/195v.svg#a"></use>
            </svg>
          </figure>

Or, tu utilises un symbole. Il me semble que ça peut poser problème.

*Je n'ai pas mis les mains dans le cambouis. Cette réponse est juste une réflexion.
Modifié par niuxe (03 Sep 2024 - 02:01)
Bonjour Niuxe,
niuxe a écrit :
Bref, est-ce que par hasard, ça ne viendrait pas de là ? [...] Si je ne dis pas de bêtise, ton anim passe de 90% à 100%. (j'ai tendance à écrire en % mes anims). Pour moi, tu déclares à 90%, stroke-dashoffset: 0; et à 100% tu redéclares stroke-dashoffset: 0; . Sachant que la valeur par défaut de stroke-dashoffset est de 0.

stroke-dashoffset passe bien d'un 0% implicite à 100%. Il ne démarre pas de 0px car la valeur est calculée pour chaque path par JavaScript via la fonction setSvgAnimationAttributes() inclue dans le fichier svgAnimation.js. Le 90% de l'animation CSS c'est pour gérer la couleur.

niuxe a écrit :
Aussi, tu parles d'un bug sur chrome, mais quel est le comportement qu'il te sort ?

Le SVG, éventuellement sprite, est bien rendu en inline, les stroke-dashoffset sont bien rendus pour chaque path, mais le SVG est "invisible", comme si la colorisation ne se faisait pas.

niuxe a écrit :
Je viens d'inspecter ta 404. [...] Or, tu utilises un symbole. Il me semble que ça peut poser problème.

Tout à fait, on ne peut pas animer les sprites SVG, c'est pourquoi j'utilise préalablement une fonction JS svgSpriteToInline() qui transforme ces sprites en SVG inline. Lorsque le SVG est prêt la fonction envoie un CustomEvent('svgSpriteInlined') et la fonction initSvgObserver() capte l'événement personnalisé.
Modifié par Olivier C (03 Sep 2024 - 11:25)
J'ai peut-être trouvé mon problème (je suis au boulot avec l'inspecteur de mon vieux Chrome v111) : sur les paths du SVG j'injecte des attributs en javascript de cette manière (ici pour le contexte) :
  path.setAttribute('stroke-dasharray', pathLength) // ok
  path.setAttribute('stroke-dashoffset', pathLength) // ok
  path.setAttribute('fill', 'transparent') // ?
  path.setAttribute('stroke', 'orange') // ?
  path.setAttribute('stroke-width', '1') // ?

Les deux premiers sont nécessaires pour l'animation CSS qui va s'appuyer sur les valeurs définies ainsi. Par contre je ne sais plus pourquoi j'avais aussi défini les attributs fill et strocke (et même stroke-width)... peut-être lors de mon dev... Quoi qu'il en soit ils ne me semblent plus nécessaires et même pire : ce sont peut-être eux qui me foutent le bronx pour les anciens navigateurs qui semblent ne pas pouvoir passer outre via CSS. Une histoire de poids des sélecteurs qui aurait changé d'une version à l'autre face aux attributs inlines ?

J'attends de rentrer chez moi pour supprimer ces lignes et voir ce que ça donne.

Édit : me revoilà chez moi, modifs faites... il n'y a pas d'effet de bord sur les navigateurs récents, maintenant je dois attendre de retourner au boulot pour tester sur la vieille version 111 de Chrome (ah misère...).
Modifié par Olivier C (03 Sep 2024 - 22:26)
C'est bon, j'ai trouvé la source du problème et il s'agissait de CSS : la version susnommée de Chrome (v111 et inf.) ne supporte pas cette partie de la règle conditionnelle @media qui n'est supportée qu'à partir de Chrome v120 :
(scripting: enabled)

J'ai déjà modifié le JS pour qu'il n'y ait rien de non nécessaire en attribut inline, ce qui fait que, au pire, les SVG s'affichent sans animation. Tant pis pour les anciens navigateurs ; pas grave car même si la baseline est proche, le temps que je sorte un truc pour la production...
Modifié par Olivier C (04 Sep 2024 - 23:43)
Meilleure solution
Parce que sa baseline est encore récente, mars 2023, et surtout c'est ce que je possède au boulot - dans un CHU -, les techniciens bloquant les MAJ par "sécurité"...

C'est ce qui m'a permis de voir le bug mentionné plus haut et qui m'a incité à trouver une alternative élégante : au départ je ne savais pas d'où venait le problème, il était donc important de trouver au minimum la solution d'une dégradation gracieuse au cas où.