0
\$\begingroup\$

I have begun coding a simple graph plotter for my schoolchildren using JavaScript. I have used the paper.js library as I would like to be able to export the graphs as svg files.

I am only a beginner to all this (just a humble maths teacher) so I would hugely welcome any thoughts you may have. The code does not run particularly quickly so I would be particularly interested in any improvements to performance.

Many thanks and best wishes.

HTML:

<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.11/paper-full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/9.3.0/math.min.js"></script>

<input type="number" id="input_xWidth" value=14><br>
<input type="number" id="input_yWidth" value=4><br>
<input type="text" id="eqn" value='sin(x)'><br>

<button onclick="drawGrid()">draw grid</button>
<button onclick="exportSVG()">export</button>

<br><br>

<canvas id="canvas_1"></canvas><br>

JavaScript:

var graphScope = new paper.PaperScope();
var canvas_1 = document.getElementById('canvas_1');
graphScope.setup(canvas_1);
graphScope.activate();

const scale = 10;

function drawGrid() {

  var xWidth = document.getElementById("input_xWidth").value;
  var yWidth = document.getElementById("input_yWidth").value;

  var z;
  var zz;

  //clear the canvas
  graphScope.project.activeLayer.removeChildren()

  //draw minor gridlines
  for (z = 0; z < xWidth; z++) {
    for (zz = 1; zz < 5; zz++) {
      var myPath = new graphScope.Path();
      myPath.strokeColor = new graphScope.Color(0.9, 0.9, 0.9);
      myPath.add(new graphScope.Point(z * scale + (scale / 5) * zz, -(0)));
      myPath.add(new graphScope.Point(z * scale + (scale / 5) * zz, -(yWidth * scale)));
    }
  }

  for (z = 0; z < yWidth; z++) {
    for (zz = 1; zz < 5; zz++) {
      var myPath = new graphScope.Path();
      myPath.strokeColor = new graphScope.Color(0.9, 0.9, 0.9);
      myPath.add(new graphScope.Point(0, -(z * scale + (scale / 5) * zz)));
      myPath.add(new graphScope.Point(xWidth * scale, -(z * scale + (scale / 5) * zz)));
    }
  }

  //draw major gridlines
  for (z = 0; z <= xWidth; z++) {
    var myPath = new graphScope.Path();
    myPath.strokeColor = new graphScope.Color(0.5, 0.5, 0.5);
    myPath.add(new graphScope.Point(z * scale, -(0)));
    myPath.add(new graphScope.Point(z * scale, -(yWidth * scale)));
  }

  for (z = 0; z <= yWidth; z++) {
    var myPath = new graphScope.Path();
    myPath.strokeColor = new graphScope.Color(0.5, 0.5, 0.5);
    myPath.add(new graphScope.Point(0, -(z * scale)));
    myPath.add(new graphScope.Point(xWidth * scale, -(z * scale)));
  }

  // parse equation from input box
  const node2 = math.parse(document.getElementById("eqn").value)
  const code2 = node2.compile()
  let scope = {
    x: 3,
  }


  // trim graph to grid
  var rectangle = new graphScope.Rectangle(new graphScope.Point(0, 0), new graphScope.Point(xWidth * scale, -yWidth * scale));
  var GraphBoundary = new graphScope.Path.Rectangle(rectangle);
  var graphPath = new graphScope.Path();
  for (z = 0; z < xWidth; z += 0.001) {
    scope.x = z
    graphPath.add(new graphScope.Point(z * scale, -(20 + scale * code2.evaluate(scope))));
  }
  var NewPath = graphPath.intersect(GraphBoundary, {
    trace: false
  })
  NewPath.strokeColor = new graphScope.Color(0.1, 0.1, 0.1);
  graphPath.remove();

  //fit page to canvas bounds
  graphScope.project.activeLayer.fitBounds(graphScope.view.bounds);
}

function exportSVG() {
  var fileName = "custom.svg"
  var url = "data:image/svg+xml;utf8," + encodeURIComponent(graphScope.project.exportSVG({
    asString: true
  }));
  var link = document.createElement("a");
  link.download = fileName;
  link.href = url;
  link.click();
}
\$\endgroup\$

1 Answer 1

1
+50
\$\begingroup\$

I'm not familiar with Paper so can't say anything about that. And I won't say much about the HTML, as it's obviously just a functional placeholder, except two points:

  • Use double quotes " consistently on all attributes.
  • Don't use on... attributes. Assign event listeners in the script using addEventListener.

Regarding the script:

  • Use let/const instead of var.
  • Declare the variable in loops separately in the for statement using let (e.g. don't reuse the same declared variable in all loops).
  • Use better variable names. I have no idea what z, zz, node2, code2, etc. mean. (Also make sure all variable names start with a lower case letter.)
  • Don't repeatedly create the same colors in the loops. Create them once outside the loop.
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.