While working for a cross platform hybrid app, I had the requirement of drawing draggable shapes on Canvas. I came across many JavaScript Canvas Libraries such as jCanvas, which suited the purpose. However, I finally settled down for CreateJS.
In this post, I will show how I created draggable shapes such as circle, rectangles and star on Canvas with EaselJS, part of CreateJS library for drawing on Canvas.
About CreateJS
CreateJS comes with a wide set of libraries called EaselJS (drawing on canvas), TweenJS (animating on canvas), SoundJS (playing sound with javascript) & PreloadJS (preloading assets like sounds, images). Together they are capable of powering your next cross-platform hybrid app or game built on HTML5 Canvas. These libraries are designed to work completely independently.
In this post, I will just be using EaselJS for drawing shapes and making them draggable upon mouse or touch interactions.
Creating shapes on Canvas with EaselJS
In HTML, we need to define our canvas and give it a suitable id so that we can refer it in JavaScript. Also we hook onto the body onload event to initate our work. We link up the createjs library from the createjs CDN. That is all we need to put into our HTML as most of the work will be done in JavaScript.
<script src="http://code.createjs.com/createjs-2013.12.12.min.js"></script> <body onload="init();"> <canvas id="canvas" width="500" height="500"></canvas> </body> <!--html file-->
Scale Canvas to full width & height
The first thing that I will do in JavaScript init() method is to scale the canvas to occupy full width and height. This way we will make sure that our canvas is able to dynamically adjust to the screen size of user. This is done using the code below:
var canvas = document.getElementsByTagName('canvas')[0]; canvas.width = window.innerWidth; canvas.height = window.innerHeight; //scale canvas
Note that the above code will ensure canvas resize to full screen only once i.e. upon load of html document in clients browser. If you need to adjust canvas upon every windows resize, you may want to hook onto onresize event to execute this piece of code.
Draw Geometrical Shapes on canvas
CreateJS allows us to easily draw geomterical shapes on canvas with desired size, fill and position. In order to do that, we need to first initialize a stage object with our canvas, then we create shape objects and ask CreateJS to draw the desired shape for this shape object. Afterwards we add these shape objects to the stage and call stage.update() which will do the actual drawing in the canvas.
Below you can see JavaScript code for creating and drawing circle shape which is then added to the stage. For code used to draw other shapes, please refer to the codepen for this post.
function addCircle(x, y, r, fill) { var circle = new createjs.Shape(); circle.graphics.beginFill(fill).drawCircle(0, 0, r); circle.x = x; circle.y = y; circle.name = "circle"; circle.on("pressmove", drag); stage.addChild(circle); } //drawing circle and adding to stage
Making shapes draggable
As you will notice, I have registered drag function with the “pressmove” event with every shape. This will allow us to listen to the drag event on shapes and update the co-ordinates of our shape at the touch point. Since all the drawn objects are a Shape object, we use a single drag function shown below. I had to handle the square shape separately as the anchor point for square shapes is top-left.
function drag(evt) { // target will be the container that the event listener was added to if(evt.target.name == "square") { evt.target.x = evt.stageX - SIZE; evt.target.y = evt.stageY - SIZE; } else { evt.target.x = evt.stageX; evt.target.y = evt.stageY; } // make sure to redraw the stage to show the change stage.update(); } //handle drag of shapes
Draggable Shapes Demo
See the Pen Drawing draggable shapes on Canvas by Kanishk Kunal on CodePen.
Hi Kanishk Kunal,
Thanks for you post.
I would like to ask: how can dynamic resize shape (square) ?
You need to call square.graphics.clear().beginFill(fill).drawRoundRect(0, 0, s, s, r) with new dimensions followed by stage.update() to change the shape of the square.
Kanishk,
I have achieved what you have demonstrated, however, is there a way to track the percentage two objects overlap? I am trying to track the percentage of two circles overlapping. Then track all three circles overlapping.
Hi Mark, It is possible to find the area overlapped by circles. You can use the circle’s center and radius to do the calculation as show here: http://mathworld.wolfram.com/Circle-CircleIntersection.html
That helps a ton! Thank you.
Hi Kanishk,
Thank you for this, it was super useful! I’m wondering if you knew an easy trick to automatically reset the layout to the default position after, say, three “drags”?
Hi Gaelle, you can achieve this by storing the initial center position of the shapes and then moving them back to the initial position after three drags. You can listen to the ‘pressup’ event to detect the third drag. Check out the EaselJS mouse interaction tutorial for more information: http://www.createjs.com/tutorials/Mouse%20Interaction/
Have you had a look at https://konvajs.github.io/ ? Im about to do a project and thinking about using it rather than createjs.
Hello Louie, I have not tried Konva, but it does look promising.