如何在点击上进行面向对象的canvas元素比较?

时间:2017-03-23 03:46:37

标签: javascript object canvas

最终我想知道在画布中点击了哪个对象,我编写了脚本:

  dist.push(Math.abs(x-ball1.x-88.5) + Math.abs(y-ball1.y-110));
  dist.push(Math.abs(x-ball2.x-88.5) + Math.abs(y-ball2.y-110));
  dist.push(Math.abs(x-ball3.x-88.5) + Math.abs(y-ball3.y-110));
  function sortNumber(a,b) {
    return a - b;
  }
  dist.sort(sortNumber);

显然这只给我一些数字,但我需要它与ball1,ball2和ball3连接。我想我可以为此嵌套一个阵列,但我还没有想出逻辑...

或者我的方法可能从一开始就错了?

P.S。,显然如果我只有三个球,我可以这样做:

var b1d = Math.abs(x-ball1.x-88.5) + Math.abs(y-ball1.y-110);
  var b2d = Math.abs(x-ball1.x-88.5) + Math.abs(y-ball1.y-110);
  var b3d = Math.abs(x-ball1.x-88.5) + Math.abs(y-ball1.y-110);
  dist.push(b1d, b2d, b3d);
  function sortNumber(a,b) {
    return a - b;
  }
  dist.sort(sortNumber);
  if (dist[0] == b1d) {
    alert('b1');
  } else if (dist[0] == b2d) {
    alert('b2');
  } else if (dist[0] == d3d) {
    alert('b3');
  } else {
    alert('####');
  }

但如果我有数百个球,这可能不是最好的方式......

1 个答案:

答案 0 :(得分:2)

你的搜索方式取决于你对球的处理方式,以及你如何放置它们。

这是一个简单的示例,您可以单击一个球并将其置于前台。 我们创造了200个球。

为了找到正确的球,我们开始搜索一次排序的数组,基于球的z-index(从背面的球到叶子上的球),因为你不能点击球在后面,我们从数组的最后一个元素开始搜索。

在这个例子中,这是一个很好的解决方案,但在你的应用程序中它可能不是,它取决于许多事情,比如球是否重叠,或者如果不是随机的。

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

var getRandomColor = function() {
	// Code from : http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript
	var letters = '0123456789ABCDEF';
	var color = '#';
	for (var i = 0; i < 6; i++ ) {
		color += letters[Math.floor(Math.random() * 16)];
	}
	return color;
}

var createRandomBall = function(){
	// The ball object
	var ball = {};

	// Random radius (min 5 max 30)
	ball.radius = Math.floor((Math.random() * 25) + 5);
	ball.radius2 = Math.pow(ball.radius, 2);
	// Random x position
	ball.x = Math.floor((Math.random() * (canvas.width - ball.radius*2)) + ball.radius);
	// Random y position
	ball.y = Math.floor((Math.random() * (canvas.height - ball.radius*2)) + ball.radius);
	// Random color
	ball.color = getRandomColor();

	return ball;
}

// Create many balls
var ballList = [];
var tmp_ball;
for (var i = 0; i < 200; i++) {
	// Make a random ball
	tmp_ball = createRandomBall();
	// Add to the list
	ballList.push(tmp_ball);
}

// Render the balls
var renderBalls = function(){
	var ball;
	// For each ball
	for (var i = 0; i < ballList.length; i++) {
		ball = ballList[i];

		// Stroke ball
		context.beginPath();
		context.arc(ball.x, ball.y, ball.radius - 1, 0, 2 * Math.PI, false);
		context.fillStyle = ball.color;
		context.fill();
		context.lineWidth = 1;
		context.strokeStyle = '#000000';
		context.stroke();
	}
}

// Render balls
renderBalls();

// Add click event
canvas.addEventListener('click', function(event){
	// Get x and y of click
	var click = {
		x : event.clientX - canvas.offsetLeft,
		y : event.clientY - canvas.offsetTop
	};
		
	var ball = null;

	// Find clicked ball
	// we search the array from the back, 
	// because on the back balls are over the frond balls 
	for (var i = ballList.length - 1; i >= 0; i--) {

		if( Math.pow(click.x - ballList[i].x, 2) + Math.pow(click.y - ballList[i].y, 2) <= ballList[i].radius2 ){
			ball = i;
			break;
		}
		
	}

	// If no ball found return
	if(ball == null){
		console.log("No ball clicked");
		return;
	}

	// else ball found
	ball = ballList.splice(ball, 1)[0];

	// Else position ball on the frond
	ballList.push(ball);
	// Re-render
	renderBalls();

}, false);
*{
				padding: 0px;
				margin: 0px;
			}
			#myCanvas{
				position: absolute;
				top: 10px;
				right: 10px;
				bottom: 10px;
				left: 10px;
			}
