◆ Portail Antalaha

Bibliothèques › Zdog

Référence de l'API Zdog

Classes

L'API de Zdog consiste principalement à créer et à utiliser des instances de ses classes.

let illo = new Zdog.Illustration({
  element: '.zdog-canvas',
});

let anchor = new Zdog.Anchor({
  addTo: illo,
  translate: { y: 10 },
});

let rect = new Zdog.Rect({
  addTo: anchor,
});

illo.updateRenderGraph();

Propriétés

Définissez les propriétés initiales avec un objet.

let rect = new Zdog.Rect({
  addTo: illo,
  width: 80,
  height: 60,
  rotate: { y: -2 },
  color: '#E62',
});

Lisez et modifiez ensuite les propriétés sur l'instance retournée.

// lire une option
console.log( rect.rotate.y );
// => -2

// modifier une option
rect.rotate.y = 3;

Héritage

Certaines classes de Zdog héritent des fonctionnalités d'autres classes. Par exemple, Rect hérite de Shape, et Shape hérite d'Anchor. Cela signifie que Rect peut utiliser toutes les propriétés et méthodes de Shape et d'Anchor.

Anchor

Un élément qui peut être ajouté à un autre élément, et auquel d'autres éléments peuvent être ajoutés.

Anchor est la super-classe de toutes les classes d'éléments et de formes : Shape, Group, Illustration, Rect, Ellipse, Box, etc. Tous les éléments qui peuvent être ajoutés à une scène Zdog se comportent comme des Anchor. Toutes les classes d'éléments peuvent utiliser les propriétés et méthodes d'Anchor.

La classe Anchor elle-même est un élément invisible. Les ancres sont utiles pour regrouper des formes liées et les transformer ensemble.

let anchor = new Zdog.Anchor({
  // options
});

addTo

Ajoute l'élément à un élément parent.

addTo: illo
// ajouter l'ancre à illo
let anchor = new Zdog.Anchor({
  addTo: illo,
});
// ajouter un triangle à l'ancre
let triangle = new Zdog.Shape({
  addTo: anchor,
  translate: { z: 40 },
  // ..
});
// ajouter un cercle à l'ancre
let circle = new Zdog.Ellipse({
  addTo: anchor,
  translate: { z: -40 },
  // ..
});

Des formes peuvent être ajoutées comme enfants d'autres formes. Une forme enfant est positionnée par rapport à son parent.

let zCircle = new Zdog.Ellipse({
  addTo: illo,
  translate: { z: 40 }, // z +40 par rapport à illo
  // ...
});

let xRect = new Zdog.Rect({
  addTo: zCircle,
  translate: { x: 40 }, // x +40 par rapport à zCircle
  // ...
});

let yTri = new Zdog.Polygon({
  addTo: xRect,
  translate: { y: -60 }, // y -60 par rapport à xRect
  // ...
});

translate

Positionne l'élément. À définir avec un Vector.

translate: { x: 20, y: -40 }
// déplace de 20 px vers la droite et de 40 px vers le haut

rotate

Fait pivoter l'élément. À définir avec un Vector pour faire pivoter l'élément autour de l'axe correspondant.

rotate: { x: Zdog.TAU/8 }
// rotation autour de l'axe horizontal
rotate: { y: Zdog.TAU/8 }
// rotation autour de l'axe vertical
rotate: { z: Zdog.TAU/8 }
// rotation autour de l'axe z

scale

Agrandit ou réduit la géométrie de l'élément. scale ne met pas stroke à l'échelle.

Définissez scale avec un nombre pour appliquer la même échelle à x, y et z.

scale: 2
// agrandit toutes les coordonnées de 200 %

Définissez scale avec un Vector pour une échelle propre à chaque coordonnée.

scale: { x: 0.5, y: 1.5 }
// échelle x 50 %, y 150 %

copy()

Copie un élément. copy() copie uniquement l'élément, pas son graphe d'éléments descendants. Utilisez copyGraph() pour copier l'élément et son graphe.

let ellipse = new Zdog.Ellipse({
  addTo: illo,
  diameter: 40,
  stroke: 10,
  color: '#636',
});

// copie de l'ellipse, avec des options modifiées
ellipse.copy({
  translate: { x: 60 },
  color: '#E62',
});

copyGraph()

Copie l'élément et ses éléments descendants.

