Click here to Skip to main content
15,867,594 members
Articles / Web Development / HTML5

Simple HTML5 Spiro Drawing Page

Rate me:
Please Sign up or sign in to vote.
4.96/5 (12 votes)
9 Oct 2011CPOL3 min read 31.5K   572   26   9
A simple HTM5 web page using Javascript and Canvas

Introduction

HTML5 is rapidly increasing in popularity so I thought I would take it for a spin and try out the new canvas element. The canvas element is basically a rectangular area in which you can draw the usual 2D graphical elements like lines, paths, text, etc. and with the ability to specify fill, gradients, line styles and push and pop transforms for doing things like rotation. It's much lighter weight than SVG and allows the user to manipulate every pixel within that rectangular area, making it great for writing games.

Background

As a first step in playing with canvas, I chose a very simple program I wrote decades ago when my kids were playing around with a Spirograph. I could see the simplest patterns were essentially one circular path being rotated on the end of another circular path with a specific ratio between the two diameters of the circular paths and the ratio of their rotational velocities. With that in mind, I created a very simply GDI Windows application that could achieve something similar. Surprisingly, I was able to almost copy and paste the drawing part of the original C++ code into my JavaScript and with some minor modifications, make it run (e.g. change int to var). Another reason that few changes were required is that both GDI and canvas have the origin at the top left, i.e. larger X values are to the right and larger Y values are towards the bottom of the drawing area.

The web page is shown below. It has four selectors at the top of the page. The first two are the ratios I mentioned earlier, the third sets the number of steps in a complete circuit and the fourth selector is for the colour. Changing any of these causes an immediate redraw. I tested the page on all the usual browsers: IE9, Chrome, Firefox, Opera, Safari and it worked identically - the only slight difference being Safari which didn't draw the coloured background of the colour selector or its drop list items.

Image 1

Using the Code

The main HTML code is shown below. I placed all the selectors in a div so I could adjust the CSS to get the spacing and appearance I wanted. In case you didn't know hitting F12 in IE9 brings up a nice "developer tool" that allows you to inspect the HTML, CSS, Scripts, etc. and allows you to modify the CSS on the fly. Chrome has a similar tool (use right click "Inspect Element") which in some ways I find better. The main thing to note with the selectors is that they must all have an id (as the JavaScript will need this to find the element and read its attributes) and they have their onchange handler all set to call 'updateCanvas()'.

HTML
<div id='params'>
Size Ratio: 
<select id='sizeratio' onchange='updateCanvas()'>
 <option>1</option> 
 <option>2</option> 
 <option>3</option> 
 <option selected="selected">4</option> 
 <option>5</option> 
</select>
  Speed Ratio: 
<select id='speedratio' onchange='updateCanvas()'>
 <option>2</option> 
 <option>3</option> 
 <option selected="selected">4</option> 
 <option>5</option> 
</select>
  Steps: 
<select id='steps' onchange='updateCanvas()'>
 <option>100</option> 
 <option>200</option> 
 <option selected="selected">300</option> 
 <option>400</option> 
 <option>500</option> 
</select>
  Colour: 
<select id="color_menu0" name="color_menu0" 
	onchange="updateCanvas();" style="width: 60px">
<option style="background-color:#5f9ea0" value="#5f9ea0" selected="selected"/>     
<option style="background-color:#d2691e" value="#d2691e"/>     
<option style="background-color:#ffd700" value="#ffd700"/>     
<option style="background-color:#7fff00" value="#7fff00"/>     
<option style="background-color:#006400" value="#006400"/>     
<option style="background-color:#a52a2a" value="#a52a2a"/>     
<option style="background-color:#ff1493" value="#ff1493"/>     
</select>
</div>
<div>
<canvas id='canvas1' width='700' height='700' >
Canvas is not supported by this browser.</canvas>
</div>
<script type="text/javascript">
 updateCanvas();
</script>

