Logiciel libre de géométrie, d'analyse et de simulation multiplateforme par Yves Biton

Accueil Tutoriels Export html et LateX

Utiliser MathGraph32 en ligne et interagir avec la figure : Exemple 3 d’utilisation de l’API

modification vendredi 25 août 2023.


Avant de lire cet article, vous devez être familier avec le lancement d’une figure MathGraph32 avec son loader. Si vous ne l’êtes pas il est conseillé de consulter cet article.

Il est conseillé aussi de commencer par cet article.

Nous allons partir de la figure ci-dessous et agir sur cette figure avec le player MathGraph32 en utilisant l’API de MathGraph32.

L’API de MathGraph32 permet d’afficher une figure en ligne (player ou éditeur), de lui rajouter des objets et d’ajouter des écouteurs d’événements sur des objets de la figure.


Et voici ci-dessous le code HTML d’une page contenant la figure et le code qui va nous permettre d’agir sur cette page le code est documenté pour vous aider à comprendre comment cela fonctionne).

<!DOCTYPE html>
<html>
<head>
   <meta http-equiv="X-UA-Compatible" content="IE=9">
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta name="generator" content="MathGraph32"/>
   <title>Feuille de travail dynamique MathGraph32</title>
   <style type="text/css">
       svg {
           -webkit-user-select: none; /* Chrome all / Safari all */
           -moz-user-select: none; /* Firefox all */
           -ms-user-select: none; /* IE 10+ */
           -webkit-tap-highlight-color: transparent; /*Nécessaire sur ipad pour ne pas avoir de rectangle gris sélectionné lors des touch events */
       }
   </style>