let anchor = new Zdog.Anchor({
  addTo: illo,
});
new Zdog.Ellipse({
  addTo: anchor,
  diameter: 40,
  stroke: 10,
  color: '#636',
});

// copie l'ancre et l'ellipse qu'elle contient
anchor.copyGraph({
  translate: { x: 60 },
});

addChild()

Ajoute un élément enfant. addChild() est utile pour déplacer un élément enfant vers un nouveau parent, ou pour créer un élément sans addTo.

let anchor = new Zdog.Anchor({
  // ...
});

let shape = new Zdog.Shape({
  // pas de addTo
});
// ajouter la forme à l'ancre
anchor.addChild( shape );

removeChild()

Retire un élément enfant.

let shape = new Zdog.Shape({
  addTo: anchor,
});

anchor.removeChild( shape );

remove()

Retire l'élément de son parent.

let shape = new Zdog.Shape({
  addTo: anchor,
});

shape.remove();

updateGraph()

Met à jour l'élément et tout son graphe d'éléments descendants afin qu'ils soient prêts à être dessinés. Utile pour le rendu sans Illustration.

anchor.updateGraph();

renderGraphCanvas()

Dessine l'élément et tous ses éléments descendants sur un élément <canvas>. Utile pour le rendu sans Illustration.

anchor.renderGraphCanvas( ctx );
  • ctx : CanvasRenderingContext2D
let canvas = document.querySelector('.zdog-canvas');
let ctx = canvas.getContext('2d');

let scene = new Anchor();
// ajouter quelques formes...

scene.updateGraph();
// dessiner sur le canvas
scene.renderGraphCanvas( ctx );

renderGraphSvg()

Dessine l'élément et tous ses éléments descendants dans un élément SVG. Utile pour le rendu sans Illustration.

anchor.renderGraphSvg( element );
  • element : un élément conteneur SVG comme <svg> ou <g>.
let svg = document.querySelector('.zdog-svg');

let scene = new Anchor({...});
// ajouter quelques formes...

scene.updateGraph();
// dessiner dans le SVG
scene.renderGraphSvg( svg );

normalizeRotate()

Ramène les valeurs x, y et z de rotate entre 0 et TAU (rotation « circulaire »).

Shape

Une forme visible. Shape est la super-classe de toutes les classes de formes : Rect, Ellipse, Cone, etc. Toutes les classes de formes peuvent utiliser les options et méthodes de Shape.

color

Définit la couleur du trait et du remplissage de la forme. Accepte toute chaîne de couleur : code hexadécimal, rgb(), hsla(), etc. Valeur par défaut : color: '#333'.

color: '#E62'

stroke

Dessine le trait de la forme et définit son épaisseur. Valeur par défaut : stroke: 1.

stroke: 30

Définissez stroke à 0 ou false pour le désactiver.

// dessiner uniquement le remplissage
stroke: false,
fill: true,

fill

Dessine l'aire intérieure de la forme. Désactivé par défaut : fill: false.

fill: true

closed

Ferme le tracé en reliant le dernier point au premier. Activé par défaut : closed: true.

closed: false

visible

Affiche ou masque la forme. N'affecte pas les éléments enfants. Activé par défaut : visible: true.

backface

Affiche ou masque la forme lorsque sa face arrière est visible. Activé par défaut : backface: true.

Définissez backface: false pour masquer la forme lorsque sa face arrière est visible.

backface: false

Définissez backface avec une couleur pour changer la couleur de la forme lorsque sa face arrière est visible.

backface: "#636"

front

Un Vector servant à déterminer où se trouve l'avant de la forme. Utile pour modifier le fonctionnement de backface sur des Shape personnalisées. Valeur par défaut : front: { z: 1 }.

updatePath()

Met à jour le tracé de la forme. Appelez updatePath() après avoir modifié un point du tracé d'une Shape, la largeur ou la hauteur d'un Rect, etc.

let triangle = new Zdog.Shape({...});
// obtenir le premier point du tracé
let trianglePoint = triangle.path[0];
let dragStartX, dragStartY;

// glisser pour modifier le point du tracé
new Zdog.Dragger({
  onDragStart: function() {
    dragStartX = trianglePoint.x;
    dragStartY = trianglePoint.y;
  },
  onDragMove: function( pointer, moveX, moveY ) {
    trianglePoint.x = dragStartX + moveX;
    trianglePoint.y = dragStartY + moveY;
    // le point du tracé a changé : updatePath() applique la modification
    triangle.updatePath();
  },
});

