News

Animated eCards with HTML5

Animated eCards with HTML5

Create seasonal animated eCards using the all new <canvas> element

Hail HTML5! With the advent of the <canvas> tag, we can use simple JavaScript to achieve Flash-like animated eCards quickly and easily.

Animated eCards have traditionally been created with Flash. This is because there hasn’t really been any alternative that can offer the same degree of control, ease-of-use and browser compatibility. Happily there is now a usable alternative with a smaller code footprint, and the chances are you’re using a compatible browser already (only IE doesn’t yet support the tag). Part of the new HTML5 specification, the <canvas> tag allows us to create text and graphics directly onto a canvas space inside the browser window. Using the power of JavaScript with libraries such as jQuery, we can create interactive animations and advanced functionality such as real-time stock charts. You don’t need to learn a new language or skill to do this; if you’ve got a basic understanding of HTML and JavaScript, you can create animations today!

In this tutorial we’re going to create a very basic animated eCard that can be sent to a friend with a custom message. To avoid complicating the issue we’re going to do this without any databases or special server requirements.

Project files for this tutorial can be downloaded here.

This article was originally authored by Sam Hampton-Smith and featured within Web Designer issue 165

01 Create your canvas

Create a new web document and enter the code below. This code creates a basic HTML page with a simple <canvas> tag. You’ll need to download the jQuery framework from www.jquery.com and save it into a sub folder called “Scripts”, or change the link in the code to the location you’ve saved the jQuery file to:

<html>
 <head>
 <title>Seasonal Greetings</title>
 <script type=”text/javascript” src=”scripts/jquery-
 1.3.2.min.js”></script>
 <script type=”text/javascript”>
 function init() {
var canvas = document.getElementById(“greetings”); 
 if (canvas.getContext){
 var ctx = canvas.getContext(‘2d’);
 draw(ctx);
 } else {
 // canvas-unsupported code here
 alert(“sorry, can’t display the card”);
 }
 }
 function draw(ctx) {
 }
 $(document).ready(function(){
 init();
 });
 </script>
 </head>
 <body>
 <canvas id=”greetings” width=”600”
 height=”400”>I’m sorry, your browser can’t display this eCard</canvas>
 </body>
 </html>

02 Basic shapes

The code we have got as a starting point includes a couple of functions in JavaScript that we’ll need throughout the tutorial. We’ll start off with something simple – we’re going to create a large rectangle of colour to fill our canvas area. Add the following code inside the draw() function:

