Quantcast
Viewing latest article 9
Browse Latest Browse All 10

Create a HTML5 canvas element with clickable elements

Image may be NSFW.
Clik here to view.
Canvas with clickable circles

A client asked me to implement a website with different images having clickable circles on top of them. The circles would be placed randomly – and would be used to display additional information about what was going on in that particular place in the image.

Fortunately, the client did not require that users with older browser should be able to view the website. So I was able to use some modern technology in order to make my life a bit easier.

I have never worked with the HTML5 canvas-element before. So I needed to get some hands-on experience with it. I therefore decided to create a proof-of-concept first. You can see this proof-of-concept in the following fiddle: http://jsfiddle.net/Terkildsen/9pgWf/

The following is a quick walk-through of the elements in the code. First, I start off with a canvas element:

  <body>
    <canvas id="myCanvas" width="1420" height="702"></canvas>
  </body>

After that, I create a reference to the canvas-element in my JavaScript – and initialize a circles-array that will hold information about each circle:

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var circles = [];

Then I implement a function to handle the drawing of each circle. The function will accept a reference to the canvas-element (context), the x- and y-position of the circle, the fillcolor, radius, and different other parameters necessary to draw the circle. The circle is drawn by using the context.arc-method – which is documented right here: http://www.html5canvastutorials.com/tutorials/html5-canvas-arcs/

var draw = function (context, x, y, fillcolor, radius, linewidth, strokestyle, fontcolor, textalign, fonttype, filltext) {
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fillStyle = fillcolor;
    context.fill();
    context.lineWidth = linewidth;
    context.strokeStyle = strokestyle;
    context.stroke();
    
    context.fillStyle = fontcolor;
    context.textAlign = textalign;
    context.font = fonttype;
    
    context.fillText(filltext, x, y);    
};

Now I create an object that will hold the position of each circle – this information is used later on for deciding whether or not the user clicked on the circle

var Circle = function(x, y, radius) {
    this.left = x - radius;
    this.top = y - radius;
    this.right = x + radius;
    this.bottom = y + radius;
};

I then create a drawCircle-method that will call the draw-method – in order to draw the circle – and that will store the position of each new circle.

var drawCircle = function (context, x, y, fillcolor, radius, linewidth, strokestyle, fontcolor, textalign, fonttype, filltext, circles) {
    draw(context, x, y, fillcolor, radius, linewidth, strokestyle, fontcolor, textalign, fonttype, filltext);
    var circle = new Circle(x, y, radius);
    circles.push(circle);  
};

Now I can add my circles – naturally, this would come from a database containing the texts as well as the coordinates of each circle.

drawCircle(context, 300, canvas.height / 2, "green", 40, 5, "#003300", "white", "center", "bold 32px Arial", "1", circles);
drawCircle(context, 600, canvas.height / 3, "blue", 50, 5, "#003300", "white", "center", "bold 32px Arial", "2", circles);

And then, finally, I add a jQuery-method that will bind to the click-event, and decide which circle – if any – the user clicked. Here, I use the previously stored information about each circles’ position to calculate whether or not the user clicked a certain circle. Right now, I just alert some dummy text – but I will add a method to display additional information.

$('#myCanvas').click(function (e) {
    var clickedX = e.pageX - this.offsetLeft;
    var clickedY = e.pageY - this.offsetTop;
    
    for (var i = 0; i < circles.length; i++) {
        if (clickedX < circles[i].right && clickedX > circles[i].left && clickedY > circles[i].top && clickedY < circles[i].bottom) {
            alert ('clicked number ' + (i + 1));
        }
    }
});

That’s it – for a complete working sample please go to http://jsfiddle.net/Terkildsen/9pgWf/


Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.

Viewing latest article 9
Browse Latest Browse All 10

Trending Articles