Skip to content

Instantly share code, notes, and snippets.

@pixlpa
Forked from anonymous/Draggable-Shapes.markdown
Last active August 29, 2015 13:57
Show Gist options
  • Save pixlpa/9396624 to your computer and use it in GitHub Desktop.
Save pixlpa/9396624 to your computer and use it in GitHub Desktop.
For each shape drawn into a canvas, an offscreen canvas is painted with the same shape, with the red color channel storing an ID. Shape click-testing is done by querying the color of the clicked position in the offscreen canvas. For UI with a lot of shapes (data viz for example) this is much more efficient than looping through and hit testing ba…
var canvas = document.getElementById('cvs'),
c = canvas.getContext('2d'),
ocan = document.createElement("canvas"),
oc = ocan.getContext('2d');
ocan.width=canvas.width;
ocan.height=canvas.height;
var offx = canvas.offsetLeft;
var offy = canvas.offsetTop;
var lastX = 0,lastY=0;
var active = 0;
var boxes = new Array();
for(var i=1;i<60;i++){
if(i<30){
boxes[i]=new uiBox(i,Math.random()*400,Math.random()*200,Math.random()*100,Math.random()*50,randomColor());
boxes[i].draw();
}
else {
boxes[i]=new uiCircle(i,Math.random()*400+400,Math.random()*200,Math.random()*30+5,randomColor());
boxes[i].draw();
}
}
$(document).ready(function(){
$('#cvs').mousedown(function(e){
var x = e.pageX-offx;
var y = e.pageY-offy;
active = getID(x,y);
lastX = x;
lastY = y;
if(active>0){
if (boxes[active].isCorner(x,y)==1){
$(window).bind("mousemove",function(e){
var x = e.pageX-offx;
var y = e.pageY-offy;
if(active>0){
if(active<30){
boxes[active].w += x-lastX;
if(boxes[active].w<5) boxes[active].w = 5;
boxes[active].h += y-lastY;
if(boxes[active].h<5) boxes[active].h = 5;
}
else {
boxes[active].r += x-lastX;
if(boxes[active].r<5) boxes[active].r = 5;
}
lastX = x;
lastY = y;
oc.clearRect(0,0,1200,800);
c.clearRect(0,0,1200,800);
for(var i=1;i<60;i++){
boxes[i].draw();
}
}
});
}
else {
$(window).bind("mousemove",function(e){
var x = e.pageX-offx;
var y = e.pageY-offy;
if(active>0){
boxes[active].x+=x-lastX;
boxes[active].y+=y-lastY;
}
lastX = x;
lastY = y;
oc.clearRect(0,0,1200,800);
c.clearRect(0,0,1200,800);
for(var i=1;i<60;i++){
boxes[i].draw();
}
c.fillStyle = "#888";
});
}
}
$(window).bind('mouseup',function() {
$(this).unbind('mousemove');
active = 0;
oc.clearRect(0,0,1200,800);
c.clearRect(0,0,1200,800);
for(var i=1;i<60;i++){
boxes[i].draw();
}
});
});
});
function getID(x,y){
var p = oc.getImageData(x, y, 1, 1).data;
//use blue channel as reference to
//see if it's a fuzzy edge pixel
if(p[2]==255) return p[0];
else return 0;
}
function randomColor(){
var cc = new Array();
var r = Math.random()*255;
var g = Math.random()*255;
var b = Math.random()*255;
return ((r << 16) | (g << 8) | b).toString(16);;
}
function uiBox(id,x,y,w,h,color){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.id = id;
this.draw = function(){
c.fillStyle = this.color;
oc.fillStyle = 'rgb('+this.id+',0,255)';
c.fillRect(this.x,this.y,this.w,this.h);
oc.fillRect(this.x,this.y,this.w,this.h);
}
this.isCorner = function(l,t){
var checkx = l > (this.x+this.w-10);
var checky = t > (this.y+this.h-10);
return (checkx&&checky);
}
}
function uiCircle(id,x,y,r,color){
this.x = x;
this.y = y;
this.r = r;
this.color = color;
this.id = id;
this.draw = function(){
c.fillStyle = this.color;
oc.fillStyle = 'rgb('+this.id+',0,255)';
c.beginPath();
oc.beginPath();
c.arc(this.x,this.y,this.r, 0, 2 * Math.PI, false);
oc.arc(this.x,this.y,this.r, 0, 2 * Math.PI, false);
c.closePath();
oc.closePath();
c.fill();
oc.fill();
}
this.isCorner = function(l,t){
var checkx = l > (this.x+this.r-10);
return (checkx);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment