Sketch for doing hit-testing of arbitrary shapes on a canvas. Checks color of offscreen canvas, which is encoded with an ID# in the red channel. Lower right corner drags resize boxes.
A Pen by Andrew Benson on CodePen.
Sketch for doing hit-testing of arbitrary shapes on a canvas. Checks color of offscreen canvas, which is encoded with an ID# in the red channel. Lower right corner drags resize boxes.
A Pen by Andrew Benson on CodePen.
| <canvas id="cvs" width="1200px" height="800px"></canvas><div id="jim"></div> | |
| <div id="flyover"></div> |
| 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').mousemove(function(e){ | |
| var x = e.pageX-offx; | |
| var y = e.pageY-offy; | |
| var act = getID(x,y); | |
| var fly = $('#flyover'); fly.css('opacity',1.); | |
| fly.css('top',e.pageY+5+'px'); | |
| fly.css('left',e.pageX+20+'px'); | |
| fly.text("ID:"+act); | |
| //$('#flyover').css('opacity',0.); | |
| }); | |
| $('#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); | |
| } | |
| } |
| #flyover { | |
| width: 20px; | |
| height: 10px; | |
| border-radius: 4px; | |
| box-shadow: -3px 3px 5px #555; | |
| background-color: #FBFBFB; | |
| position:absolute; | |
| z-index:2; | |
| top: 0px; | |
| left: 0px; | |
| opacity:0; | |
| font-size:10px; | |
| padding:5px; | |
| transition: opacity 0.3s; | |
| -webkit-transition: opacity 0.3s; | |
| } | |
| canvas { | |
| z-index:1; | |
| } |