var lingrad = ctx.createLinearGradient(0,0,0,400);
 lingrad.addColorStop(0, ‘#4280c3’);
 lingrad.addColorStop(1,
 ‘#45bbed’);
 ctx.fillStyle = lingrad;
 ctx.fillRect (0, 0, 600, 400);

03 Loading images

The object named ctx represents our canvas, and to interact with the canvas we need to call methods associated with that object. The code you just added calls the fillRect method which created a filled rectangle with the gradient we created in the lines above as the fill. Let’s do something a little more ambitious. Add the code below to load in a snowflake image (you’ll find these images ):

var img = new Image();
 img.onload = function(){ ctx.
 drawImage(img, 100, 100); }
 img.src = “WFlakeBig.png”;

04 Abstracting position

You should now have a nice big snowflake sitting in the middle of the canvas (at co-ordinates 100×100). We can change the position of the image by altering these co-ordinates, and abstract them into variables named x1 and y1. Change your code to view as follows (new code shown in bold):

var x1 = 0;
 var y1 = 200;
 img = new Image();
 img.src = “WFlakeBig.png”;
function init() {
 var canvas = document.getElementById(“greetings”);
 if (canvas.getContext){
 var ctx = canvas.getContext(‘2d’);
 draw(ctx);
 } else {
 // canvas-unsupported code here
 alert(“sorry, can’t display the card”);
 }
 }
function draw(ctx) {
 var lingrad = ctx.
 createLinearGradient(0,0,0,400);
 lingrad.addColorStop(0, ‘#4280c3’);
 lingrad.addColorStop(1, ‘#45bbed’);
 ctx.fillStyle = lingrad;
 ctx.fillRect (0, 0, 600, 400);
 ctx.drawImage(img, x1, y1);
 }
$(document).ready(function(){
 init();
 });

05 Animating

In order to make the image move across our canvas we need to update and redraw the canvas frequently, creating the illusion of movement. We do this by changing the position variables for the image, and calling the draw function using setInterval() – a built-in function that executes code at specified intervals. Add the code below to see an animation in practice:

var x1 = 0;
 var y1 = 200;
 img = new Image();
 img.src = “WFlakeBig.png”;
function init() {
 var canvas = document.getElementById(“greetings”);
 if (canvas.getContext){
 var ctx = canvas.getContext(‘2d’);
 setInterval(function(){draw(ctx)},10);
 } else {
 // canvas-unsupported code here
 alert(“sorry, can’t display the card”);
 }
 }
function draw(ctx) {
 y1-y1+1;
 if (y1>400) y1=-200;
 var lingrad = ctx.
 createLinearGradient(0,0,0,400);
 lingrad.addColorStop(0, ‘#4280c3’);
 lingrad.addColorStop(1, ‘#45bbed’);
 ctx.fillStyle = lingrad;
 ctx.fillRect (0, 0, 600, 400);
 ctx.drawImage(img, x1, y1);
 }
$(document).ready(function(){
 init();
 });

06 Build multiple levels

Add the same block of code multiple times to load and position several of these images across the canvas. For each different instance of the snowflake select a different starting location. Build up an additional five or six snowflakes so that you have a good spread of flakes across the canvas space; remember that when they disappear they’ll be recycled at the top:

var x1 = 0;
 var y1 = 200;
 var x2 = 0;
 var y2 = 200;
 var x3 = 0;
 var y3 = 200;
 var x4 = 0;
 var y4 = 200;
 var x5 = 0;
 var y5 = 200;
 var x6 = 0;
 var y6 = 200;
 img = new Image();
 img.src = “WFlakeBig.png”;
 img2 = new Image();
 img2.src = “WFlakeBig.png”;
 img3 = new Image();
 img3.src = “WFlakeBig.png”;
 img4 = new Image();
 img4.src = “WFlakeBig.png”;
 img5 = new Image();
 img5.src = “WFlakeBig.png”;
 img6 = new Image();
 img6.src = “WFlakeBig.png”;
 function init() {
 var canvas = document.getElementById(“greetings”);
 if (canvas.getContext){
 var ctx = canvas.getContext(‘2d’);
 setInterval(function(){draw(ctx)},10);
 } else {
 // canvas-unsupported code here
 alert(“sorry, can’t display the card”);
 }
 }
 function draw(ctx) {
 y1=y1+1;
 if (y1>400) y1=-200;
 y2=y2+1;
 if (y2>400) y2=-200;
 y3=y3+1;
 if (y3>400) y3=-200;
 y4-y4+1;
 if (y4>400) y4=-200;
 y5=y5+1;
 if (y5>400) y5=-200;
 y6=y6+1;
 if (y6>400) y6=-200;
var lingrad = ctx.createLinearGradient(0,0,0,400);
 lingrad.addColorStop(0, ‘#4280c3’);
 lingrad.addColorStop(1, ‘#45bbed’);
 ctx.fillStyle = lingrad;
 ctx.fillRect (0, 0, 600, 400);
 ctx.drawImage(img, x1, y1);
 ctx.drawImage(img2, x2, y2);
 ctx.drawImage(img3, x3, y3);
 ctx.drawImage(img4, x4, y4);
 ctx.drawImage(img5, x5, y5);
 ctx.drawImage(img6, x6, y6);
}  
$(document).ready(function(){
 init();
 });

07 Load different images

Step07

We have included a total of three different colours of snowflake on the disc, and each is available in two sizes, so change your code above to load different images for different snowflakes. This will help reduce the monotony of the eCard.

08 Add different speeds

Step08

As well as different sizes and colours of snowflake, if we alter the speed they fall at we’ll create a nice feeling of depth and believability to our simple scene. Luckily this is very easy because of the way we’ve designed our code; the flakes have a speed value which we can alter to affect how quickly they fall. Experiment with setting different flakes to have values between one and five.

09 Add text

We’d like to add a personal message that appears during the animation. We can affect where this appears in the apparent z-index by putting the code to draw it in the middle of our bunch of snowflakes. Add the following code to insert a message after one second (100 ten millisecond cycles):

var x1 = 0;
 var y1 = 200;
 var x2 = 0;
 var y2 = 200;
 var x3 = 0;
 var y3 = 200;
 var x4 = 0;
 var y4 = 200;
 var x5 = 0;
 var y5 = 200;
 var x6 = 0;
 var y6 = 200;
img = new Image();
 img.src = “WFlakeBig.png”;
 img2 = new Image();
 img2.src = “WFlakeBig.png”;
 img3 = new Image();
 img3.src = “WFlakeBig.png”;
 img4 = new Image();
 img4.src = “WFlakeBig.png”;
 img5 = new Image();
 img5.src = “WFlakeBig.png”;
 img6 = new Image();
 img6.src = “WFlakeBig.png”;
 var counter = 0;
 var messagetodisplay = “Happy New Year!”;
 function init() {
 var canvas = document.getElementById(“greetings”);
 if (canvas.getContext){
 var ctx = canvas.getContext(‘2d’);
 setInterval(function(){draw(ctx)},10);
 } else {
 // canvas-unsupported code here
 alert(“sorry, can’t display the card”);
 }
 }
function draw(ctx) {
 counter = counter + 1;
 y1=y1+1;
 if (y1>400) y1=-200;
 y2=y2+1;
 if (y2>400) y2=-200;
 y3=y3+1;
 if (y3>400) y3=-200;
 y4-y4+1;
 if (y4>400) y4=-200;
 y5=y5+1;
 if (y5>400) y5=-200;
 y6=y6+1;
 if (y6>400) y6=-200;
var lingrad = ctx.createLinearGradient(0,0,0,400);
 lingrad.addColorStop(0, ‘#4280c3’);
 lingrad.addColorStop(1, ‘#45bbed’);
 ctx.fillStyle = lingrad;
 ctx.fillRect (0, 0, 600, 400);
 ctx.drawImage(img, x1, y1);
 ctx.drawImage(img2, x2, y2);
 ctx.drawImage(img3, x3, y3);
 ctx.drawImage(img4, x4, y4);
 ctx.drawImage(img5, x5, y5);
 ctx.drawImage(img6, x6, y6);
 if (counter>100) {
 ctx.font = “40px Times New Roman”;
 ctx.fillStyle = “rgba(255,255,255,1)”;
 ctx.fillText(messagetodisplay, 130, 200);
 }
 }
 $(document).ready(function(){
 init();
 });

10 Animate opacity

The text currently just appears all of a sudden. We can reduce the harshness of this effect by animating the opacity of the text as it appears. Change the code you just added so that it has its own cycle as shown in the code below. Note how we’re setting the opacity of the text to animate from zero to one:

var x1 = 0;
 var y1 = 200;
 var x2 = 0;
 var y2 = 200;
 var x3 = 0;
 var y3 = 200;
 var x4 = 0;
 var y4 = 200;
 var x5 = 0;
 var y5 = 200;
 var x6 = 0;
 var y6 = 200;
 img = new Image();
 img.src = “WFlakeBig.png”;
 img2 = new Image();
 img2.src = “WFlakeBig.png”;
 img3 = new Image();
 img3.src = “WFlakeBig.png”;
 img4 = new Image();
 img4.src = “WFlakeBig.png”;
 img5 = new Image();
 img5.src = “WFlakeBig.png”;
 img6 = new Image();
 img6.src = “WFlakeBig.png”;
 var textopacity = 0;
 var counter = 0;
 var messagetodisplay = “Happy New Year!”;
 function init() {
 var canvas = document.getElementById(“greetings”);
 if (canvas.getContext){
 var ctx = canvas.getContext(‘2d’);
 setInterval(function(){draw(ctx)},10);
 } else {
 // canvas-unsupported code here
 alert(“sorry, can’t display the card”);
 }
 }
 function draw(ctx) {
 counter = counter + 1;
 y1=y1+1;
 if (y1>400) y1=-200;
 y2=y2+1;
 if (y2>400) y2=-200;
 y3=y3+1;
 if (y3>400) y3=-200;
 y4-y4+1;
 if (y4>400) y4=-200;
 y5=y5+1;
 if (y5>400) y5=-200;
 y6=y6+1;
 if (y6>400) y6=-200;
 var lingrad = ctx.
 createLinearGradient(0,0,0,400);
 lingrad.addColorStop(0, ‘#4280c3’);
 lingrad.addColorStop(1, ‘#45bbed’);
 ctx.fillStyle = lingrad;
 ctx.fillRect (0, 0, 600, 400);
 ctx.drawImage(img, x1, y1);
 ctx.drawImage(img2, x2, y2);
 ctx.drawImage(img3, x3, y3);
 ctx.drawImage(img4, x4, y4);
 ctx.drawImage(img5, x5, y5);
 ctx.drawImage(img6, x6, y6);
 if (counter>100) {
 ctx.font = “40px Times New Roman”;
 if (textopacity<100) textopacity = textopacity + 1;
 showopacity = textopacity/100; ctx.fillStyle =
 “rgba(255,255,255,”+showopacity+”)”;
 ctx.fillText(messagetodisplay, 130, 200);
 }
 }
$(document).ready(function(){
 init();
 });

11 Test and review

Step11

Save your file and test it in your browser (remember this won’t work in IE). You should see a continuous animation of falling snowflakes and the message Happy New Year! animating from zero to 100 per cent opacity over the course of about a second. The hard work is now all done!

12 Make it customisable

In order to allow users to send their own customisable eCards we need to make the card customisable in some way. The easiest way to achieve this is by allowing users to add their own message to the card. We’ve been using a string variable to store the message that gets displayed in the card, so to alter the message to a customisable message we simply need to update that value. Try changing the message to check this works:

var messagetodisplay=”This is a test”;

13 Accepting user input

Step13

We’re going to allow users to fill in a form to send this eCard to their friends. We’ll use PHP to get the contents of the form and generate an email. Inside the email there will be a link that encodes the value of the message the user wants to send, and when the link is clicked, that value will be inserted as the message to be displayed.

14 Create an HTML form

To send our eCard we need to collect the data to be included in the card and the address to send the card to. It would also help to avoid spam-traps if we record the name and email address of the user sending the card. Add the following code beneath your <canvas> tag to create a form that collects the data we need.

<h1>Send this eCard to a friend!</h1>
 <form action=”sendmail.php” method=”post”>
 <label>Your Name:<input type=”text”
 name=”yourname” /></label>
 <label>Your Email:<input type=”text”
 name=”youremail” /></label>
 <label>Friend Name:<input type=”text”
 name=”theirname” /></label>
 <label>Friend Email:<input type=”text”
 name=”theiremail” /></label>
 <label>Message to display: <input type=”text”
 name=”message” /></label>
 <label><input type=”submit” value=”Send this
 eCard” /></label>
 </form>

15 PHP sendmail

Now we’ve got our form collecting the data, we need to construct our email and send it off to the recipient. To do this we’re using the most basic of PHP sendmail implementations – this isn’t production-ready code, and you should use your preferred email sending language and script. For the purposes of this tutorial though, create a file called sendmail.php and paste the following code into the file:

<?php
 // Send an email based on form submission
 $url = “http://www.yourdomain.com/index.
 php?msg=”.urlencode($_POST[“message”]);    $to =
 $_POST[“theiremail”];
 $subject = $_POST[“yourname”].” has sent you an
 eCard!”;
 $body = “Please click on this link to view your card:
 “.$url;
 if (mail($to, $subject, $body)) {
 echo(“<p>Message successfully sent!</p>”);
 } else {
 echo(“<p>Message delivery failed...</p>”);
 }
 ?>

16 How we created a link

Step16

Our PHP page collects the data and emails it off, but we need to do a little bit of manipulation to the submitted data to construct a successful link the recipient can click on to receive their card. This is a low-tech solution as we could have stored the data in a database, but for very simple applications this approach will suffice.

17 Grab variables from a URL

Step17

Back in our eCard page we need to grab the variables from the querystring (the bit after the ? in the page address) and use these to provide the values for the message string. Add the code below to use PHP to grab the values and set the variables with this data (note that you’ll need to save your HTML document with a .php extension, it’ll no longer work when you test it locally):

var messagetodisplay = ‘<?php if(isset($_GET[“msg”])
 && $_GET[“msg”] != “”)  echo($_GET[“msg”]); ?>’;
 if (messagetodisplay==””) messagetodisplay =
 “Happy New Year!”;

18 Add some style

Our form is looking pretty ugly, so add a bit of style to suit your eCard and page by using CSS. What you do here will be determined by the style of your pages. In our case we’re just tidying up the way the form is displayed to make it a little more presentable. Add the CSS below to your style sheet:

<style>
 body {
 font-family:    arial, helvetica, sans-serif;
 font-size:    62.5%;
 color:        black;
 background:    white;
 }
#greetings {
 border:        2px solid #4280c3;
 width:        600px;
 position:    relative;
 margin:        auto;
 }
label {
 font-size:    1.4em;
 padding:    5px;
 float:        left;
 clear:        left;
 display:    block;
 width:        480px;
 }
input {
 font-size:    1.4em;
 padding:    5px;
 float:        right;
 clear:        right;
 }
 </style>

19 Play the animation

Step19

We can play the functionality by appending our own variable values to the querystring – try entering index.php?msg=Hello%20there%20Old%20Chum to see the value passed into the animation. Make sure this is working before you proceed to the final steps; if not, check your PHP above (or substitute for ASP, or ASP.NET as appropriate for your server).

20 Test functionality

Step20

Upload all the files to your webspace and load the page up in your web browser. The animation will play with the default value of “Happy New Year!” as the message. Complete the form and send yourself an email to check that you both get the email, and that when you click on the link it opens up in your browser successfully.

21 Test in different browsers

Step21

Don’t forget to test your eCard in lots of different browsers – this should work in Opera, Safari and Firefox 1.5+. Don’t forget to add meaningful alternative content for Internet Explorer users inside the opening and closing <canvas> tags – this will be displayed on any non-compatible browser.

22 Take it to the next level

Step22

We’ve really only scratched the surface of what’s possible using the <canvas> tag and some basic JavaScript; we could have created the snowflake graphics entirely using canvas methods. Why not create a seasonal card with more complex animations, or the ability for a user to load their own images to be animated?

×