<canvas id="myCanvas" width="600" height="200"></canvas>

一般的解决方案是制作地图表,画布的网格,并在每个单元格上添加相应的球,以便您可以匹配单击的网格框并检查较小的一组球。 / p>

因此,举例来说,当你点击时,你想要的是,点击下的所有球都会改变颜色。这是一个将球映射到较小组的示例,我们制作了10列和5行的网格。每个球可能超过1组。我们创造了400个球。

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

var getRandomColor = function() {
	// Code from : http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript
	var letters = '0123456789ABCDEF';
	var color = '#';
	for (var i = 0; i < 6; i++ ) {
		color += letters[Math.floor(Math.random() * 16)];
	}
	return color;
}

var gridSize = {x:10, y:5};
var gridList = [];
// Rows
for (var i = 0; i < gridSize.y; i++) {
	gridList.push([]);
	// Columns
	for (var j = 0; j < gridSize.x; j++) {
		gridList[i].push([]);
	}
}

var createRandomBall = function(){
	// The ball object
	var ball = {};

	// Random radius (min 5 max 30)
	ball.radius = Math.floor((Math.random() * 25) + 5);
	ball.radius2 = Math.pow(ball.radius, 2);
	// Random x position
	ball.x = Math.floor((Math.random() * (canvas.width - ball.radius*2)) + ball.radius);
	// Random y position
	ball.y = Math.floor((Math.random() * (canvas.height - ball.radius*2)) + ball.radius);
	// Random color
	ball.color = getRandomColor();

	// Map ball - find cells that the circle overlap
	grid = {
		x : {
			min : Math.floor((ball.x - ball.radius)*gridSize.x/canvas.width),
			max : Math.floor((ball.x + ball.radius)*gridSize.x/canvas.width)
		},
		y : {
			min : Math.floor((ball.y - ball.radius)*gridSize.y/canvas.height),
			max : Math.floor((ball.y + ball.radius)*gridSize.y/canvas.height)
		}
	}

	for (var y = grid.y.min; y <= grid.y.max; y++) {
		for (var x = grid.x.min; x <= grid.x.max; x++) {
			gridList[y][x].push(ball);
		}
	}

	return ball;
}

// Create many balls
var ballList = [];
var tmp_ball;
for (var i = 0; i < 400; i++) {
	// Make a random ball
	tmp_ball = createRandomBall();
	// Add to the list
	ballList.push(tmp_ball);
}

// Render the balls
var renderBalls = function(){
	var ball;
	// For each ball
	for (var i = 0; i < ballList.length; i++) {
		ball = ballList[i];

		// Stroke ball
		context.beginPath();
		context.arc(ball.x, ball.y, ball.radius - 1, 0, 2 * Math.PI, false);
		context.fillStyle = ball.color;
		context.fill();
		context.lineWidth = 1;
		context.strokeStyle = '#000000';
		context.stroke();
	}

	for (var i = 0; i < gridSize.x + 1; i++) {
		context.beginPath();
		context.moveTo((canvas.width/gridSize.x)*i, 0);
		context.lineTo((canvas.width/gridSize.x)*i, canvas.height);
		context.stroke();
	}

	for (var i = 0; i < gridSize.y + 1; i++) {
		context.beginPath();
		context.moveTo(0, (canvas.height/gridSize.y)*i);
		context.lineTo(canvas.width, (canvas.height/gridSize.y)*i);
		context.stroke();
	}
}

// Render balls
renderBalls();

// Add click event
canvas.addEventListener('click', function(event){
	// Get x and y of click
	var click = {
		x : event.clientX - canvas.offsetLeft,
		y : event.clientY - canvas.offsetTop
	};
	var grid = {
		x : Math.floor(click.x*gridSize.x/canvas.width),
		y : Math.floor(click.y*gridSize.y/canvas.height)
	};
		
	var ball = 0;

	var smallerList = gridList[grid.y][grid.x];

	// Find clicked ball
	for (var i = smallerList.length - 1; i >= 0; i--) {

		if( Math.pow(click.x - smallerList[i].x, 2) + Math.pow(click.y - smallerList[i].y, 2) <= smallerList[i].radius2 ){
			ball++;
			smallerList[i].color = getRandomColor();
		}
		
	}

	console.log("Group["+grid.y+"]["+grid.x+"], " + smallerList.length + " balls in group, clicked " + ball + " balls");

	// If no ball found return
	if(ball == 0){
		return;
	}

	// Re-render
	renderBalls();

}, false);
*{
				padding: 0px;
				margin: 0px;
			}
			#myCanvas{
				position: absolute;
				top: 10px;
				right: 10px;
				bottom: 10px;
				left: 10px;
			}
<canvas id="myCanvas" width="600" height="200"></canvas>