In the previous working on canvas post, I explored creating and hit-testing rectangles using the canvas object and JavaScript. This time I'm going to add circles.
Click on the above shapes, get really close to the edges. See if you can catch the hit-test out.
Step 1: Circle drawing function
First of all it is necessary to add a circle drawing function to the code.
function drawCircle(x,y,r,color) { context.beginPath(); // begins new path context.arc(x,y,r,0,2*Math.PI); context.fillStyle=color; context.fill(); // use of fill autocloses a path }
Step 2: Expand switch statement
Next it is necessary to extend the switch statement for the circle:// draw object based on type switch(objType) { case "rectangle": drawRect(objDimensions[0],objDimensions[1],objDimensions[2],objDimensions[3],color); break; case "circle": drawCircle(objDimensions[0],objDimensions[1],objDimensions[2],color); break; default: console.log("undefined"); }
Step 3: Hit-test extended
The hit-test must also be extended to receive the call from the switch statement. The maths here tests the distance of the touch from the origin of the circle, if it is less than the radius it's a hit.// TEST FOR CIRCLE BEGINS else if (objType == "circle") { var a = Math.pow(x-objDimensions[0],2); var b = Math.pow(y-objDimensions[1],2); if (Math.sqrt(a+b)<=objDimensions[2]) { document.getElementById("result").innerHTML="You hit: " + obj["id"]; // break once object has been found break; } } // TEST FOR CIRCLE ENDS
Step 4: Putting it all together
And here's the entire code necessary to replicate the above example:<canvas height="200px" id="square" onclick="hitTest(event)" style="-webkit-tap-highlight-color: rgba(0,0,0,0); border: dotted 1px;" width="200px"></canvas> <div id="result"> </div> <script> var objectArray = [{"rectangle":[50,50,100,150], "color":"lightgreen", "id":"green rectangle"},{"rectangle":[100,150,100,50], "color":"pink", "id":"pink rectangle"},{"circle":[100,150,60,50], "color":"lightblue", "id":"blue circle"},{"circle":[10,150,60,50], "color":"red", "id":"red circle"}]; // array of objects // retrieve canvas and context var canv = document.getElementById("square"); var context = canv.getContext("2d"); // rectangle drawing function function drawRect(x,y,w,h,color) { context.fillStyle=color; context.fillRect(x,y,w,h); } // circle drawing function function drawCircle(x,y,r,color) { context.beginPath(); context.arc(x,y,r,0,2*Math.PI); context.fillStyle=color; context.fill(); // use of fill autocloses a path (see Mozilla Dev) } // retrieve object properties for (i=0;i<=objectArray.length-1; i++) { var keys = Object.keys(objectArray[i]); var objType = keys[0]; var objDimensions = objectArray[i][objType]; var color = objectArray[i]["color"]; // draw objects based on type switch(objType) { case "rectangle": drawRect(objDimensions[0],objDimensions[1],objDimensions[2],objDimensions[3],color); break; case "circle": drawCircle(objDimensions[0],objDimensions[1],objDimensions[2],color); break; default: console.log("undefined"); break; } } function hitTest(e) { // first retrieve event target (i.e. canvas) - this could be tested for equality to canvas if multiple canvases exist var object = e.target; // get test position of hit relative to what's currently in the browser and where the canvas is positioned on the page var rectObject = object.getBoundingClientRect(); var x=e.clientX - rectObject.left; var y=e.clientY - rectObject.top; // detect object clicked, starting with last in array because this will be uppermost for (i=objectArray.length-1; i>=0; i--) { var obj = objectArray[i]; var keys = Object.keys(objectArray[i]); var objType = keys[0]; var objDimensions = obj[objType]; // test for rectangle // TEST FOR RECTANGLE BEGINS if (objType == "rectangle") { if (x >= objDimensions[0] && x <= objDimensions[2] + objDimensions[0] && y >= objDimensions[1] && y <= objDimensions[3] + objDimensions[1]) { document.getElementById("result").innerHTML="You hit: " + obj["id"]; // break once object has been found break;} } // TEST FOR RECTANGLE ENDS // TEST FOR CIRCLE BEGINS else if (objType == "circle") { var a = Math.pow(x-objDimensions[0],2); var b = Math.pow(y-objDimensions[1],2); if (Math.sqrt(a+b)<=objDimensions[2]) { document.getElementById("result").innerHTML="You hit: " + obj["id"]; // break once object has been found break; } } // TEST FOR CIRCLE ENDS document.getElementById("result").innerHTML="Co-ordinates: "+x+", "+y; } } </script>
Comments
Post a Comment