</head>
<body>
<div id="mtg32div">
</div>
<!--<script type="text/javascript" src="https://www.mathgraph32.org/js/mtgLoad/mtgLoad.min.js"></script> -->
<script type="text/javascript" src="build/mtgLoad.module.js"></script>
<script type="application/javascript">
 (function autostart() {
   const svgOptions = {
     idSvg: "mtg32svg", width: "900", height: "500"
   }

   const mtgOptions = {
     fig: "TWF0aEdyYXBoSmF2YTEuMAAAABM+TMzNAAJmcv###wEA#wEAAAAAAAAAAAUeAAACygAAAQEAAAAAAAAAAQAAADb#####AAAAAQAKQ0NhbGNDb25zdAD#####AAJwaQAWMy4xNDE1OTI2NTM1ODk3OTMyMzg0Nv####8AAAABAApDQ29uc3RhbnRlQAkh+1RELRj#####AAAAAQAKQ1BvaW50QmFzZQD#####AAAAAAAOAAFPAMAoAAAAAAAAAAAAAAAAAAAAAAUAAUB0sAAAAAAAQHGdcKPXCj7#####AAAAAQAUQ0Ryb2l0ZURpcmVjdGlvbkZpeGUA#####wEAAAAADgAAAQAAAAEAAAABAT#wAAAAAAAA#####wAAAAEAD0NQb2ludExpZURyb2l0ZQD#####AAAAAAEOAAFJAMAYAAAAAAAAAAAAAAAAAAAAAAUAAUBB3vnbItDmAAAAAv####8AAAABAAlDRHJvaXRlQUIA#####wAAAAAAEAAAAQAAAAEAAAABAAAAA#####8AAAABABZDRHJvaXRlUGVycGVuZGljdWxhaXJlAP####8AAAAAAA4AAAEAAAABAAAAAQAAAAT#####AAAAAQAJQ0NlcmNsZU9BAP####8BAAAAAAAAAQAAAAEAAAAD#####wAAAAEAEENJbnREcm9pdGVDZXJjbGUA#####wAAAAUAAAAG#####wAAAAEAEENQb2ludExpZUJpcG9pbnQA#####wEAAAAADgAAAQAABQABAAAABwAAAAkA#####wAAAAABDgABSgDAKAAAAAAAAMAQAAAAAAAAAAAFAAIAAAAH#####wAAAAIAB0NSZXBlcmUA#####wDm5uYAA3JlcAABAAAAAQAAAAMAAAAJAQEAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAT#wAAAAAAAAAAAAAT#wAAAAAAAA#####wAAAAEACkNVbml0ZXhSZXAA#####wAEdW5pdAAAAAr#####AAAAAQALQ0hvbW90aGV0aWUA#####wAAAAH#####AAAAAQAKQ09wZXJhdGlvbgMAAAABP#AAAAAAAAD#####AAAAAQAPQ1Jlc3VsdGF0VmFsZXVyAAAAC#####8AAAABAAtDUG9pbnRJbWFnZQD#####AQAAAAAQAAJXIgEAAAEAAAAAAwAAAAz#####AAAAAQAJQ0xvbmd1ZXVyAP####8AAAABAAAADf####8AAAABAAdDQ2FsY3VsAP####8AB25iZ3JhZHgAAjIwAAAAAUA0AAAAAAAAAAAAEQD#####AAduYmdyYWR5AAIyMAAAAAFANAAAAAAAAP####8AAAABABRDSW1wbGVtZW50YXRpb25Qcm90bwD#####ABRHcmFkdWF0aW9uQXhlc1JlcGVyZQAAABsAAAAIAAAAAwAAAAoAAAAPAAAAEP####8AAAABABNDQWJzY2lzc2VPcmlnaW5lUmVwAAAAABEABWFic29yAAAACv####8AAAABABNDT3Jkb25uZWVPcmlnaW5lUmVwAAAAABEABW9yZG9yAAAACgAAAAsAAAAAEQAGdW5pdGV4AAAACv####8AAAABAApDVW5pdGV5UmVwAAAAABEABnVuaXRleQAAAAr#####AAAAAQAQQ1BvaW50RGFuc1JlcGVyZQAAAAARAAAAAAAOAAABAAAFAAAAAAoAAAAOAAAAEgAAAA4AAAATAAAAFgAAAAARAAAAAAAOAAABAAAFAAAAAAoAAAANAAAAAA4AAAASAAAADgAAABQAAAAOAAAAEwAAABYAAAAAEQAAAAAADgAAAQAABQAAAAAKAAAADgAAABIAAAANAAAAAA4AAAATAAAADgAAABUAAAAMAAAAABEAAAAWAAAADgAAAA8AAAAPAAAAABEAAAAAAA4AAAEAAAUAAAAAFwAAABkAAAAMAAAAABEAAAAWAAAADgAAABAAAAAPAAAAABEAAAAAAA4AAAEAAAUAAAAAGAAAABv#####AAAAAQAIQ1NlZ21lbnQAAAAAEQEAAAAAEAAAAQAAAAEAAAAXAAAAGgAAABcAAAAAEQEAAAAAEAAAAQAAAAEAAAAYAAAAHAAAAAQAAAAAEQEAAAAACwABVwDAFAAAAAAAAMA0AAAAAAAAAAAFAAE#3FZ4mrzfDgAAAB3#####AAAAAgAIQ01lc3VyZVgAAAAAEQAGeENvb3JkAAAACgAAAB8AAAARAAAAABEABWFic3cxAAZ4Q29vcmQAAAAOAAAAIP####8AAAACABJDTGlldU9iamV0UGFyUHRMaWUBAAAAEQBmZmYAAAAAAB8AAAAOAAAADwAAAB8AAAACAAAAHwAAAB8AAAARAAAAABEABWFic3cyAA0yKmFic29yLWFic3cxAAAADQEAAAANAgAAAAFAAAAAAAAAAAAAAA4AAAASAAAADgAAACEAAAAWAAAAABEBAAAAAAsAAAEAAAUAAAAACgAAAA4AAAAjAAAADgAAABMAAAAZAQAAABEAZmZmAAAAAAAkAAAADgAAAA8AAAAfAAAABQAAAB8AAAAgAAAAIQAAACMAAAAkAAAABAAAAAARAQAAAAALAAFSAEAgAAAAAAAAwCAAAAAAAAAAAAUAAT#RG06BtOgfAAAAHv####8AAAACAAhDTWVzdXJlWQAAAAARAAZ5Q29vcmQAAAAKAAAAJgAAABEAAAAAEQAFb3JkcjEABnlDb29yZAAAAA4AAAAnAAAAGQEAAAARAGZmZgAAAAAAJgAAAA4AAAAQAAAAJgAAAAIAAAAmAAAAJgAAABEAAAAAEQAFb3JkcjIADTIqb3Jkb3Itb3JkcjEAAAANAQAAAA0CAAAAAUAAAAAAAAAAAAAADgAAABMAAAAOAAAAKAAAABYAAAAAEQEAAAAACwAAAQAABQAAAAAKAAAADgAAABIAAAAOAAAAKgAAABkBAAAAEQBmZmYAAAAAACsAAAAOAAAAEAAAACYAAAAFAAAAJgAAACcAAAAoAAAAKgAAACv#####AAAAAgAMQ0NvbW1lbnRhaXJlAAAAABEBZmZmAAAAAAAAAAAAQBgAAAAAAAAAAAAAAB8LAAH###8AAAABAAAAAAAAAAEAAAAAAAAAAAALI1ZhbChhYnN3MSkAAAAZAQAAABEAZmZmAAAAAAAtAAAADgAAAA8AAAAfAAAABAAAAB8AAAAgAAAAIQAAAC0AAAAbAAAAABEBZmZmAAAAAAAAAAAAQBgAAAAAAAAAAAAAACQLAAH###8AAAABAAAAAAAAAAEAAAAAAAAAAAALI1ZhbChhYnN3MikAAAAZAQAAABEAZmZmAAAAAAAvAAAADgAAAA8AAAAfAAAABgAAAB8AAAAgAAAAIQAAACMAAAAkAAAALwAAABsAAAAAEQFmZmYAwCAAAAAAAAA#8AAAAAAAAAAAAAAAJgsAAf###wAAAAIAAAABAAAAAQAAAAAAAAAAAAsjVmFsKG9yZHIxKQAAABkBAAAAEQBmZmYAAAAAADEAAAAOAAAAEAAAACYAAAAEAAAAJgAAACcAAAAoAAAAMQAAABsAAAAAEQFmZmYAwBwAAAAAAAAAAAAAAAAAAAAAAAAAKwsAAf###wAAAAIAAAABAAAAAQAAAAAAAAAAAAsjVmFsKG9yZHIyKQAAABkBAAAAEQBmZmYAAAAAADMAAAAOAAAAEAAAACYAAAAGAAAAJgAAACcAAAAoAAAAKgAAACsAAAAz#####wAAAAEADUNQb2ludEJhc2VFbnQA#####wAAAAAAEAABTQAAAAAAAAAAAEAIAAAAAAAAAAABAAEAAAAKQBAAAAAAAABACAAAAAAAAAEBAAAADv##########",
     isEditable: false,
     loadApi: true
   }
   let app
   let polyCaptured = false
   let xmouse, ymouse // Coordonnées du pointeur souris
   mtgLoad("mtg32div", svgOptions, mtgOptions).then(
     (mtgApp) => {
       console.log("mtg32 App loaded", mtgApp)
       app = mtgApp
       addBoutonAndLatex()
     }
   ).catch(
     (error) => {
       if (error) console.error(error)
     }
   )

   function addBoutonAndLatex() {
     // La ligne ci-dessous est nécessaire pour le palyer au cas où il y aurait plusieurs figures MathGraph32 dans la page
     app.setApiDoc('mtg32svg')
     // On crée un affichage de texte. La propriété rep (tag du repère étant donnée) sa position sera donnée
     // dans le repère par x et y (sinon ce serait des coordonnées absolues dans le svg)
     app.addText({
       text: 'Retirer la liaison de N',
       rep: 'rep',
       x: -8,
       y: 7,
       transparent: false,
       backgroundColor: 'yellow',
       tag: 'txt1',
       border: '3D'
     })
     // On affecte à l'élément svg représentant ce texte un écouteur d'événement mousedone
     // qui appelle la fonction addPtsAndPoly
     app.addEltListener({
       elt: 'txt1',
       eventName: 'mousedown',
       callBack: suppressLink
     })
     // On crée les mesures des abscisses et ordonnées du point M
     app.addXMeasure({ a: 'M', rep: 'rep', nameCalc: 'xM'})
     app.addYMeasure({ a: 'M', rep: 'rep', nameCalc: 'yM'})
     // On crée un calcul ayant comme formule xM^2+yM^2
     app.addCalc({ nameCalc: 'long2', formula: 'xM^2+yM^2'})
     // On crée un affichage LaTeX dynamique affichant la valeur de long2 sous une racine carée au-dessus de M
     app.addLinkedLatex({latex: 'OM=\\sqrt{\\ForSimp{long2}}', a: 'M', color: 'maroon', transparent: false, vAlign: 'top', hAlign: 'center', offsetY: -10 })
     app.addCircleOr({ o: 'M', r: 'sqrt(5)', tag: 'circ1'})
     // On récupère les coordonnées du point M dzans le svg
     const pos = app.getPointPosition({ a: 'M'})
     // On crée un point lié au cercle, la position départ étant l'intersection du cercle avec la
     // droite passant par le centre M et le point de coordonnées pos.x + 10 et pos.y dans le svg
     // Ainsi le point est initialement à droite de M sur une position horizontale
     app.addLinkedPointCircle({c: 'circ1', x: pos.x + 10, y: pos.y, name: 'N'})
     // On ajoute un point P de coordonnées (7;1) dans le repère
     app.addPointXY({ rep:'rep', x: 7, y: 1, color: 'blue', name: 'P'})
     // On ajoute un cercle de centre P et passant par M
     app.addCircleOA({ o: 'P', a: 'N', color: 'green', tag: 'circ2'})
     // On crée l'intersection des deux cercles
     app.addIntCircleCircle({ c: 'circ1', c2: 'circ2', name: 'Q', name2: 'R', color: 'red' })
     // On ajoute la droite (OM) en pointillés
     app.addLineAB({ a: 'O', b: 'M', lineStyle: '.', color:'red', tag: 'lineOM' })
   }

   function suppressLink() {
     // La ligne ci-dessous est nécessaire pour le palyer au cas où il y aurait plusieurs figures MathGraph32 dans la page
     app.setApiDoc('mtg32svg')
     // On retire le listener sur l'affichage de texte car un deuxième appel provoquerait des erreurs
     app.removeEltListener({ elt: 'txt1', eventName: 'mousedown' })
     // On appelle removePointLink sur le point N ce qui transforme ce point lié en un point libre
     app.removePointLink({a: 'N'})
     // On crée un nouveau bouton pour lier le point M qui est devenu libre àa la droite (OM)
     app.addText({
       text: 'Lier N à la droite (OM)',
       rep: 'rep',
       x: -8,
       y: 7,
       transparent: false,
       backgroundColor: 'yellow',
       tag: 'txt2',
       border: '3D'
     })
     app.addEltListener({
       elt: 'txt2',
       eventName: 'mousedown',
       callBack: createLink
     })
     app.deleteElt({ elt: 'txt1'})
   }
   function createLink() {
     // La ligne ci-dessous est nécessaire pour le palyer au cas où il y aurait plusieurs figures MathGraph32 dans la page
     app.setApiDoc('mtg32svg')
     // On retire le listener sur l'affichage de texte car un deuxième appel provoquerait des erreurs
     app.removeEltListener({ elt: 'txt2', eventName: 'mousedown' })
     // On récu^ère la position actuelle du point N.
     const pos = app.getPointPosition({ a: 'N' })
     // La position de départ du point lié R créé ci-dessous est le projeté orthogonal du point de coordonnées (x; y)
     // sur la droite de tag lineOM
     app.addLinkedPointLine({ d: 'lineOM', x: pos.x, y: pos.y, name: 'S', hiddenName: true })
     // On appelle setLinkPointPoint ce qui transforme le point libre M en un point confondu avec le point lié R
     app.setLinkPointPoint({ a: 'N', b: 'S' })
     app.deleteElt({ elt: 'txt2'})
   }
 })()
