Initiation au graphisme avec eFORTH pour le web

publication: 14 mars 2023 / mis à jour 20 mars 2023

Read this page in english

 


Comprendre l'environnement graphique

eFORTH utilise l'élément HTML <canvas> pour gérer des formes graphiques. Cet élément est activé en exécutant le mot gr qui est défini dans le vocabulaire web:

web gr 
300 200 window 

On définit ensuite la taille de cet élément en utilisant window. Dans notre exemple, ceci definit une fenêtre graphique de 600 pixels de large par 400 pixels de hauteur.

Dans la suite de cet article, il est convenu que tous nos exemples commeceront avec ces deux lignes d'initialisation sans qu'il soit nécessaire de les réécrire pour chaque exemple.

Le système de coordonnées de <canvas> commence toujours à l'angle supérieur gauche. Il est défini en points. Dans notre cas, chaque point correspondra à un pixel. Cette échelle peut être modifiée avec scale. Nous verrons l'utilisation de ce mot plus tard.

Notion de tracé et remplissage

Les fonctions graphiques associées à <canvas> sont simples, mais nécessitent une certaine méthode pour être efficaces.

Un tracé, c'est un chemin. On marque le début d'un tracé avec le mot beginPath. Puis un tracé est déterminé par sa couleur avec color!. Et enfin, on réalise le tracé avec moveTo et lineTo.

Le tracé s'achève avec stroke si on ne souhaite afficher que les traits du tracé:

$ff0000 constant red 
beginpath   red color!   10 150 moveTo 10 20 lineto   280 20 lineto stroke 

Pour réaliser un tracé plein, on remplace stroke par fill:

$ff0000 constant red 
$0000ff constant blue 
beginpath   red color!   10 150 moveTo   10  20 lineto   280 20 lineto stroke 
beginpath  blue color!   10 180 moveTo  280 180 lineto   280 40 lineto fill 

La couleur peut aussi être définie en fin de tracé. Dans ce cas, elle s'appliquera à tout le tracé depuis l'exécution de beginPath:

$ff0000 constant red 
$0000ff constant blue 
 
web gr 
400 300 window 
 
beginpath   10 150 moveTo   10  20 lineto   280 20 lineto 
red color!   stroke 
4 linewidth 
beginpath   10 180 moveTo  280 180 lineto   280 40 lineto 
blue color!   fill 
 red color!   stroke 

Ici, ce sont les deux dernières lignes de code qui nous intéressent. On exécute d'abord le tracé de notre figure, puis c'est seulement après ce tracé qu'on sélectionne la couleur de fond avec blue color! fill et ensuite la couleur du contour avec red color! stroke.

La coloration du contour n'apparait que sur la partie de contour tracée.

Pour fermer un tracé, on peut utiliser le mot closePath. Voici comment définir ce mot qui n'existe pas d'origine dans le vocabulaire web:

web definitions 
JSWORD: closePath { } 
    context.ctx.closePath(); 
~ 
forth definitions 

Et maintenant, on peut modifier le code de traçage:

4 linewidth 
beginpath   10 180 moveTo  280 180 lineto   280 40 lineto closePath 
blue color!   fill 
 red color!   stroke 

Rotations et translations

Le système de coordonnées de canvas commence dans l'angle supérieur gauche de notre fenêtre graphique. Les coordonnées x soint croissantes vers la droite, les coordonnées y sont croissantes vers le bas.

Ceci est vrai tant que l'on n'effecture aucune transformation. Pour bien assimiler ceci, nous allons tracer une vraie grille dans l'espace de travail:

600 constant gridWidth 
300 constant gridHeight 
 10 constant gridStep 
 
$cfcfcf constant lightGrey 
$afafff constant lightBlue 
 
web 
: drawGrid ( -- ) 
    \ draw vertical lines 
    gridWidth 0 do 
        beginPath 
        i 0 moveTo 
        i gridHeight lineTo 
        stroke 
    gridStep +loop 
    \ draw horizontal lines 
    gridHeight 0 do 
        beginPath 
        0 i moveTo 
        gridWidth i lineTo 
        stroke 
    gridStep +loop 
  ; 
 
web gr 
gridWidth gridHeight window 
lightGrey color! drawGrid 

Nous allons effectuer une rotation de 30°. La rotation s'effectue dans le sens horaire et s'applique depuis l'axe horizontal supérieur et au point de départ de traçage qui est dans l'angle supérieur gauche:

Avec eFORTH, on utilise le mot rotate qui a besoin de deux paramètres:

Pour effectuer une rotation de 90 degrés, on peut taper 90 360 rotate. Mais on peut aussi taper 1 4 rotate qui aura exactement le même effet.

Nous allons effectuer une rotation de 30° et tracer une autre grille colorée en bleu clair:

web gr 
gridWidth gridHeight window 
lightGrey color! drawGrid 
1 12 rotate 
lightBlue color! drawGrid 

Mmmmmm.... très intéressant! Les tracés peuvent sortir de l'espace de travail sans faire planter eFORTH...

Voyons ce que ça donne si on trace un rectangle dans chacune de ces grilles:

: myBox ( color -- ) 
    color! 10 10 400 200 box 
  ; 
web gr 
gridWidth gridHeight window 
lightGrey color! drawGrid 
fullRed myBox 
1 12 rotate 
lightBlue color! drawGrid 
fullBlue myBox 

La rotation est cumulative. Pour faire tourner de trente autre degrés, on exécutera à nouveau 1 12 rotate.

La translation est réalisée par le mot translate. Ce mot a besoin de deux paramètres, x er y, indiquant le déplacement horizontal et vertical dans l'espace de travail:

web gr 
gridWidth gridHeight window 
lightGrey color! drawGrid 
fullRed myBox 
300 100 translate 
lightBlue color! drawGrid 
fullBlue myBox 

Une fois translate exécuté, le nouveau système de coordonnées est situé au point de destination de cette translation. Les translations et rotations sont cumulatives:

: myBox ( color -- ) 
    color! 10 10 400 200 box 
  ; 
 
: addTranslateRotate ( -- ) 
    50 0 translate 
    5 360 rotate 
  ; 
 
: myBoxes ( -- ) 
    12 for 
        aft 
            fullRed myBox 
            addTranslateRotate 
            fullBlue myBox 
            addTranslateRotate 
        then 
    next 
  ; 
web gr 
gridWidth gridHeight window 
lightGrey color! drawGrid 
myBoxes 

Cas pratique: tracé des heures d'une horloge

Voici un exemple pratique, le traçage des heures d'une pendule:

600 constant gridWidth 
300 constant gridHeight 
 10 constant gridStep 
 
gridHeight 2/ 90 100 */ value clockRadius 
gridHeight 2/ 10 /      value face_width 
 
$cfcfcf constant lightGrey 
$afafff constant lightBlue 
$ff0000 constant fullRed 
$0000ff constant fullBlue 
 
web 
: drawHrMin { size } 
    beginPath 
    clockRadius size 100 */ 0 moveTo 
    clockRadius 0 lineTo 
    stroke 
  ; 
 
\ draw hours 
: drawHours ( --) 
    fullBlue color! 
    face_width 3 5 */ lineWidth 
    12 0 do 
        1 12 rotate 
        85 drawHrMin 
    loop 
  ; 
 
web gr 
gridWidth gridHeight window 
lightGrey color! drawGrid 
gridWidth 2/ gridHeight 2/ translate 
drawHours 

Bonne programmation.


Legal: site web personnel sans commerce / personal site without seling