# Graphing Equation in HTML5 Using Canvas

## Introduction

In this article, I will walk through how to use a graphing equation in an HTML5 canvas.

## Graphing Equation in HTML5 using Canvas

### What is the Graph of an Equation?

It is the set of points where the equation is true.

### Features of a Graph

For a graph to be "complete" you need to show all the important features.
• Peaks
• Valleys
• Flat Areas
• Asymptotes
• Any other special feature
Browser Support

It is supported by all major browsers such as Internet Explorer 9, Firefox 3.6+, Safari 4+ and Chrome, etc.

Procedure for creating the graphing equations

Step 1

We first define the element using a "canvas" in HTML5. The height and width attributes set the canvas and graph size.

<canvas id="myCanvas" width="600" height="300" style="border: 1px solid black;"></canvas>

Step 2

In order to interact with this canvas through JavaScript, we will need to first get the element by Id and then create a context.
1. <script type="text/javascript">
2.     var canvas = document.getElementById('mycanvas');
3.     var ctx = canvas.getContext("2d");
4. </script>
Step 3

In the following code we will create a "Graph" function in which we define various methods, variables, constants and properties.
1. function Graph(config)
2. {
3.    // user defined properties
4.    this.canvas = document.getElementById(config.canvasId);
5.    this.minX = config.minX;
6.    this.minY = config.minY;
7.    this.maxX = config.maxX;
8.    this.maxY = config.maxY;
9.    this.unitsPerTick = config.unitsPerTick;
10.
11.    // constants
12.    this.axisColor = "#aaa";
13.    this.font = "8pt Calibri";
14.    this.tickSize = 20;
15.
16.    // relationships
17.    this.context = this.canvas.getContext("2d");
18.    this.rangeX = this.maxX - this.minX;
19.    this.rangeY = this.maxY - this.minY;
20.    this.unitX = this.canvas.width / this.rangeX;
21.    this.unitY = this.canvas.height / this.rangeY;
22.    this.centerY = Math.round(Math.abs(this.minY / this.rangeY) * this.canvas.height);
23.    this.centerX = Math.round(Math.abs(this.minX / this.rangeX) * this.canvas.width);
24.    this.iteration = (this.maxX - this.minX) / 1000;
25.    this.scaleX = this.canvas.width / this.rangeX;
26.    this.scaleY = this.canvas.height / this.rangeY;
27.
28.    // draw x and y axis
29.    this.drawXAxis();
30.    this.drawYAxis();
Step 4

In the following code, we will draw the x-axis. On the x-axis, we draw the left tick marks and then draw the right tick marks. For drawing both of the tick marks we apply the loop.
1. Graph.prototype.drawXAxis = function ()
2. {
3.    var context = this.context;
4.    context.save();
5.    context.beginPath();
6.    context.moveTo(0, this.centerY);
7.    context.lineTo(this.canvas.width, this.centerY);
8.    context.strokeStyle = this.axisColor;
9.    context.lineWidth = 2;
10.    context.stroke();
Figure 1

The following figure represents the x-axis:

1. // draw tick marks
2. var xPosIncrement = this.unitsPerTick * this.unitX;
3. var xPos, unit;
4. context.font = this.font;
5. context.textAlign = "center";
6. context.textBaseline = "top";
7.
8. // draw left tick marks
9. xPos = this.centerX - xPosIncrement;
10. unit = -1 * this.unitsPerTick;
11. while (xPos > 0)
12.    {
13.       context.moveTo(xPos, this.centerY - this.tickSize / 2);
14.       context.lineTo(xPos, this.centerY + this.tickSize / 2);
15.       context.stroke();
16.       context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
17.       unit -= this.unitsPerTick;
18.       xPos = Math.round(xPos - xPosIncrement);
19.    }
Figure 2

The following figure represents the left side tick mark of the x-axis:

1. // draw right tick marks
2. xPos = this.centerX + xPosIncrement;
3. unit = this.unitsPerTick;
4. while (xPos < this.canvas.width)
5.    {
6.       context.moveTo(xPos, this.centerY - this.tickSize / 2);
7.       context.lineTo(xPos, this.centerY + this.tickSize / 2);
8.       context.stroke();
9.       context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
10.       unit += this.unitsPerTick;
11.       xPos = Math.round(xPos + xPosIncrement);
12.    }
13. context.restore();
Figure 3

The following figure represents the right side tick mark of the x-axis

Step 5

Similarily, we will draw the y-axis. On the y-axis we will draw the tick marks along the upper side of the y-axis and finally, we draw the tick mark for the bottom side of the y-axis. For drawing both of the tick marks and labels we apply the loop.
1. Graph.prototype.drawYAxis = function ()
2. {
3.    var context = this.context;
4.    context.save();
5.    context.beginPath();
6.    context.moveTo(this.centerX, 0);
7.    context.lineTo(this.centerX, this.canvas.height);
8.    context.strokeStyle = this.axisColor;
9.    context.lineWidth = 2;
10.    context.stroke();
Figure 4

The following figure represents the y-axis

1. // draw tick marks
2. var yPosIncrement = this.unitsPerTick * this.unitY;
3. var yPos, unit;
4. context.font = this.font;
5. context.textAlign = "right";
6. context.textBaseline = "middle";
7.
8. // draw top tick marks
9. yPos = this.centerY - yPosIncrement;
10. unit = this.unitsPerTick;
11. while (yPos > 0)
12.   {
13.      context.moveTo(this.centerX - this.tickSize / 2, yPos);
14.      context.lineTo(this.centerX + this.tickSize / 2, yPos);
15.      context.stroke();
16.      context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
17.      unit += this.unitsPerTick;
18.      yPos = Math.round(yPos - yPosIncrement);
19.    }
Figure 5

The following figure represents the upper side tick mark on the y-axis

1. // draw bottom tick marks
2. yPos = this.centerY + yPosIncrement;
3. unit = -1 * this.unitsPerTick;
4. while (yPos < this.canvas.height)
5.   {
6.     context.moveTo(this.centerX - this.tickSize / 2, yPos);
7.     context.lineTo(this.centerX + this.tickSize / 2, yPos);
8.     context.stroke();
9.     context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
10.     unit -= this.unitsPerTick;
11.     yPos = Math.round(yPos + yPosIncrement);
12.   }
13. context.restore();
Figure 6

The following figure represents the lower side of the y-axis

Figure 7

The following figure represents the combination of the x-axis and the y-axis. Both form a graph.

Step 6

In the following step we will draw the equation on the graph. We will apply the loop for drawing the equation.
1. Graph.prototype.drawEquation = function (equation, color, thickness)
2. {
3.    var context = this.context;
4.    context.save();
5.    context.save();
6.    this.transformContext();
7.
8.    context.beginPath();
9.    context.moveTo(this.minX, equation(this.minX));
10.
11.    for (var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration)
12.     {
13.        context.lineTo(x, equation(x));
14.     }
15.
16.     context.restore();
17.     context.lineJoin = "round";
18.     context.lineWidth = thickness;
19.     context.strokeStyle = color;
20.     context.stroke();
21.     context.restore();
22. };
Step 7

We will transform the context to move it to the center. Then we will stretch the grid to fit the canvas window, and invert the y scale so that it increments as you move upwards.
1. Graph.prototype.transformContext = function ()
2. {
3.    var context = this.context;
4.
5.    // move context to center of canvas
6.    this.context.translate(this.centerX, this.centerY);
7.
8.    context.scale(this.scaleX, -this.scaleY);
9. };
Step 8

In the following code the window onload we will draw lines on the graph.
2. {
3.    var myGraph = new Graph({
4.        canvasId: "myCanvas",
5.        minX: -10,
6.        minY: -10,
7.        maxX: 10,
8.        maxY: 10,
9.        unitsPerTick: 1
10.     });
11.
12.     myGraph.drawEquation(function (x) {
13.          return 5 * Math.sin(x);
14.     }, "green", 3);
15.
16.     myGraph.drawEquation(function (x) {
17.          return x * x;
18.     }, "blue", 3);
19.
20.     myGraph.drawEquation(function (x) {
21.           return 1 * x;
22.     }, "red", 3);
23. };
Example
1. <!DOCTYPE html>
2.
3. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
5.     <meta charset="utf-8" />
6.     <title>Graphing Equation in HTML5</title>
7.     <script>
8.         function Graph(con) {
9.             // user defined properties
10.             this.canvas = document.getElementById(con.canvasId);
11.             this.minX = con.minX;
12.             this.minY = con.minY;
13.             this.maxX = con.maxX;
14.             this.maxY = con.maxY;
15.             this.unitsPerTick = con.unitsPerTick;
16.
17.             // constants
18.             this.axisColor = "#aaa";
19.             this.font = "8pt Calibri";
20.             this.tickSize = 20;
21.
22.             // relationships
23.             this.context = this.canvas.getContext("2d");
24.             this.rangeX = this.maxX - this.minX;
25.             this.rangeY = this.maxY - this.minY;
26.             this.unitX = this.canvas.width / this.rangeX;
27.             this.unitY = this.canvas.height / this.rangeY;
28.             this.centerY = Math.round(Math.abs(this.minY / this.rangeY) * this.canvas.height);
29.             this.centerX = Math.round(Math.abs(this.minX / this.rangeX) * this.canvas.width);
30.             this.iteration = (this.maxX - this.minX) / 1000;
31.             this.scaleX = this.canvas.width / this.rangeX;
32.             this.scaleY = this.canvas.height / this.rangeY;
33.
34.             // draw x and y axis
35.             this.drawXAxis();
36.             this.drawYAxis();
37.         }
38.
39.         Graph.prototype.drawXAxis = function () {
40.             var context = this.context;
41.             context.save();
42.             context.beginPath();
43.             context.moveTo(0, this.centerY);
44.             context.lineTo(this.canvas.width, this.centerY);
45.             context.strokeStyle = this.axisColor;
46.             context.lineWidth = 2;
47.             context.stroke();
48.
49.             // draw tick marks
50.             var xPosIncrement = this.unitsPerTick * this.unitX;
51.             var xPos, unit;
52.             context.font = this.font;
53.             context.textAlign = "center";
54.             context.textBaseline = "top";
55.
56.             // draw left tick marks
57.             xPos = this.centerX - xPosIncrement;
58.             unit = -1 * this.unitsPerTick;
59.             while (xPos > 0) {
60.                 context.moveTo(xPos, this.centerY - this.tickSize / 2);
61.                 context.lineTo(xPos, this.centerY + this.tickSize / 2);
62.                 context.stroke();
63.                 context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
64.                 unit -= this.unitsPerTick;
65.                 xPos = Math.round(xPos - xPosIncrement);
66.             }
67.
68.             // draw right tick marks
69.             xPos = this.centerX + xPosIncrement;
70.             unit = this.unitsPerTick;
71.             while (xPos < this.canvas.width) {
72.                 context.moveTo(xPos, this.centerY - this.tickSize / 2);
73.                 context.lineTo(xPos, this.centerY + this.tickSize / 2);
74.                 context.stroke();
75.                 context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
76.                 unit += this.unitsPerTick;
77.                 xPos = Math.round(xPos + xPosIncrement);
78.             }
79.             context.restore();
80.         };
81.
82.         Graph.prototype.drawYAxis = function () {
83.             var context = this.context;
84.             context.save();
85.             context.beginPath();
86.             context.moveTo(this.centerX, 0);
87.             context.lineTo(this.centerX, this.canvas.height);
88.             context.strokeStyle = this.axisColor;
89.             context.lineWidth = 2;
90.             context.stroke();
91.
92.             // draw tick marks
93.             var yPosIncrement = this.unitsPerTick * this.unitY;
94.             var yPos, unit;
95.             context.font = this.font;
96.             context.textAlign = "right";
97.             context.textBaseline = "middle";
98.
99.             // draw top tick marks
100.             yPos = this.centerY - yPosIncrement;
101.             unit = this.unitsPerTick;
102.             while (yPos > 0) {
103.                 context.moveTo(this.centerX - this.tickSize / 2, yPos);
104.                 context.lineTo(this.centerX + this.tickSize / 2, yPos);
105.                 context.stroke();
106.                 context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
107.                 unit += this.unitsPerTick;
108.                 yPos = Math.round(yPos - yPosIncrement);
109.             }
110.
111.             // draw bottom tick marks
112.             yPos = this.centerY + yPosIncrement;
113.             unit = -1 * this.unitsPerTick;
114.             while (yPos < this.canvas.height) {
115.                 context.moveTo(this.centerX - this.tickSize / 2, yPos);
116.                 context.lineTo(this.centerX + this.tickSize / 2, yPos);
117.                 context.stroke();
118.                 context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
119.                 unit -= this.unitsPerTick;
120.                 yPos = Math.round(yPos + yPosIncrement);
121.             }
122.             context.restore();
123.         };
124.
125.         Graph.prototype.drawEquation = function (equation, color, thickness) {
126.             var context = this.context;
127.             context.save();
128.             context.save();
129.             this.transformContext();
130.
131.             context.beginPath();
132.             context.moveTo(this.minX, equation(this.minX));
133.
134.             for (var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
135.                 context.lineTo(x, equation(x));
136.             }
137.
138.             context.restore();
139.             context.lineJoin = "round";
140.             context.lineWidth = thickness;
141.             context.strokeStyle = color;
142.             context.stroke();
143.             context.restore();
144.         };
145.
146.         Graph.prototype.transformContext = function () {
147.             var context = this.context;
148.
149.             // move context to center of canvas
150.             this.context.translate(this.centerX, this.centerY);
151.
152.             context.scale(this.scaleX, -this.scaleY);
153.         };
154.
155.         window.onload = function () {
156.             var myGraph = new Graph({
157.                 canvasId: "myCanvas",
158.                 minX: -10,
159.                 minY: -10,
160.                 maxX: 10,
161.                 maxY: 10,
162.                 unitsPerTick: 1
163.             });
164.
165.             myGraph.drawEquation(function (x) {
166.                 return 5 * Math.sin(x);
167.             }, "green", 3);
168.
169.             myGraph.drawEquation(function (x) {
170.                 return x * x;
171.             }, "blue", 3);
172.
173.             myGraph.drawEquation(function (x) {
174.                 return 1 * x;
175.             }, "red", 3);
176.         };
177.     </script>