</script>
</body>
</html>

La figure commence par ajouter à la figure :

Initialement, vous pouvez capturer le point N qui est un point lié au cercle de centre M.

Si vous cliquez sur bouton (texte) Retirer la liaison de N, ce texte est retiré de la figure et détruit et, si vous capturez le point M vous constaterez qu’il est devenu un point libre.

Vous constaterez aussi qu’un nouvel affichage de texte est apparu : Lier N à la droite (OM).

Si vous cliquez sur ce nouveau bouton, vous constaterez que le point N est maintenant lié à la droite (OM). En fait N est maintenant lié à un nouveau point rajouté à la figure, le point S, qui est un point lié à la droite (OM).

Le comportement de cette page est simulé ci-dessous :

A remarquer :

Dans le cas du player, avant d’agir sur la figure, un appel à setApidoc(idDoc) est indispensable où idDoc est l’id du svg contenant la figure (donné dans l’objet svgOption).

L’intersection des deux cercles a été créée via la ligne suivante : app.addIntCircleCircle({ c: 'circ1', c2: 'circ2', name: 'Q', name2: 'R', color: 'red', smartIntersect: true})

On demande ici de créer les deux points d’intersection des deux cercles de tag circ1 et circ2.

Par défaut, l’API de mathgrapph32 utilise une technique d’intersection ’intelligente’. Ici MathGraph32 sait que le point N appartient au cercle de tag circ1 puisque c’est un point lié à ce cercle. Un seul point d’intersection est donc créé de nom Q.

On pourrait donc replacer cette ligne par : app.addIntCircleCircle({ c: 'circ1', c2: 'circ2', name: 'Q', color: 'red', smartIntersect: true})

Lorsque qu’on a supprimé la liaison entre le point N et le cercle, il manque alors un des deux points d’intersection des deux cercles. Si nous voulons que ce point soit présent, on peut remplacer la ligne par celle-ci :

app.addIntCircleCircle({ c: 'circ1', c2: 'circ2', name: 'Q', name2: 'R', color: 'red', smartIntersect: true, smartInt: false})

On obtient alors le comportement simulé ci-dessous :