Draw functions f (x) with JavaScript and canvas

1

My idea is to paint a x function using JavaScript and Canvas , I've been looking through the internet and have not found anything about it, I may have looked bad, I do not know, but the question is that I'm not sure how to start, here I leave what I've tried so far:

$(document).ready(function() {

  var windowWidth = window.innerWidth;
  var windowHeight = window.innerHeight;

    //Establezco una escala que posteriormente aplico
  var scale = 100;

  var cv = document.getElementById("fx");
  cv.height = windowHeight;
  cv.width = windowWidth;

  var ctx = cv.getContext("2d");

   //Aquí traslado todo el contexto al centro de la pantalla
  ctx.translate((windowWidth / 2),(windowHeight / 2));

//Esta función simplemente dibuja los ejes (es lo de menos)
  drawaxis();
  function drawaxis() {

    var x_axis = {
      x: -windowWidth / 2,
      y: 0,
      xf: windowWidth / 2,
      yf: 0
    }

    var y_axis = {
      x: 0,
      y: -windowHeight / 2,
      xf: 0,
      yf: windowHeight /2
    }

    ctx.beginPath();
    ctx.moveTo(x_axis["x"],x_axis["y"]);
    ctx.lineTo(x_axis["xf"],x_axis["yf"]);
    ctx.stroke();
    ctx.closePath();

    ctx.beginPath();
    ctx.moveTo(y_axis["x"],y_axis["y"]);
    ctx.lineTo(y_axis["xf"],y_axis["yf"]);
    ctx.stroke();
    ctx.closePath();

  }

//Aquí es donde empiezan los inconvenientes (que más abajo detallo)
  for (x = -windowWidth; x <= windowWidth; x = x + 0.01) {
    var y = Math.pow(x,2);
    drawfx(x,y);
  }

//Pintar los puntos para pintar los valores
  function drawfx(x,y) {

//Aquí es donde aplico la escala
    x = x*scale;
    y = y*scale;

    ctx.beginPath();
    ctx.arc(x, y, 1, 0, 2 * Math.PI);
    ctx.fill();
    ctx.closePath();
  }

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<!-- El tamaño del canvas lo cambio en el script -->
  <canvas id="fx" width="0" height="0"></canvas>
</div>

Once this is done, the result is more or less decent, leaving it like this:

The problem of doing it this way is that until the for loop does not end, the graph is not painted and this causes a slight waiting time until all the values are calculated.

And the second problem is in (as you can see in the image) that being in this case an exponential function as the values increase the points are increasingly separated and for this reason the " continuous line "begins to be" discontinuous ".

And now, my question is whether this is a more or less decent way of doing it or if there are much better ways of doing it than I am missing .......

I would appreciate any help possible. Thanks!

    
asked by lromeraj 09.03.2017 в 18:23
source

3 answers

5

If you want to graph mathematical functions in every sense of the word, this library is for you link

function draw() {
    try {
      functionPlot({
        target: '#plot',
        data: [{
          fn: document.getElementById('eq').value,
          sampler: 'builtIn',  // this will make function-plot use the evaluator of math.js
          graphType: 'polyline'
        }]
      });
    }
    catch (err) {
      console.log(err);
      alert(err);
    }
  }

  document.getElementById('form').onsubmit = function (event) {
    event.preventDefault();
    draw();
  };

  draw();
 input[type=text] {
      width: 300px;
    }
    input {
      padding: 6px;
    }
    body, html, input {
      font-family: sans-serif;
      font-size: 11pt;

    }
    form {
      margin: 20px 0;
    }
<title>math.js | plot</title>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/mathjs/3.10.0/math.min.js"></script>

  <!-- load http://maurizzzio.github.io/function-plot/ -->
  <script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <script src="https://wzrd.in/standalone/[email protected]"></script>
  
<form id="form">
  <label for="eq">Enter an equation:</label>
  <input type="text" id="eq" value="4 * sin(x) + 5 * cos(x/2)" />
  <input type="submit" value="Draw" />
</form>

<div id="plot"></div>

<p>
  Plot library: <a href="https://github.com/maurizzzio/function-plot">https://github.com/maurizzzio/function-plot</a>
</p>
    
answered by 09.03.2017 / 19:18
source
1

You could use p5.js to make the curves, something like this:

function draw() {
    // Acá van los cálculos para obtener los puntos
    // p5.js tiene funciones matemáticas, así que te
    // Podrían ser útiles

    beginShape(); //Para empezar a dibujar la figura
    vertex(x, y); // Para añadir vértices
    curveVertex(x, y); // Vértices para hacer curvas
    endShape(CLOSE); // Para terminar de dibujar
    // El parámetro "CLOSE" es opcional, y sirve
    // Para cerrar la figura.
}

I suggest you read the Documentation .

I hope it's useful!

    
answered by 09.12.2018 в 16:37
0

First, you are getting more complicated , because fooplot exists to generate exactly what you're looking for.

Second: I thought that using requestAnimationFrame could be drawn gradually. I was wrong in that. I would not know how to show the drawing progressively.

Third, for the subject of the dashed line, instead of drawing circles of 1px radius, you should draw a line, as in the Riemann hypothesis. The line goes from (x, y) to (x + dx, y + dy).

var interval = 0.01;

for (x = -windowWidth; x < windowWidth; x = x + interval) {
    drawfx(x, interval);
}

function drawfx(x,interval) {
    var x0 = x,
        y0 = Math.pow(x0,2),
        x1 = x + interval,
        y1 = Math.pow(x1,2);

    x0 = x0*scale;
    y0 = y0*scale;
    x1 = x1*scale;
    y1 = y1*scale;

    ctx.beginPath();
    ctx.moveTo(x0, y0);
    ctx.lineTo(x1, y1);
    ctx.stroke();
    ctx.closePath();
}

$(document).ready(function() {

  var windowWidth = window.innerWidth;
  var windowHeight = window.innerHeight;

    //Establezco una escala que posteriormente aplico
  var scale = 100;

  var cv = document.getElementById("fx");
  cv.height = windowHeight;
  cv.width = windowWidth;

  var ctx = cv.getContext("2d");

   //Aquí traslado todo el contexto al centro de la pantalla
  ctx.translate((windowWidth / 2),(windowHeight / 2));

//Esta función simplemente dibuja los ejes (es lo de menos)
  drawaxis();
  function drawaxis() {

    var x_axis = {
      x: -windowWidth / 2,
      y: 0,
      xf: windowWidth / 2,
      yf: 0
    }

    var y_axis = {
      x: 0,
      y: -windowHeight / 2,
      xf: 0,
      yf: windowHeight /2
    }

    ctx.beginPath();
    ctx.moveTo(x_axis["x"],x_axis["y"]);
    ctx.lineTo(x_axis["xf"],x_axis["yf"]);
    ctx.stroke();
    ctx.closePath();

    ctx.beginPath();
    ctx.moveTo(y_axis["x"],y_axis["y"]);
    ctx.lineTo(y_axis["xf"],y_axis["yf"]);
    ctx.stroke();
    ctx.closePath();

  }

var interval = 0.01;

for (x = -windowWidth; x < windowWidth; x = x + interval) {
  drawfx(x, interval);
}

function drawfx(x,interval) {
    var x0 = x,
        y0 = Math.pow(x0,2),
        x1 = x + interval,
        y1 = Math.pow(x1,2);

    x0 = x0*scale;
    y0 = y0*scale;
    x1 = x1*scale;
    y1 = y1*scale;

    ctx.beginPath();
    ctx.moveTo(x0, y0);
    ctx.lineTo(x1, y1);
    ctx.stroke();
    ctx.closePath();
}

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<!-- El tamaño del canvas lo cambio en el script -->
  <canvas id="fx" width="0" height="0"></canvas>
</div>
    
answered by 09.03.2017 в 19:10