The JavaScript code for the updateCanvas() function is shown below. The code starts by getting all the selector controls using document.getElementById() using a string argument being the id of the HTML element. It then needs to get the selected index and use that to index the options attached to the control. We then get the text part of the selected option and for the first three selectors, convert the text to a floating point number using the Number() method. For the fourth selector, we get the value rather than the text - reason being the options don't have any text as we just want the background colour displayed. Note the format of the value text is the standard colour format #rrggbb which is the same format used in HTML and for setting canvas values like fillstyle.

JavaScript
function updateCanvas() {
	var c = document.getElementById("canvas1");
	var ctlSpeedRatio = document.getElementById("speedratio");
	var ctlSizeRatio = document.getElementById("sizeratio");
	var ctlSteps = document.getElementById("steps");
	var ctlColour = document.getElementById("color_menu0");
	var speedRatio = 
		Number(ctlSpeedRatio.options[ctlSpeedRatio.selectedIndex].text);
	var sizeRatio = Number(ctlSizeRatio.options[ctlSizeRatio.selectedIndex].text);
	var steps = Number(ctlSteps.options[ctlSteps.selectedIndex].text);
	var colour = ctlColour.options[ctlColour.selectedIndex].value;
	var cxt = c.getContext("2d");
	cxt.beginPath();
	cxt.fillStyle = "#FFEEEE";
	cxt.clearRect(0, 0, 700, 700);
	cxt.fillRect(0, 0, 700, 700);
	cxt.strokeStyle = colour;// "#5555FF";
	var xOrigin = 350;
	var yOrigin = 350;
	var jSize = 320/(sizeRatio + 1);
	var iSize = sizeRatio * jSize;

	//begin drawing
	var n = steps * speedRatio;
	for (var i = 0; i <= n; i++) {
		var f = i * 3.14159265358979 * 2;
		var xi = (iSize * Math.sin(f / n)) + xOrigin;
		var yi = (iSize * Math.cos(f / n)) + yOrigin;

		var xj = (jSize * Math.sin(f / speedRatio));
		var yj = (jSize * Math.cos(f / speedRatio));
		if (i == 0)
			cxt.moveTo(xi + xj, yi + yj);
		else
			cxt.lineTo(xi + xj, yi + yj);
	}
	cxt.stroke();
}

Points of Interest

One thing I did learn is that you need to start your drawing by calling the context's beginpath() method or the canvas won't be erased. I was also surprised by how good the intellisense was in VS2010 in many cases though I note it failed badly in some areas, e.g. listing all the drawing context's methods.

History

This is my first play around with HTML5's canvas element. I hope to bring out some further articles regarding canvas and also SVG.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Product Manager
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Dimiter20114-Feb-19 8:30
Dimiter20114-Feb-19 8:30 
GeneralMy Head! Pin
Brisingr Aerowing30-Aug-12 10:01
professionalBrisingr Aerowing30-Aug-12 10:01 
SuggestionMy vote of 5 Pin
Akram El Assas23-Apr-12 12:11
Akram El Assas23-Apr-12 12:11 
GeneralMy vote of 5 Pin
Jason Hanlin Day14-Nov-11 17:36
Jason Hanlin Day14-Nov-11 17:36 
GeneralMy vote of 5 Pin
Elham M19-Oct-11 3:43
Elham M19-Oct-11 3:43 
This is fascinating!
GeneralMy vote of 5 Pin
SledgeHammer0114-Oct-11 11:37
SledgeHammer0114-Oct-11 11:37 
GeneralMy vote of 3 Pin
Aric Wang9-Oct-11 20:13
Aric Wang9-Oct-11 20:13 
GeneralRe: My vote of 3 PinPopular
Andreas Blohm10-Oct-11 2:18
Andreas Blohm10-Oct-11 2:18 
GeneralRe: My vote of 3 PinPopular
HaBiX10-Oct-11 20:30
HaBiX10-Oct-11 20:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.