
HTML5′s canvas implementation allows you to draw whatever takes you fancy; be it a thermometer, speedometer, map or compass. This post takes my previous posts one step further and mixes together the techniques used in the aforementioned posts to draw an interactive animated Caesar cipher. In cryptography, a Caesar cipher is one of the simplest and most widely known encryption techniques. It is a substitution cipher in which letters are replaced by a letter some fixed number of positions down the alphabet. For example, with a shift of 4, A would be replaced by E, B would become F, and so on. The method is named after Julius Caesar, who used it in his private correspondence. In this post one will explain how to draw a Caesar Cipher gauge. The gauge will allow a user to input the desired shift. When a shift value is input the Caesar Cipher dial will rotate to represent the new shift.
.
The HTML Source
The following code is stripped to the minimum in order to draw the dial:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Animated Caesar Cipher Wheel</title>
<script src='caesar_cipher.js'></script>
<link rel="stylesheet" type="text/css" href="caesar_cipher.css" media="all" />
</head>
<body onload='init();'>
<canvas id="caesar" width="500" height="500"></canvas>
<input id="shift" type="text" value="00" maxlength="2" onChange="handleShiftChange(this.value)" />
</body>
</html>
The HTML is straight forward. The items of interest are the canvas element, the ‘onload’ event for the body, the script tag and the css link include. For those who are not familiar with HTML let me explain how we draw the dial onto the canvas. When any HTML page loads the browser will run the JavaScript code attached to the onload event of the body tag e.g.
<body onload='init();'>
<script src='caesar_cipher.js'></script>
In order to understand how the ‘init’ function work we need to understand how the browsers locates it. The browser will load any JavaScript code included in a script tag prior to displaying the page to the user e.g.
<script src='caesar_cipher.js'></script>
Therefore, the content of my script “caesar_cipher.js” will be loaded, and thus, the function called ‘init’ will be available. If you were to look inside the aforementioned script you will be able to see the code e.g.
function init()
{
// Grab the compass element
var canvas = document.getElementById('caesar');
// Canvas supported?
if(canvas.getContext('2d'))
{
ctx = canvas.getContext('2d');
// Load the needle image
dial = new Image();
dial.src = 'caesar_cipher_dial.png';
// Load the compass image
img = new Image();
img.src = 'caesar_cipher.png';
img.onload = draw;
// Start the change input monitor timer
setInterval(checkForShiftChange, 1000);
}
else
{
alert("Canvas not supported!");
}
}
The content of the function is quite readable and the code is ordered in logic steps. The first step is to obtain a handle to the canvas element. If the canvas element is found we then proceed to ensure that the browser supports the canvas implementation. Assuming support is implemented the second step is to load the inner and outer dial image resources. The second image – the dial with the letters in the shifted position – is created with an onload event attached. This event informs the browser to call the JavaScript function ‘draw’ directly after the image has loaded. We’ll cover the content of the draw function latter in this post. The final step of the ‘init’ function is to start a timer:
// Start the change input monitor timer
setInterval(checkForShiftChange, 1000);
The timer basically tells the JavaScript engine to execute the function ‘checkForShiftChange’ every second (1000 milliseconds). This function contains the following:
function checkForShiftChange()
{
// Get the angle related to the shift value
var iExpectedAngle = getRequiredAngle();
// If the currect angle is not the expected angle start the timer
if(iExpectedAngle != degrees)
{
if(bTurning)
stopTimer();
// Determine which way the rotation for move
bClockwise = iExpectedAngle > degrees;
// Star the timer
timer = setInterval(draw, 50);
bTurning = true;
}
}
The purpose of the function is to obtain the current shift value from the input box and then convert it to the angle which represents the rotation factor that the outer dial needs to be rotated in order to display the letters in the correct location. The function responsible for converting the shift value to the related angle is called ‘getRequiredAngle’. This contains the following:
function getRequiredAngle()
{
// Grab a handle to the shift input
var shift = document.getElementById('shift');
var iExpectedAngle = 0;
var iShiftInput = 0;
if(shift != null)
{
// Make sure we have a number
iShiftInput = shift.value * 1.0;
// Calculate the expected angle for the shift
iExpectedAngle = Math.floor(((360/26) * (iShiftInput % 26)),0);
}
return iExpectedAngle;
}
The function simply grabs the value input into the ‘shift’ input tag (user driven input). It then converts this to an angle by multiplying it by a factor of 360 divided by 26. The result is then returned to the calling interface. This returned value is used by the ‘checkForShiftChange’ function, it first checks whether the value has changed e.g. do we need to rotate the dial? If a rotation is required the function determines whether the it would be quicker to turn the dial clockwise or anti-clockwise. With this information to hand it then starts another timer which calls the ‘draw’ function every 50 milliseconds. In reality we could simply redraw the dial in at the desired angle; however, it is far more realistic to animate the transition. Thus, the ‘draw’ function increments the angle of the outer dial by 3 degrees every-time the draw function is called e.g.

