SVG & 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 SVG au cercle 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 envisagée

@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 deuxième solution est tout aussi incorrecte.
Les paramètres "cx" et "cy" sont des attributs et donc ne peuvent être modifiés via le CSS !

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;}

Elle consiste à utiliser dans le "keyframes" (modèle d'animation CSS) la propriété transform avec toutes ses fonctions possibles (scale, translate, rotate, etc).
Dans l'exemple il faut déplacer la boule donc c'est la fonction translate !

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".

Le bon code complet

... @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> ...

L'ombrage en SVG est beaucoup plus compliqué qu'en CSS.
Il faut dessiner deux ronds : un rond en gris flouté et décalé de 3px (par application du filtre composite SVG) et au dessous du 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 avec le bon code

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