Animation d'objets SVG avec CSS : pièges à éviter

Après s'être habitué à animer des objets HTML via CSS on peut être tenté d'intégrer dans un "keyframes" destiné à s'appliquer à un objet SVG des propriétés de style telles box-shadow, background, top, left et d'autres.
Or ces propriétés CSS ne sont pas reconnues par le format SVG !

Reprenons le thème de la boule de billard qui rebondit à l'infini sur les bords de ce dernier.

Le code dans la balise SVG

<svg viewBox ="0 0 800 200" width="90%" height ="auto" style = 'background : yellow ;box-shadow : 5px 5px 5px gray;'> <circle cx="10" cy="190" r="10" fill ="red" id ="rond" style ="box-shadow : 2px 2px 2px gray;"/> </svg>

Mais il y a un bug.
La boule rouge n'est pas ombrée !

La propriété CSS box-shadow s'applique bien à la balise SVG de la page qui est un élément HTML mais pas à l'objet circle qui est un objet SVG !
Solution : définir et appliquer un filtre composite SVG.

Le code CSS d'animation

Passons maintenant à l'animation de la boule.

Première solution envisagée

@keyframes deplace
	{ 
		0% {}
		25% {left :200px ; top : 10px; }
		50% {left :400px ; top:190px;}
		75% {left :600px ; top:10px; }
		100% {left :800px ; top:190px;}
	}
#rond{animation : deplace 10s 0s infinite linear alternate;}

Cette solution est valide pour déplacer un objet HTML (positionné en relatif ou en absolu dans une boîte HTML).
Mais les notions de positionnement absolu,relatif sont inconnues du format SVG donc ici ça ne marchera pas !!!

Deuxième solution

@keyframes deplace
	{ 
		0% {}
		25% {cx :200px ; cy:10px; }
		50% {cx :400px ; cy:190px;}
		75% {cx :600px ; cy:10px; }
		100% {cx :800px ; cy:190px;}
	}
#rond{animation : deplace 10s 0s infinite linear alternate;}

Cette solution "marche" avec Chrome mais pas avec Firefox !
En effet les paramètres cx,cy ne sont pas des propriétés (de style) mais des attributs (de balise).

La bonne solution

@keyframes deplace
	{ 
		0% {}
		25% {transform :translate(200px,-190px);}
		50% {transform :translate(400px,0px);}
		75% {transform :translate(600px,-190px);  }
		100% {transform :translate(790px,0px); }
	}
#rond{animation : deplace 10s 0s infinite linear alternate;}

Attention dans un canevas SVG je rappelle que l'origine par défaut d'une transformation est le point haut gauche.
Il faut donc exprimer les translations par rapport à ce point !

Pour résumer lorsque vous voulez animer des objets SVG avec CSS et qu'il s'agit de modifier les dimensions et le positionnement de ces objets il faut utiliser la propriété CSS transform

Et l'ombrage de la boule ?

Il faut définir un filtre composite SVG et l'appliquer à l'objet "circle".

Solution définitive

Le code

... @keyframes deplace { 0% {} 25% {transform :translate(200px,-190px);} 50% {transform :translate(400px,0px);} 75% {transform :translate(600px,-190px); } 100% {transform :translate(790px,0px); } } #rond{animation : deplace 10s 0s infinite linear alternate;} ... <svg viewBox ="0 0 800 200" width="90%" height ="auto" style = 'background : yellow ;box-shadow : 5px 5px 5px gray;'> <defs> <filter id="ombrage"> <feGaussianBlur stdDeviation="2" result ="flou"/> <feOffset in ="flou" dx="3" dy ="3" /> </filter> </defs> <g id ="rond"> <circle cx="10" cy="190" r="10" fill ="gray" filter="url(#ombrage)" /> <circle cx="10" cy="190" r="10" fill ="red" /> </g> </svg> ...

Il faut dessiner deux ronds : un rond en gris flouté et décalé de 3px (application du filtre) et au dessus un rond rouge.
C'est désormais le groupe de ces deux formes qui constitue l'objet "rond".

Pour réviser les filtres SVG visitez le tuto "dessiner avec SVG".

Aperçu

Vous pouvez constater que désormais la boule rouge est bien ombrée.
Retour menu