Once the required angle has been reached, the function stops the timer. As stated above the ‘draw’ function is called once during the initial load and then subsequently for every transition. The code within the draw function is:
function draw()
{
var iExpectedAngle = getRequiredAngle();
calculateNewAngle(iExpectedAngle);
clearCanvas();
// Draw the background onto the canvas
ctx.drawImage(img, 0, 0);
// Save the current drawing state
ctx.save();
// Now move across and down half the image
ctx.translate(245, 264);
// Rotate around this point
ctx.rotate(degrees * (Math.PI / 180));
// Draw the shifted letters
ctx.drawImage(dial, -245, -264);
// Restore the previous drawing state
ctx.restore();
}
The content of the function ascertains the new rotation angle. It then passes the angle into the ‘calculateNewAngle’ function. This function performs a few sanity checks before adjusting the current angle in either a clockwise, or, anti-clockwise direction. The function includes the following:
function calculateNewAngle(iExpectedAngle)
{
// If we've hit the right place stop the timer
if(iExpectedAngle == degrees)
{
stopTimer();
return;
}
if(bClockwise)
{
// Increment the angle of the needle by 5 degrees
degrees += 3;
// Check if we have passed the 0/360 point and adjust
if(degrees > 360)
degrees = 0;
// Check if we have moved past the target
if(degrees > iExpectedAngle)
degrees = iExpectedAngle
}
else
{
// Decrement the angle of the needle by 5 degrees
degrees -= 3;
// Check if we have passed the 0/360 point and adjust
if(degrees < 0)
{
if(iExpectedAngle == 0)
degrees = 0;
else
degrees = 360;
}
// Check if we have moved past the target
if(degrees < iExpectedAngle)
degrees = iExpectedAngle
}
}
This function’s first task is to check whether the target angle has been reached, or, in other terms we have positioned the outer dial in the correct shifted position. If the angle has been reached the function stops the timer and exits. If the later is not true the function then adjusts the current angle in the desired location and returns to the calling interface. The remainder of the ‘draw’ function above then clears the canvas. The background image is then rendered to the canvas and a call to the save context function is made. This saves the drawing state of canvas. The canvas drawing state is basically a snapshot of all the attributes that have been applied to the canvas including the transformations, styles, line widths and clipping regions. By default, none of these are set; thus, we are simply saving the defaults applied to our canvas so we can revert back to them later. The next step deals with the animation. This involves two steps. The first step performs the following translation:
// Now move across and down half the image
ctx.translate(245, 264);
This translation moves the centre point to the middle of the image which happens to be 245 x 264 pixels. By default the rotation is performed on the canvas with the rotation centred at position 0, 0. If we were to simply ask the canvas to rotate at increments of 3 degrees the dials would become miss-aligned. Both images are the same size, thus, they share the same centre point; therefore, by rotating around this common centre point we can move the outer dial to the correct location. The last part of the ‘draw’ function is to restore context back to the default.

Like this:
Like Loading...
2 Comments
Leave a CommentTrackbacks