Group

Un élément avec un ordre de rendu séparé. Hérite d'Anchor.

Utilisez un Group pour contrôler l'ordre de rendu. Les formes sont dessinées dans l'ordre où elles sont ajoutées au Group. Les Group sont utiles pour positionner des formes à l'intérieur d'autres formes, comme des fenêtres dans des murs ou des pupilles dans des yeux.

// dessiner les formes dans l'ordre d'ajout
var eyeGroup = new Zdog.Group({
  addTo: illo,
  translate: { z: 20 },
});
// d'abord le blanc de l'œil
new Zdog.Ellipse({
  addTo: eyeGroup,
  width: 160,
  height: 80,
  // ...
});
// puis l'iris
let iris = new Zdog.Ellipse({
  addTo: eyeGroup,
  diameter: 70,
  // ...
});
// puis la pupille
iris.copy({
  diameter: 30,
  color: '#636',
});
// le reflet en dernier, au premier plan
iris.copy({
  diameter: 30,
  translate: { x: 15, y: -15 },
  color: 'white',
});

visible

Affiche ou masque le groupe, y compris tous les éléments enfants du groupe. Shape.visible n'affiche ou ne masque que l'élément lui-même. Activé par défaut : visible: true.

updateSort

Met à jour l'ordre de rendu des éléments enfants du groupe.

Désactivé par défaut : updateSort: false. Les éléments enfants d'un groupe sont dessinés dans l'ordre où ils ont été ajoutés au Group.

Dragger

Suit les interactions de glissement via les événements de pointeur. Illustration hérite de Dragger, ce qui active dragRotate et l'usage des fonctions de rappel onDrag.

La classe Dragger seule est utile pour des interactions de glissement en dehors de Illustration.dragRotate ou pour le rendu sans Illustration. Consultez updatePath pour une autre démo de Dragger.

// utiliser Dragger pour faire pivoter des formes séparément
let circle = new Zdog.Ellipse({...});
let triangle = new Zdog.Shape({...});
// variables pour la rotation par glissement
let viewRotation = new Zdog.Vector();
let dragStartRX, dragStartRY;

new Zdog.Dragger({
  startElement: illo.element,
  onDragStart: function() {
    // mettre en évidence au début du glissement
    circle.color = '#C25';
    triangle.color = '#EA0';
    // mémoriser la rotation
    dragStartRX = viewRotation.x;
    dragStartRY = viewRotation.y;
  },
  onDragMove: function( pointer, moveX, moveY ) {
    // déplacer la rotation
    let moveRX = moveY / illo.width * Zdog.TAU * -1;
    let moveRY = moveX / illo.width * Zdog.TAU * -1;
    viewRotation.x = dragStartRX + moveRX;
    viewRotation.y = dragStartRY + moveRY;
  },
  onDragEnd: function() {
    // retirer les couleurs de mise en évidence à la fin du glissement
    circle.color = '#636';
    triangle.color = '#E62';
  },
});

function animate() {
  // faire pivoter les formes
  circle.rotate.set( viewRotation );
  triangle.rotate.set( viewRotation );
  illo.updateRenderGraph();
  requestAnimationFrame( animate );
}
animate();

startElement

L'élément sur lequel démarre le glissement, lors de l'événement initial mousedown, pointerdown ou touchstart.

// définir avec une chaîne de sélecteur
startElement: '.zdog-canvas'

// définir avec un Element
startElement: document.querySelector('.zdog-canvas')

onDragStart

Fonction de rappel déclenchée au début du glissement, lors de l'événement initial mousedown, pointerdown ou touchstart.

onDragStart: function( pointer ) {
  console.log(`Glissement démarré en ${pointer.pageX}, ${pointer.pageY}`);
}
  • pointer : l'objet Event ou Touch, avec .pageX et .pageY.

onDragMove

Fonction de rappel déclenchée lorsque le glissement se déplace, lors d'un événement mousemove, pointermove ou touchmove.

onDragMove: function( pointer, moveX, moveY ) {
  console.log(`Glissement déplacé de ${moveX}, ${moveY}`);
}
  • pointer : l'objet Event ou Touch, avec .pageX et .pageY.
  • moveX : distance horizontale parcourue depuis la position de départ du glissement.
  • moveY : distance verticale parcourue depuis la position de départ du glissement.

onDragEnd

Fonction de rappel déclenchée à la fin du glissement, lors de l'événement mouseup, pointerup ou touchend.

