C'est fini ! Félicitations !

Voici donc le rendu final de l'API que nous aurons fait dans ce tutoriel :

background_color = "#000"; var maTortue = new Tortue(); maTortue.is_visible = false; var angle = 0; const SIDES = 6; function hexagonSpiral() { maTortue.pd(); for (var i = 0 ; i < 360 ; i++) { maTortue.color("hsl("+ (((i % SIDES) * (360 / SIDES))) +",75%,"+Math.round(100*i/360)+"%)"); maTortue.width(i/120 + 1); maTortue.forward(i); maTortue.left(Math.floor(360/SIDES) - 1); } maTortue.pu(); } function boucle() { angle = (angle + 1) % 360; maTortue.reset(); maTortue.right(angle); hexagonSpiral(); } setInterval(boucle, 5);

Remarquez que le < est devenu &lt; car le navigateur web a convertit le symbole pendant le chargement de la page.
Vous aurez donc une erreur en lancant le script tel quel...

Code de l'API téléchargeable :

Sur ce lien.

Code de l'API en clair

class TurtleElement extends HTMLElement { constructor() { // On laisse le navigateur comprendre qu'il s'agit d'une balise html super(); // On recupere le contenu de la balise et on l'efface var code = this.innerHTML; this.innerHTML = ""; // On crée un élément canvas var child = document.createElement("canvas"); child.id = 'screen'; child.height = this.getAttribute("canvas-height") || "400"; child.width = this.getAttribute("canvas-width") || "400"; child.style.display = "block"; this.appendChild(child); // On crée un élément textarea qui contient le code de départ child = document.createElement("textarea"); child.value = code; child.style.height = (this.getAttribute("textarea-height") || "100") + "px"; child.style.width = (this.getAttribute("textarea-width") || "400") + "px"; child.style.resize = "none"; child.style.color = "white"; child.style.backgroundColor = "black"; child.style.fontFamily = "monospace"; child.onkeydown = (event) => { switch (event.key) { case "Tab": var v = child.value, s = child.selectionStart, e = child.selectionEnd; child.value = v.substring(0, s) + ' ' + v.substring(e); child.selectionStart = child.selectionEnd = s + 4; return false; case "Enter": if (!event.shiftKey) { var code = child.value; child.value = ""; window.eval(code); // Where magic happens event.preventDefault(); return false; } break; } }; this.appendChild(child); } } customElements.define("turtle-js", TurtleElement); // Variables globales var screen = document.getElementById("screen"); var context = screen.getContext("2d"); var background_color = "#fff"; var tortues = new Array(); // Pour rafraichir l'ecran function rafraichir() { context.fillStyle = background_color; context.fillRect(0, 0, screen.width, screen.height); for (tortue of tortues) { if (tortue.show_drawing) { for (chemins of tortue.all_shapes) { context.strokeStyle = chemins.color; context.lineWidth = chemins.width; context.stroke(chemins); } } if (tortue.isvisible()) { tortue.blitturtle(tortue.turtle_color); } } } var taux_de_rafraichissement = setInterval(rafraichir, 1); function blitOnScreen () { for (tortue of tortues) { if (tortue.is_drawing) { tortue.pu(); tortue.pd(); } } } setInterval(blitOnScreen, 50); // Nouvel objet : class CheminTortue extends Path2D { constructor(old) { super(old); if (old !== undefined) { this.color = old.color; this.width = old.width } else { this.color = "#000"; this.width = 2; } } } // Notre tortue class Tortue { constructor() { // On définit les centres de l'écran this.center_x = Math.floor(screen.width / 2); this.center_y = Math.floor(screen.height / 2); // On pose la tortue au centre de l'écran this.x = this.center_x; this.y = this.center_y; // Variable d'état this.is_drawing = false; this.show_drawing = true; this.has_moved = false; this.angle = 0; this.is_visible = true; this.turtle_color = "black"; this.turtle_width = 2; // Chemins à stocker this.all_shapes = [new CheminTortue()]; tortues.push(this); } blitturtle(color) { context.fillStyle = color; context.beginPath(); context.moveTo(Math.round(this.x), Math.round(this.y)); context.lineTo(Math.round(this.x - 12 * Math.cos(Math.PI / 6 + Math.PI * (this.angle / 180))), Math.round(this.y + 12 * Math.sin(Math.PI / 6 + Math.PI * (this.angle / 180)))); context.lineTo(Math.round(this.x - 7 * Math.cos(Math.PI * (this.angle / 180))), Math.round(this.y + 7 * Math.sin(Math.PI * (this.angle / 180)))); context.lineTo(Math.round(this.x - 12 * Math.cos(Math.PI * (this.angle / 180) - Math.PI/6)), Math.round(this.y + 12 * Math.sin(Math.PI * (this.angle / 180) - Math.PI / 6))); context.closePath(); context.fill(); } showturtle() { this.is_visible = true; } st() { return this.showturtle(); } hideturtle() { this.is_visible = false; } ht() { return this.hideturtle(); } isvisible() { return this.is_visible; } pendown() { this.new_shape = new CheminTortue(); this.new_shape.color = this.turtle_color; this.new_shape.width = this.turtle_width; // Premier point du dessin this.new_shape.moveTo(Math.round(this.x), Math.round(this.y)); this.is_drawing = true; this.has_moved = false; } // Equivalents pd() { return this.pendown(); } down() { return this.pendown(); } penup() { // On ferme le chemin this.new_shape.closePath(); // On ajoute une copie du chemin crée pour éviter les bugs de reference this.all_shapes.push(new CheminTortue(this.new_shape)); this.is_drawing = false; this.has_moved = false; } // Equivalents pu() { return this.penup(); } up() { return this.penup(); } color(clr) { if (this.has_moved) { this.new_shape.closePath(); this.all_shapes.push(new CheminTortue(this.new_shape)); this.new_shape = new CheminTortue(); this.new_shape.moveTo(Math.round(this.x), Math.round(this.y)); } if (this.is_drawing) { this.new_shape.color = clr; } this.turtle_color = clr; this.has_moved = false; } width(wdt) { if (this.has_moved) { this.new_shape.closePath(); this.all_shapes.push(new CheminTortue(this.new_shape)); this.new_shape = new CheminTortue(); this.new_shape.moveTo(Math.round(this.x), Math.round(this.y)); } if (this.is_drawing) { this.new_shape.width = Math.floor(wdt); } this.turtle_width = wdt; this.has_moved = false; } reset() { this.clear(); this.color("#000"); this.width(2); this.x = this.center_x; this.y = this.center_y; this.angle = 0; } clear() { if (!this.is_drawing) { this.pendown(); } this.penup(); this.all_shapes = [new CheminTortue()]; } forward(len) { // On change de position this.x += len * Math.cos(Math.PI * (this.angle / 180)); this.y -= len * Math.sin(Math.PI * (this.angle / 180)); // On dessine la ligne if (this.is_drawing) { this.new_shape.lineTo(Math.round(this.x), Math.round(this.y)); this.has_moved = true; } } // Equivalents et opposés fd(len) { return this.forward(len); } backward(len) { this.angle = 180 + this.angle; this.forward(len); this.angle = this.angle - 180; } bk(len) { return this.backward(len); } back(len) { return this.backward(len); } goto(x, y) { this.x = x; this.y = y; // On dessine la ligne if (this.is_drawing) { this.new_shape.lineTo(Math.round(this.x), Math.round(this.y)); this.has_moved = true; } } left(angle) { // Modulo toujours positif this.angle = (((this.angle + angle) % 360) + 360) % 360; } // Equivalents et opposés lt(angle) { return this.left(angle); } right(angle) { return this.left(-angle); } rt(angle) { return this.left(-angle); } }