Files
doc-svg/examen3/solution3.md

118 lines
3.7 KiB
Markdown
Raw Permalink Normal View History

2025-10-30 13:08:21 +01:00
---
layout: layouts/page.njk
title: Solution de l'évaluation SVG n° 3
---
Ajouter le svg de la carte de l'Europe dans la page. Ajouter une propriété `viewbox` pour [recadrer](../../zone/) la carte.
```svg
<svg width="990.133" height="797.822" xmlns="http://www.w3.org/2000/svg" viewbox="155 215 445 380">
```
Ajouter un [symbole](../../bibliotheque/) dans un bloc de définition `defs`ne pas oublier le `viewbox` pour pouvoir le redimensionner plus tard
```svg
<defs>
<symbol id="plane" viewBox="0 0 800 800">
<path d="m 800,41.803859 q 0,49.821051 Z"/>
</symbol>
</defs>
```
Ajouter le symbole dans l'illustration. Appliquer deux [transformations](../../transformation) : une rotation de 45° et une translation pour aligner le nez de l'avion avec l'abscisse x=0
```svg
<use id="avion" x="0" href="#plane" width="10" height="10" transform="rotate(45) translate(-9 0)" />
```
Ajouter le [chemin](../../formes). Pour l'instant il ne contient qu'un point d'origine.
```svg
<path id="trajectoire" d="M0,0" fill="none" stroke-dasharray="5 5"
stroke-width="2" stroke="red"></path>
```
Attacher un événement `clic` sur les cercles.
```javascript
document.querySelectorAll("circle").forEach(ville => ville.addEventListener("click", evt => {
```
La fonction pour calculer la distance euclidienne entre 2 points
```javascript
function getDistance(x1, y1, x2, y2) {
return Math.sqrt( Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2) );
}
```
Déclaration des variables globales. L'élément svg avion, le cercle de départ, le chemin tel qu'il sera construit et la durée totale de l'animation
```javascript
let avion = document.querySelector("#avion");
let depart;
let path = "";
let dur = 0;
```
Lors du clic, si le départ n'est pas encore défini, le définir et commencer le chemin par une commande **M** suivi d'une commande **L** pour les segments à venir
```javascript
if (depart)
{ }
else {
depart = evt.currentTarget;
path = `M${depart.getAttribute("cx")},${depart.getAttribute("cy")}L` ;
}
```
Si il y a deja un départ. Prendre le point d'arrivée, calculer la longueur du segment (depart et arrivée). Calculer la durée totale en divisant par 20 le nombre de pixels de distance. Ajouter le point d'arrivée au chemin. Fixer l'arrivée comme le _prochain_ départ.
```javascript
if (depart)
{
let arrivee = evt.currentTarget;
let longueur = getDistance(arrivee.getAttribute("cx"), arrivee.getAttribute("cy"),
depart.getAttribute("cx"), depart.getAttribute("cy"));
dur += longueur / 20;
path += ` ${arrivee.getAttribute("cx")},${arrivee.getAttribute("cy")}`;
depart = arrivee;
}
```
Ajouter une [animation](../../animation) de chemin `animateMotion` avec comme référence la trajectoire.
```svg
<use id="avion" x="0" href="#plane" width="10" height="10" transform="rotate(45) translate(-9 0)" >
<animateMotion dur="5s" repeatCount="1" restart="whenNotActive" rotate="auto" fill="freeze">
<mpath href="#trajectoire"/>
</animateMotion>
</use>
```
Si une durée a été calculée. Appliquer le chemin `path` construit à l'élément trajectoire. Fixer aussi la durée de l'animation et démarrer l'animation
```javascript
if (dur)
{
let trajectoire = document.querySelector("#trajectoire");
trajectoire.setAttribute("d", path);
let anim = avion.querySelector("animateMotion");
anim.setAttribute("dur", `${dur}s`);
anim.beginElement();
}
```
Si il n'y a pas encore de durée, stopper l'animation.
```javascript
else
{
let anim = avion.querySelector("animateMotion");
anim.endElement();
}
```
<a href="../reponse3" download>télécharger</a> la solution
Voir la [solution](../reponse3)