onDragEnd: function() {
  console.log('Glissement terminé');
}

Illustration

Gère l'affichage et la rotation d'une scène sur un élément HTML. Hérite à la fois d'Anchor et de Dragger. Illustration remplit plusieurs rôles.

  • En tant qu'Anchor, elle sert d'élément de plus haut niveau auquel tous les autres éléments de la scène sont ajoutés.
  • Elle gère le rendu des éléments vers un élément HTML, soit un <canvas>, soit un <svg>.
  • Elle gère l'interaction de glissement permettant de faire pivoter un élément.
let illo = new Zdog.Illustration({
  element: '.zdog-canvas',
  dragRotate: true,
});
// ajouter des formes à l'Illustration
// triangle
new Zdog.Shape({
  addTo: illo,
  // ...
});
// cercle
new Zdog.Ellipse({
  addTo: illo,
  // ...
});
// animer
function animate() {
  illo.updateRenderGraph();
  requestAnimationFrame( animate );
}
animate();

element

L'élément HTML sur lequel dessiner, soit un <canvas>, soit un <svg>.

// définir avec une chaîne de sélecteur
element: '.zdog-canvas'

// définir avec un Element
element: document.querySelector('.zdog-canvas')

Illustration exige que la taille initiale de l'élément soit définie dans ses attributs width et height.

<canvas class="zdog-canvas" width="240" height="240"></canvas>

Avec un élément <canvas>, Illustration augmente la résolution du <canvas> pour les écrans à haute densité de pixels.

<canvas class="zdog-canvas" width="240" height="240"></canvas>
element: '.zdog-canvas'
<svg class="zdog-svg" width="240" height="240"></svg>
element: '.zdog-svg'

translate, rotate et scale

En tant qu'Anchor, vous pouvez appliquer les transformations translate, rotate et scale à l'Illustration.

Définissez rotate pour fixer la rotation initiale de la vue de la scène.

rotate: { y: Zdog.TAU/8 }
// rotation de 45°

zoom

Agrandit ou réduit la taille d'affichage du rendu. Alors que scale modifie la taille de la géométrie des éléments, zoom modifie la géométrie des éléments et la taille de stroke.

zoom: 1.5
// agrandit de 150 %
zoom: 0.5
// réduit à 50 % de la taille

centered

Centre la scène dans l'élément. Activé par défaut : centered: true.

centered: false
// positionne la scène en 0,0, dans le coin supérieur gauche

dragRotate

Active la rotation d'un élément par glissement.

Avec dragRotate activé, vous pouvez utiliser les fonctions onDrag de Dragger : onDragStart, onDragMove, onDragEnd.

Définissez dragRotate: true pour faire pivoter par glissement le graphe d'éléments de l'Illustration.

let illo = new Zdog.Illustration({
  dragRotate: true,
  // ...
});

let circle = new Zdog.Ellipse({
  addTo: illo,
  // ...
});
let triangle = new Zdog.Shape({
  addTo: illo,
  // ...
});

Définissez dragRotate avec un élément pour faire pivoter par glissement le graphe de cet élément.

let triangle = new Zdog.Shape({...});

let illo = new Zdog.Illustration({
  dragRotate: triangle,
  // ...
});
illo.addChild( triangle );

let circle = new Zdog.Ellipse({
  addTo: illo,
  // ...
});

resize

Active le redimensionnement fluide de l'élément.

Avec un élément <canvas>, Illustration redéfinit les attributs width et height pour qu'ils correspondent à la taille d'affichage de l'élément, afin d'obtenir un rendu net au pixel près.

Activez resize: true pour un redimensionnement fluide de l'élément.

<!-- définir la taille initiale et le rapport d'aspect -->
<canvas class="zdog-canvas" width="480" height="240"></canvas>
.zdog-canvas {
  display: block;
  width: 100%;
}
resize: true

Avec un élément <svg>, Illustration supprime les attributs width et height : le <svg> se met alors à l'échelle proportionnellement et remplit la largeur de son élément parent, comme une <img> avec width: 100%.

<svg class="zdog-svg" width="480" height="240"></svg>
resize: true

Définissez resize: 'fullscreen' pour adapter l'élément à la taille de la fenêtre du navigateur. Voir la démo plein écran sur CodePen.

resize: 'fullscreen'
.zdog-canvas {
  width: 100%;
  height: 100%;
}

