Mon but est de détecter où ma fonction croise en premier les axes X du côté négatif. Pour cela, je vérifie d'abord sur toute la gamme, puis je divise par deux dans un des côtés, selon le résultat. J'aimerais dessiner 1 par 1 tous mes cercles. La première fois que j'obtiens quelque chose comme ça :

enter image description here

Puis j'ai cherché et essayé ceci :

window.requestAnimationFrame(drawDicho(a,b));

Et je pensais que cela dessinerait chaque cercle individuellement. Mais au lieu de cela, il ne dessine le cercle que sur les coordonnées (0,0). Si je clique à nouveau, il dessine à nouveau dessus.

enter image description here

¨

J'ai essayé window.setInterval (...) mais rien ne s'est passé non plus.

Je peux récupérer la valeur correcte, mais j'aimerais afficher les cercles un par un et pas tous en même temps. Est-ce que quelqu'un a une idée ? Peut-être que je place le code au mauvais endroit, je ne sais pas..

@UPDATE CODE COMPLET :

    <script type="text/javascript">
      window.onload = function(){
        var canvas = $('myCanvas');
        if(!canvas){
          alert("Impossible to recover canvas");
          return;
        }

        var context = canvas.getContext('2d');
        if(!context){
          alert("Impossible dto recover canvas context");
          return;
        }

        context.fillStyle = 'rgba(255, 255, 255, 1)';
        context.fillRect(0, 0, 500, 500);
        context.strokeStyle = 'rgba(0, 0, 0, 1)';

        var width = canvas.width;
        var height = canvas.height;

        //draw axis Y
        context.beginPath();
        context.moveTo(width/2, 0);
        context.lineTo(width/2, height);
        context.closePath();
        context.stroke();

        //draw axis X
        context.beginPath();
        context.moveTo(0, height/2);
        context.lineTo(width, height/2);
        context.closePath();
        context.stroke();


      }


      function function1(x){
        return Math.sin(x)-(x/13);
      }

      function function2(x){
        return x/(1-Math.pow(x, 2));
      }

      function draw(func){
        var canvas = $('myCanvas');
        var context = canvas.getContext('2d');
        var dx = canvas.width;
        var dy = canvas.height;
        var scale = dx/40; // echelle (nb pixels between x=0 et x=1)
        var x0 = dx/2;
        var y0 = dy/2;
        var iMax = 20;
        var x, y;
        var iMin = -20;
            context.translate(x0,y0);
      context.scale(1, -1);
            context.strokeStyle = 'rgba(255, 0, 0, 1)';
      context.beginPath();
      context.arc(-100, 0, 5, 0, 2*Math.PI, false);
      context.arc(100, 0, 5, 0, 2*Math.PI, false);

      for(i = -100; i<=100; i=i+0.01){
                x=i*4;
                y = scale * func(x/scale);
        context.lineTo(x, y);

          }
          context.closePath();
          context.stroke();
      }

      function drawF1(){
        draw(function1);
      }

      function drawF2(){
        draw(function2);
      }

      function drawDicho(a, b){
        var canvas = $('myCanvas');
        var context = canvas.getContext('2d');
        context.beginPath();
        context.arc(a, 0, 5, 0, 2*Math.PI, false);
        context.arc(b, 0, 5, 0, 2*Math.PI, false);
        context.closePath();
        context.stroke();
      }

      function dichotomie(func){
        var a = -100;
        var b = 100;
        var fa = func(a);
        var fb = func(b);
        var delta = 0.01;

        while(Math.abs(b-a) > delta){
        //drawDicho(a,b);
          var m = (a+b)/2;
          var fm = func(m);
          if(fm * fa <= 0){
            b = m;
            fb = fm;
          }
          else{
            a = m;
            fa = fm;
          }
          window.requestAnimationFrame(drawDicho(a,b));
        }
        if(fa * fb <= 0){
          return m.toFixed(3);

        }
        else{
          return 'no 0';
        }

      }

      function $(id){
        return document.getElementById(id);
      }

      function solvef1()
      {
        var result = dichotomie(function1);
        alert(result);
      }

      function solvef2(){
        var result = dichotomie(function2);
        alert(result);
      }

    </script>
</head>
<body style="background-color:grey">
  <p>
    <label>draw fonction: </label>
    <input type="button" name="function1" value="fonction 1" id="drawF1" onclick="drawF1()">
    <input type="button" name="function2" value="fonction 2" id="drawF2" onclick="drawF2()">
    <input type="button" name="solvef1" value="solvef1" id="solvef1" onclick="solvef1()">
    <input type="button" name="solvef2" value="solvef2" id="solvef2" onclick="solvef2()">
  </p>
    <br>
    <canvas id="myCanvas" width="500" height="500">
      Message bla bla bla
    </canvas>
</body>

(la fonction dichotomie qui calcule et dessine des cercles est utilisée lorsque je clique sur le bouton "résoudre f1")

Je vous remercie.

2
Dom 14 mars 2019 à 15:11

2 réponses

Meilleure réponse

