SVG : la balise animateMotion du SMIL

Si vous voulez déplacer un objet SVG le long d'un chemin il faut utiliser la balise animateMotion.

Déplacement d'une forme simple le long d'un chemin

Le code SVG correspondant

<svg width="100%" height="auto" viewBox ="0 0 800 600" style = 'background-image : url(../images/chalets.jpg); background-size : cover ;' > <polygon points = "0,0 0,30 30,30 20,50 50,30 80,30 90,25 80,20 50,20 30,0 30,20 10,20 0,5" fill ='silver' id ="jet" > <animateMotion begin="0s" dur="15s" repeatCount="indefinite" path = "M-100,100 h1000 " /> </polygon> </svg>

La zone de dessin a pour "background" une image qui fait fonction de décor.

SVG : il faut déplacer un polygone le long d'un chemin donc la balise animateMotion contient l'attribut path et est contenue dans le conteneur polygon.
Ici la valeur de l'attribut path est une simple droite horizontale mais ça pourrait une courbe ...
L'avion ne surgit pas brutalement (à gauche) car le chemin a une longeur de 1000 et est plus large que la zone de dessin (800).

La balise mpath

La balise animateMotion peut contenir la balise mpath. Cette dernière balise fait référence à un chemin préalablement défini.
Ci-dessous la terre tourne autour du soleil.

Le code correspondant du fichier SVG

La version brute de ce fichier (soleil.svg) a été produit par Inkscape.
J'ai dessiné l'orbite de la terre avec une ellipse. Mais l'argument de la balise mpath est obligatoirement un chemin ... Donc l'astuce consiste à convertir la forme ellipse en chemin.
Puis via NotePad j'ai inséré une image directement à partir d'un site (mozillademos) et j'ai ensuite demandé que cet objet SVG se déplace sur le chemin elliptique.
J'ai aussi optimisé le code produit par Inkscape (réduire le nombre de décimales, supprimer des attributs de balise, modifier les ID,etc.)
Ci-dessous le code optimisé.

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90%" height="auto" viewBox="0 0 240 160" > <defs> <filter id="flou" > <feGaussianBlur stdDeviation="2" /> </filter> </defs> <g transform="translate(0,-138)"> <rect style="fill:black;" width="240" height="160" x="0" y="138" /> <ellipse style="fill:yellow;filter:url(#flou)" cx="129" cy="219" rx="20" ry="20" /> <path style="fill:none; stroke:none;" d="M 227.52,219.56 A 100.79,45.67 0 0 1 126.73,265.23 100.79,45.67 0 0 1 25.94,219.56 100.79,45.67 0 0 1 126.73,173.89 100.79,45.67 0 0 1 227.52,219.56 Z" id="orbite" /> <!-- code rajouté --> <image xlink:href ='https://mdn.mozillademos.org/files/1429/Canvas_earth.png' width="10" height="10" > <animateMotion begin="0s" dur="24s" repeatCount="indefinite" > <mpath xlink:href ="#orbite" /> </animateMotion> </image> </g> </svg>

J'ai inséré une image matricielle directement à partir d'un site. Donc inutile d'installer cette image sur le serveur. Mais revers de la médaille, pour que cette animation fonctionne il faut une connexion internet.
Le chemin est identifié orbite
La balise mpath a pour attribut xlink:href avec pour valeur l'ID du chemin

L'attribut rotate

La balise animateMotion peut contenir l'attribut rotate avec la valeur auto afin que l'objet qui se déplace le long d'un chemin soit toujours perpendiculaire à la pente. La mer déchaînée : forme fermée remplie de vert foncé et floutée Bateaux sur la mer

La partie defs du code SVG (extraits)

A vous de retrouver les balises ad hoc !

<svg width="90%" height="auto" viewBox ="0 0 600 400" style = 'background : grey ;' > <defs> <filter id="flou"> <feGaussianBlur stdDeviation="3" /> </filter> <g id ="bateau"> <... x = '4' y = '-10' width = '20' height = '5' fill = 'white' /> <... x = '13' y = '-15' width = '4' height = '5' fill = 'black'/> </g> <g id ="bateau_rouge" > <... xlink:href ="#bateau" /> <... points = "0,5 28,5 32,-5, -4,-5" fill = 'red'/> </g> <g id ="bateau_marine"> <... xlink:href ="#bateau" /> <... points = "0,5 28,5 32,-5, -4,-5" fill = 'navy'/> </g> <... d = "M 0,200 c 200,-200 400,200 600,0" id ="cap" /> </defs>

On définit un modèle identifié bateau (en fait le pont et la cheminée du bateau).
A partir du modèle bateau on définit les modèles bateau_rouge et bateau_marine. Il suffit à chaque fois de rajouter seulement la coque.
On définit aussi un chemin identifié cap (cap suivi par les navires) qui est une courbe de Bézier cubique.

Partie clonage et animation des clones (extraits)

A vous de compléter !

<desc>La mer déchaînée : forme fermée remplie de vert foncé</desc> <path id = 'mer' d="M 0,200 c 200,-200 400,200 600,0 v 200 h -600 z " fill = 'darkseagreen' filter ="url(#flou)"/> <desc>Bateaux sur la mer</desc> <use xlink:href ="#bateau_rouge" > <animateMotion rotate="auto" begin="0s" dur="24s" repeatCount="indefinite"> <mpath xlink:href =... /> </animateMotion> </use> <use xlink:href ="#bateau_marine" > <animateMotion rotate="auto" begin="4s" dur="20s" repeatCount="indefinite"> <mpath xlink:href =... /> </animateMotion> </use> </svg>

On dessine deux navires en clonant les modèles bateau_rouge et bateau_marine et on les anime grâce au conteneur animateMotion contenant la balise mpath et qui fait référence au chemin route (on devrait plutôt dire cap ...).
Le bateau doit rester perpendiculaire face à la pente. Il suffit d'ajouter à la balise animateMotion l'attribut rotate avec la valeur auto.

La mer est un autre chemin (mais fermé) et rempli de la couleur "darkseagreen" et bénéficiant d'un floutage (filtre identifié: flou).
Retour menu