Pour un <canvas>, définissez une largeur et une hauteur CSS de 100%. Zdog agrandit le canvas pour correspondre au ratio de pixels de l'appareil, puis le CSS 100% le ramène à la taille d'affichage, ce qui procure une densité de pixels plus élevée.

onResize

Une fonction déclenchée lorsque l'élément est redimensionné. Nécessite que resize soit activé.

onResize: function( width, height ) {
  console.log(`L'élément de l'illo mesure ${width} x ${height}`);
}

Utilisez onResize pour ajuster zoom proportionnellement.

resize: true,
onResize: function( width ) {
  // ajuster le zoom
  this.zoom = width / 400;
},

onPrerender

Fonction déclenchée avant le rendu.

onPrerender: function( context ) {
  // ...
}
  • context : le contexte de rendu. Pour un <canvas>, le CanvasRenderingContext2D ; pour un <svg>, l'élément <svg>.
// avec <canvas>
onPrerender: function( ctx ) {
  // dessiner des lignes d'axes
  ctx.fillStyle = '#EA0';
  // avec centered activé, 0,0 est le centre du canvas
  ctx.fillRect( -1, -120, 2, 240 );
  ctx.fillRect( -120, -1, 240, 2 );
},

renderGraph()

Dessine un élément et son graphe dans l'élément de l'Illustration.

Appelez .renderGraph() pour dessiner le graphe d'éléments de l'Illustration.

illo.renderGraph()

Passez un élément pour dessiner cet élément.

illo.renderGraph( scene )

updateRenderGraph()

Combine les méthodes updateGraph() et renderGraph() pour vous économiser une ligne de code. Met à jour et dessine un élément et son graphe dans l'élément de l'Illustration.

Appelez .updateRenderGraph() pour dessiner le graphe d'éléments de l'Illustration.

illo.updateRenderGraph()

Passez un élément pour dessiner cet élément.

illo.updateRenderGraph( scene )

setSize()

Définit la taille de l'élément.

illo.setSize( width, height )

Vector

Un vecteur 3D avec des coordonnées x, y et z.

Créez un Vector en lui passant un objet vecteur ou un autre Vector.

let position = new Zdog.Vector({ x: 1, y: 0, z: 2 });

Zdog utilise des Vector pour les positions dans l'espace 3D et pour les rotations.

// position
let position = new Zdog.Vector({ x: 1, y: -2, z: 3 });
// => 1 vers la droite, 2 vers le haut, 3 plus près

Pour une rotation, les valeurs des coordonnées servent d'angle autour de l'axe correspondant.

let rotation = new Zdog.Vector({ y: Zdog.TAU/4 });
// => quart de tour autour de l'axe vertical y

Objets vecteurs

Un objet vecteur est un simple objet JavaScript avec des propriétés de coordonnées x, y et z. Ces propriétés sont facultatives : elles valent 0 par défaut si elles ne sont pas définies. Vous n'avez donc à définir que les valeurs non nulles.

new Zdog.Vector({ x: 1, z: 2 }) // => { x: 1, y: 0, z: 2 }
new Zdog.Vector({ y: 3 })       // => { x: 0, y: 3, z: 0 }
new Zdog.Vector({})             // => { x: 0, y: 0, z: 0 }

let position = new Zdog.Vector({ x: 4 });
// => { x: 4, y: 0, z: 0 }
position.add({ y: 5 });
// => { x: 4, y: 5, z: 0 }

Un objet vecteur est différent d'une instance de la classe Vector.

// ne fonctionne pas, ce n'est qu'un Object
{ x: 1 }.add({ y: 2 });

// fonctionne, c'est un Vector
new Zdog.Vector({ x: 1 }).add({ y: 2 });

set()

Définit les coordonnées x, y, z.

vec.set({ x: 1, z: 2 })
// => { x: 1, y: 0, z: 2 }

copy()

Retourne un nouveau Vector avec les coordonnées x, y et z copiées. La plupart des méthodes de Vector sont mutables : elles modifient les coordonnées du vecteur. Utilisez .copy() pour travailler avec un vecteur tout en préservant l'original.

let positionA = new Zdog.Vector({ x: 1, z: 2 });
let positionB = positionA.copy();

positionB.add({ x: 3 });
// => { x: 4, y: 0, z: 2 }
positionA
// => { x: 1, y: 0, z: 2 }

add()

Additionne les valeurs des coordonnées x, y, z.