Je mets à jour votre dichotomie de la manière suivante ( 300 est le nombre de millisecondes entre les cercles de dessin) (exécuter l'extrait sur "Pleine page")

function dichotomie(func){
    ...
    var circs=[];

    while(Math.abs(b-a) > delta){
      ...
      circs.push([a,b])
    }

    circs.map((x,i) => setTimeout(y=> drawDicho(...x),i*300) );
    ...
  }

Dans cette solution, nous utilisons des fonctions fléchées et carte de tableau

<script type="text/javascript">
      window.onload = function(){
        var canvas = $('myCanvas');
        if(!canvas){
          alert("Impossible to recover canvas");
          return;
        }

        var context = canvas.getContext('2d');
        if(!context){
          alert("Impossible dto recover canvas context");
          return;
        }

        context.fillStyle = 'rgba(255, 255, 255, 1)';
        context.fillRect(0, 0, 500, 500);
        context.strokeStyle = 'rgba(0, 0, 0, 1)';

        var width = canvas.width;
        var height = canvas.height;

        //draw axis Y
        context.beginPath();
        context.moveTo(width/2, 0);
        context.lineTo(width/2, height);
        context.closePath();
        context.stroke();

        //draw axis X
        context.beginPath();
        context.moveTo(0, height/2);
        context.lineTo(width, height/2);
        context.closePath();
        context.stroke();


      }


      function function1(x){
        return Math.sin(x)-(x/13);
      }

      function function2(x){
        return x/(1-Math.pow(x, 2));
      }

      function draw(func){
        var canvas = $('myCanvas');
        var context = canvas.getContext('2d');
        var dx = canvas.width;
        var dy = canvas.height;
        var scale = dx/40; // echelle (nb pixels between x=0 et x=1)
        var x0 = dx/2;
        var y0 = dy/2;
        var iMax = 20;
        var x, y;
        var iMin = -20;
            context.translate(x0,y0);
      context.scale(1, -1);
            context.strokeStyle = 'rgba(255, 0, 0, 1)';
      context.beginPath();
      context.arc(-100, 0, 5, 0, 2*Math.PI, false);
      context.arc(100, 0, 5, 0, 2*Math.PI, false);

      for(i = -100; i<=100; i=i+0.01){
                x=i*4;
                y = scale * func(x/scale);
        context.lineTo(x, y);

          }
          context.closePath();
          context.stroke();
      }

      function drawF1(){
        draw(function1);
      }

      function drawF2(){
        draw(function2);
      }

      function drawDicho(a, b){
        var canvas = $('myCanvas');
        var context = canvas.getContext('2d');
        context.beginPath();
        context.arc(a, 0, 5, 0, 2*Math.PI, false);
        context.arc(b, 0, 5, 0, 2*Math.PI, false);
        context.closePath();
        context.stroke();
      }

      function dichotomie(func){
        var a = -100;
        var b = 100;
        var fa = func(a);
        var fb = func(b);
        var delta = 0.01;
        var circs=[];
        
        while(Math.abs(b-a) > delta){
        //drawDicho(a,b);
          var m = (a+b)/2;
          var fm = func(m);
          
          if(fm * fa <= 0){
            b = m;
            fb = fm;
          }
          else{
            a = m;
            fa = fm;
          }
          circs.push([a,b])
        }
        console.log(circs);
        circs.map((x,i) => setTimeout(y=> drawDicho(...x),i*300) );
        
        if(fa * fb <= 0){
          return m.toFixed(3);

        }
        else{
          return 'no 0';
        }

      }

      function $(id){
        return document.getElementById(id);
      }

      function solvef1()
      {
        var result = dichotomie(function1);
        alert(result);
      }

      function solvef2(){
        var result = dichotomie(function2);
        alert(result);
      }

    </script>
</head>
<body style="background-color:grey">
  <p>
    <label>draw fonction: </label>
    <input type="button" name="function1" value="fonction 1" id="drawF1" onclick="drawF1()">
    <input type="button" name="function2" value="fonction 2" id="drawF2" onclick="drawF2()">
    <input type="button" name="solvef1" value="solvef1" id="solvef1" onclick="solvef1()">
    <input type="button" name="solvef2" value="solvef2" id="solvef2" onclick="solvef2()">
  </p>
    <br>
    <canvas id="myCanvas" width="500" height="500">
      Message bla bla bla
    </canvas>
</body>
1
Kamil Kiełczewski 14 mars 2019 à 14:15

window.requestAnimationFrame attend une référence de fonction en tant que paramètre, de sorte que la fonction donnée puisse être appelée dès que le navigateur a terminé le rendu, mais pas plus vite que 60 Hz.

En faisant:

while (…) {
  …
  window.requestAnimationFrame(drawDicho(a,b));
  …
}

Vous appelez drawDicho(a,b) tout de suite dans la boucle while et affectez la valeur de retour à requestAnimationFrame, qui n'est pas définie.

Ce dont vous avez besoin, du moins je pense que vous en avez besoin, c'est d'une boucle d'animation comme celle-ci :

const DELAY = 1000;

let 
  last = new Date().getTime(),
  circles = [
    [10,10],
    [100, 100],
    [10, 100]
  ]
;

//replace while () {} with the loop below,
//this way the execution is scheduled
(function loop () {
  const 
    now = new Date().getTime(),
    delta = now - last;

  if (delta >= DELAY && circles.length > 0) {
    drawCircle(...circles.shift());
    last = now;
  }


  window.requestAnimationFrame(loop);

})();

De cette façon, loop sera appelé fréquemment. Une boucle while n'est pas une boucle d'animation, le code est appelé tout de suite. Une boucle d'animation s'exécute avec une certaine » fréquence d'images, ce qu'une boucle while ne fait pas.

1
philipp 14 mars 2019 à 13:29