Hi folks,
I’d like to talk about how to draw simple curve using HTML5 Canvas element, a little bit of basic math and JavaScript with some animation. The example is based one I found on a book I’m reading right now:
from which I took the code to draw the Cartesian grid.
The basic idea is not using Bezier JavaScript function or quadratic ones which are useful and powerful, but doesn’t have any animation. Since I think that sometimes is funny reinventing the wheel, I decided to try to draw a circumference and a parabola without using built-in functions. Here I will explain the basic facts and the complete code is available on codepen.
Let’s start; first of all I had to make some assumptions, to simplify the code:
- Circumference will have a predefined radius and its centre will be in the cartesian origin i.e. point (0,0)
- Parabola will be centered in the cartesian origin
Wikipedia has a nice explanation of the circumference and parabola; what we really need is their cartesian equation and so:
- Circumference (centre in the origin)
- Parabola
So, after a brief explanation of what it’s needed let’s start coding:
- Create a simple HTML page with a Canvas object and a form with two buttons, one for the circumference and one for the parabola.
<div> <canvas id="main" width="400px" height="400px"></canvas> <form> <input type="button" id="parabola" value="parabola" class="button2" /> <input type="button" id="circle" value="circle" class="button3" /> </form> </div>
With a few line of JavaScript let’s add a listener to each button:
var parabola_button = document.getElementById('parabola'); parabola_button.addEventListener('click',parabolaPressed,false); var circle_button = document.getElementById('circle'); circle_button.addEventListener('click',circlePressed,false);
The actual drawing action is made up of two functions, called by pressing one of the two buttons; as an example I will write the circumference one:
function circlePressed(e){ draw_circle(100,"blue"); }
As you can see, on the button click event the “circlePressed” function is called; this function calls draw_circle which takes two arguments, the radius and the line colour. This function simply calculates the y value based on the x value and the radius using this formula:
You also have to remember that for each x point there are two y points, due to the nature of circumference and square root, so you will have to draw both of them.
Here is the function:
function draw_circle(radius,color){ var radius = radius; if(graph_in_progress == 'yes'){ alert('Another line being drawn, please wait'); }else{ init_x = -radius; init_y = -Math.sqrt(Math.pow(radius,2)-Math.pow(init_x,2)); new_x = init_x; new_y = init_y; graph_in_progress = "yes"; drawLineIntervalId = setInterval(do_animation_3,33); } function do_animation_3(){ ctx.lineWidth = 6; ctx.fillStyle = color; ctx.beginPath(); ctx.moveTo(init_x,init_y); //ctx.lineTo(new_x,new_y); ctx.fillRect(init_x,init_y,1,1); ctx.fillRect(init_x,-init_y,1,1); ctx.stroke(); ctx.closePath(); new_x = new_x+1; new_y = -Math.sqrt(Math.pow(radius,2)-Math.pow(new_x,2)); ctx.fillRect(new_x,new_y,1,1); ctx.fillRect(new_x,-new_y,1,1); if(new_x == canvas.width+5){ clearInterval(drawLineIntervalId); graph_in_progress = "no"; } } }
The function starts by checking if any other graph is being drawn, if so, an alert is displayed. Then it starts setting an initial point with the x equal to the negative value of the radius. After that an interval of 33 ms is set so to animate the graph.In the drawing function a path is started using the canvas context beginPath method, the path is then moved to the initial point and two 1 pixel rectangles are drawn. Afterwards the path must be closed and a the new x,y values are calculated and the rectangles are drawn again. To end the recursion, the function checks whether or not the current x value is bigger than the radius, if so, the time interval is cleared and the function is terminated. And here is the result:
Isn’t it easy?
Enjoy!!
Reference book: HTML5 for publishers
Complete code: codepen