let position = new Zdog.Vector({ x: 1, z: 2 });
position.add({ x: 3, y: 4 });
// => { x: 4, y: 5, z: 2 }

subtract()

Soustrait les valeurs des coordonnées x, y, z.

let position = new Zdog.Vector({ x: 1, z: 2 });
position.subtract({ x: 3, y: 4 });
// => { x: -2, y: -4, z: 2 }

multiply()

Multiplie les valeurs des coordonnées x, y, z.

let position = new Zdog.Vector({ x: 2, z: 3 });
position.multiply({ x: 3, y: 4, z: 5 });
// => { x: 6, y: 0, z: 15 }

.multiply() accepte aussi un nombre pour multiplier toutes les coordonnées par la même valeur.

let position = new Zdog.Vector({ x: 2, z: 3 });
position.multiply( 4 );
// => { x: 8, y: 0, z: 12 }

rotate()

vector.rotate( rotation );

Fait pivoter un vecteur de position à partir d'un objet vecteur de rotation rotation.

let position = new Zdog.Vector({ x: 1, y: 2 });
// rotation de 90° dans le sens horaire
position.rotate({ z: Zdog.TAU/4 });
// => { x: -2, y: 1, z: 0 }

magnitude()

Retourne la longueur totale du vecteur.

let position = new Zdog.Vector({ x: 6, y: 8 });
let mag = position.magnitude();
// => 10

lerp()

vector.lerp( point, alpha );

Interpole linéairement le vecteur vers point, où alpha est un pourcentage de la distance entre le vecteur et point.

let position = new Zdog.Vector({ x: 2, y: 4 });
// interpoler à 75 % vers 6,8,0
position.lerp( { x: 6, y: 8 }, 0.75 );
// => { x: 5, y: 7, z: 0 }

Utilities

Zdog inclut quelques constantes et méthodes pour faciliter les calculs mathématiques et les animations.

TAU

Zdog.TAU // => 6.28318

Une rotation complète en radians, soit Math.PI * 2. TAU est plus intuitif que PI, car TAU correspond directement à un tour complet.

const TAU = Zdog.TAU; // constante plus lisible

rotate: { y: TAU/4 } // /4 = quart de tour
rotate: { y: TAU/2 } // /2 = demi-tour
rotate: { y: TAU*3 } // *3 = 3 tours complets

easeInOut()

Applique une accélération puis décélération (easing « in-out »). Utile pour l'animation.

let easeAlpha = Zdog.easeInOut( alpha, power );
  • alpha : un nombre de 0 à 1.
  • power : la puissance exponentielle de la courbe d'easing. Valeur par défaut : 2.
let ticker = 0;
let cycleCount = 150;

function animate() {
  let progress = ticker / cycleCount;
  // appliquer l'easing à la rotation
  let tween = Zdog.easeInOut( progress % 1, 3 );
  illo.rotate.y = tween * Zdog.TAU;
  ticker++;

  illo.updateRenderGraph();
  requestAnimationFrame( animate );
}
animate();

extend()

Zdog.extend( a, b )

Copie les propriétés de l'objet b sur l'objet a.

let optionsA = { stroke: 4, fill: true };
let optionsB = { color: '#EA0', fill: false };

Zdog.extend( optionsA, optionsB );
// optionsA = { stroke: 4, color: '#EA0', fill: false }

lerp()

Zdog.lerp( a, b, alpha )

Interpolation linéaire entre les valeurs a et b, où alpha est un pourcentage sous forme décimale.

// à 75 % du chemin entre 20 et 40
Zdog.lerp( 20, 40, 0.75 );
// => 35

modulo()

Zdog.modulo( a, b )

Retourne le modulo (valeur « circulaire ») de a selon b.

// Il est 8 h. Quelle heure sera-t-il dans 18 heures ?
let later = Zdog.modulo( 8 + 18, 24 )
// => 2, soit 2 h du matin

// Il est 8 h. Quelle heure était-il il y a 15 heures ?
let earlier = Zdog.modulo( 8 - 15, 24 )
// => 17, soit 17 h (format 24 h)
earlier = Zdog.modulo( earlier, 12 )
// => 5 h de l'après-midi

// Pourquoi ne pas utiliser l'opérateur % ?
earlier = ( 8 - 15 ) % 24;
// => -7, aïe. % retourne des restes, qui peuvent être négatifs

Traduction française de la documentation de Zdog (licence MIT) – https://zzz.dog