javascripthtmlcanvaspath-2d

Use of isPointInPath() to reference Path2D objects?


So I've gotten pretty excited about the introduction of Canvas Paths as standard objects in contemporary browsers, and have been trying to see how much mileage I can get out of this new-ish feature. However, my understanding of how these objects interact with the isPointInPath() method (and possibly other path-based methods) is apparently somewhat flawed.

As demonstrated in the first two test functions below, I can get the drawn paths to be recognized by the isPointInPath() method. However, when I define the paths as an object, the method ceases to work (even though the path objects can be recognized for other purposes such as filling).

function startGame(){ //Initiating Environment Variables
	gamemap = document.getElementById("GameMap")
	ctx = gamemap.getContext("2d")
	testCircleBounds()
	testVarCircleBounds()
	testObjCircleBounds()
	testMultiObjCircleBounds()
}

function testCircleBounds() { //Minimalist Test of Path Methods
	ctx.beginPath()
	ctx.arc(250,250,25,0,2*Math.PI)
	console.log(ctx.isPointInPath(250,250)) //point in path detected
	ctx.closePath()
	console.log(ctx.isPointInPath(250,250)) //point in path still detected
	ctx.stroke()
	ctx.fillStyle = "yellow"
	ctx.fill() //fills great
}

function testVarCircleBounds() { //Test of Path Methods with Variables
	x_cen = 250; y_cen = 250; rad = 15
	ctx.beginPath()
	ctx.arc(x_cen,y_cen,rad,0,2*Math.PI)
	ctx.closePath()
	console.log(ctx.isPointInPath(x_cen,y_cen)) //true yet again
	ctx.stroke()
	ctx.fillStyle = "orange"
	ctx.fill() //also fills great
}

function testObjCircleBounds() { //Test of Path Methods with Single Stored Path Object
	x_cen = 250; y_cen = 250; rad = 10
	ctx.beginPath()
	lonely_node = new Path2D()
	lonely_node.arc(x_cen,y_cen,10,0,2*Math.PI)
	ctx.closePath()
	console.log(ctx.isPointInPath(x_cen,y_cen)) //point in path not found!
	ctx.stroke(lonely_node)
	ctx.fillStyle = "red"
	ctx.fill(lonely_node) //but ctx.fill notices the path just fine
}


function testMultiObjCircleBounds(){ //Test of Paths Methods with Multi-Object Referencing
	nodes = [] //initializes set of nodes as array
	for (i=0; i<25; i++) { //generates 25 nodes
		nodes[i] = new Path2D() //defines each node as Path object in the array
		node = nodes[i]
		//Places Nodes along the 'horizon' of the map
		x_cen = 20*i + 10
		y_cen = 100
		ctx.beginPath(node) //"node" argument probably not helping?
		node.arc(x_cen,y_cen,8,0,2*Math.PI)
		console.log(ctx.isPointInPath(x_cen,y_cen)) //still returns false!
		ctx.closePath(node)
		ctx.stroke(node)
		console.log(ctx.isPointInPath(x_cen,y_cen)) //arrgh!!
	}
	// Fill can also be selectively applied to referenced path objects
	for (i=0; i<25; i=i+2) {
		ctx.fill(nodes[i])
	}
		
}
<!DOCTYPE html>
<html>
<head>
<title>Wrap Around Beta</title>
<script src="Circuity_PathObjectTest.js"></script>
</head>

<body onload='startGame()'>
	
<canvas id="GameMap" width="500" height="500" style="border:1px solid #000000"></canvas>

</body>

</html>

Is this fundamentally the wrong way to think about Path2D objects and to record 'hit' areas on a canvas? If so, is there another technique (saving the canvas context for each path drawn or something along that vein) that would produce the desired effect?


Solution

  • You must send a reference to the Path2D being tested into isPointInPath:

    ctx.isPointInPath( lonely_node, x_cen, y_cen )