Selectable Shapes Part 2: Resizable, Movable Shapes on HTML5 Canvas

We explored using keyboard input to move a shape on an HTML5 canvas here http://html5.litten.com/moving-shapes-on-the-html5-canvas-with-the-keyboard/. Now we’ll take a look at using input from the mouse. With a few simple calculations, you can drag and drop shapes on the canvas with your mouse.

HTML

<div id="container2">
    <canvas id="canvas2" width="400" height="300">
    This text is displayed if your browser does not support HTML5 Canvas.
    </canvas>
    </div>
    <div style="font-family: Verdana; font-size: 12px;">
    <p>Click to select. Click on selection handles to resize. Double click to create a new node.</p>
<p>
    <a href="http://simonsarris.com/blog/225-canvas-selecting-resizing-shape">link to tutorial</a>
    </p><p>
    <a href="http://simonsarris.com/blog/140-canvas-moving-selectable-shapes">link to tutorial part 1</a>
    </p>
    </div>

CSS

#container2 { position: relative; }
#canvas2 { border: 1px solid #000; }

JavaScript

// Last updated November 2010 by Simon Sarris
// www.simonsarris.com
// [email protected]
//
// Free to use and distribute at will
// So long as you are nice to people, etc

// This is a self-executing function that I added only to stop this
// new script from interfering with the old one. It's a good idea in general, but not
// something I wanted to go over during this tutorial
(function(window) {


// holds all our boxes
var boxes2 = []; 

// New, holds the 8 tiny boxes that will be our selection handles
// the selection handles will be in this order:
// 0  1  2
// 3     4
// 5  6  7
var selectionHandles = [];

// Hold canvas information
var canvas;
var ctx;
var WIDTH;
var HEIGHT;
var INTERVAL = 20;  // how often, in milliseconds, we check to see if a redraw is needed

var mx, my; // mouse coordinates

 // when set to true, the canvas will redraw everything
 // invalidate() just sets this to false right now
 // we want to call invalidate() whenever we make a change
var canvasValid = false;

// The node (if any) being selected.
// If in the future we want to select multiple objects, this will get turned into an array
var mySel = null;

// The selection color and width. Right now we have a red selection with a small width
var mySelColor = '#CC0000';
var mySelWidth = 2;
var mySelBoxColor = 'darkred'; // New for selection boxes
var mySelBoxSize = 2;

// we use a fake canvas to draw individual shapes for selection testing
var ghostcanvas;
var gctx; // fake canvas context

// since we can drag from anywhere in a node
// instead of just its x/y corner, we need to save
// the offset of the mouse when we start dragging.
var offsetx, offsety;

// Padding and border style widths for mouse offsets
var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;




// Box object to hold data
function Box2() {
  this.x = 0;
  this.y = 0;
  this.w = 1; // default width and height?
  this.h = 1;
  this.fill = '#444444';
}

// New methods on the Box class
Box2.prototype =...