HTML5画布定位鼠标点击断裂



我有一个画布元素,当使用css定位时,无法注册鼠标单击并移动画布中绘制的元素。如果你不定位画布,鼠标点击会注册并移动选定的元素,但我需要能够定位这个画布层的左侧和顶部,这样我就可以在下面放置另一个画布,同时保持鼠标点击和移动的能力。

这是我用来获取x/y点击坐标的东西

var br = canvas.getBoundingClientRect(); //bounding rectangle
var mousex = parseInt(e.clientX-br.left);
var mousey = parseInt(e.clientY-br.top);

正如其他人所建议的那样,我已经将clientX和clientY更改为使用pageX和pageY,但问题仍然存在,即使我将画布放置在另一个div中并相应地定位。我还从mousex中减去了移动容器的量,但没有成功。即使使用flex定位也会破坏功能。

这只是画布的限制吗?

**澄清一下,如果之前不清楚的话,因为检测鼠标点击不是问题,问题是当我将画布放置在DOM中时,点击不再注册。**

您可以使用offsetLeftoffsetTop来完成此操作。这里有一个演示:

var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
targetPos = {x: 150, y: 50};
// Initial render
render();
// Whenever the user clicks on the canvas, update the position
canvas.addEventListener('click', updateTargetPos);
function updateTargetPos(e) {
targetPos = {
x: e.pageX - canvas.offsetLeft,
y: e.pageY - canvas.offsetTop
};
render();
}
function render() {
renderBackground();
renderTarget();
}
function renderBackground() {
ctx.fillStyle = "#333";
ctx.fillRect(0, 0, 300, 200);
}
function renderTarget() {
var size = 10;
ctx.fillStyle = "#f00";
ctx.fillRect(targetPos.x - size/2, targetPos.y - size/2, size, size);
}
body {
font-family: Arial, Helvetica, sans-serif;
}
#canvas {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -150px;
}
<p>Click on this absolutely positioned canvas:</p>
<canvas id="canvas" width="300" height="100"></canvas>

我在devtools中动态编辑这篇文章,这导致画布出现问题,并且能够获得正确的鼠标点击x/y。当我在开发工具中调整位置,然后尝试移动正方形时,这将不起作用。在这个例子中,在加载到dom之前修改我的样式表得到了正确的结果,因为在操纵画布定位之后需要再次运行计算。

对于那些需要视觉效果的人,这里有一些代码。要复制这个问题,你可以尝试添加justify内容:居中到.flex类,然后尝试移动绿色正方形,看看你不能移动正方形,或者更确切地说,定义为可点击的位置不在方框上方。

var canvas = document.getElementById("canvasArea");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-10;

var dx = 2;
var dy = -2;

var boundingRectangle = canvas.getBoundingClientRect();
var moveBox = false; 
var selectedBox;

function box(x, y) {
	this.color = "green";
	this.xPos = x;
	this.yPos = y;
	this.width = 50;
	this.height = 50;
}
box.prototype.drawBox = function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.xPos, this.yPos, this.width, this.height);
};
var abox = new box(x, 30);
canvas.addEventListener("mousedown", function(e) {
	e.preventDefault();
	e.stopPropagation();
	
	var mousex = parseInt(e.clientX-boundingRectangle.left);
	var mousey = parseInt(e.clientY-boundingRectangle.top);

	if(mousex > abox.xPos && mousex < abox.xPos + abox.width && mousey > abox.yPos && mousey < abox.yPos + abox.height) {
		moveBox = true;
		selectedBox = "abox"
	}
}, true);
canvas.addEventListener("mousemove", function(e) {
	e.preventDefault();
	e.stopPropagation();
	if(moveBox) {
		if(selectedBox == "abox") {
			abox.xPos = e.offsetX;
			abox.yPos = e.offsetY;
		} 
	}
})
canvas.addEventListener("mouseup", function(e) {
	e.preventDefault();
	e.stopPropagation();
	moveBox = false;
})

function bg(ctx2) {
var alpha = ctx2.globalAlpha;

ctx2.save();
ctx2.beginPath();
ctx2.moveTo(142.5, 23.7);
ctx2.lineTo(85.9, 0.0);
ctx2.lineTo(0.0, 204.8);
ctx2.lineTo(56.6, 228.5);
ctx2.lineTo(142.5, 23.7);
ctx2.closePath();
ctx2.fillStyle = "rgb(31, 155, 215)";
ctx2.fill();

ctx2.beginPath();
ctx2.moveTo(235.1, 23.7);
ctx2.lineTo(178.5, 0.0);
ctx2.lineTo(92.6, 204.8);
ctx2.lineTo(149.2, 228.5);
ctx2.lineTo(235.1, 23.7);
ctx2.closePath();
ctx2.fillStyle = "rgb(77, 75, 159)";
ctx2.fill();

ctx2.beginPath();
ctx2.moveTo(330.5, 23.7);
ctx2.lineTo(273.9, 0.0);
ctx2.lineTo(188.0, 204.8);
ctx2.lineTo(244.6, 228.5);
ctx2.lineTo(330.5, 23.7);
ctx2.closePath();
ctx2.fillStyle = "rgb(176, 67, 152)";
ctx2.fill();
ctx2.beginPath();
ctx2.moveTo(435.4, 23.7);
ctx2.lineTo(378.8, 0.0);
ctx2.lineTo(292.9, 204.8);
ctx2.lineTo(349.5, 228.5);
ctx2.lineTo(435.4, 23.7);
ctx2.closePath();
ctx2.fillStyle = "rgb(69, 174, 77)";
ctx2.fill();
ctx2.beginPath();
ctx2.moveTo(541.4, 23.7);
ctx2.lineTo(484.7, 0.0);
ctx2.lineTo(398.9, 204.8);
ctx2.lineTo(455.5, 228.5);
ctx2.lineTo(541.4, 23.7);
ctx2.closePath();
ctx2.fillStyle = "rgb(237, 127, 34)";
ctx2.fill();
ctx2.restore();
}
function render() {
	requestAnimationFrame(render);
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	abox.drawBox();
}
render(); 
bg(ctx2)
.flex {
width: 100%;
height: 100%;
display: flex;
}
canvas#canvasArea {
position: absolute;
display: inline-block;
}
.container {
position: relative;
left: 150px;
top: -20px;
z-index: 999999;
}

.container {
position: relative;
}
.canvasbg {
position: absolute;
width: 200px;
height: 150px;
margin: 20px 0;
border: none;
background: #000000;
}
<div class="flex">
<div class="container">
<div class="canvasbg">
<canvas id="canvasArea" width="220" height="150">
Your browser does not support HTML5 canvas.
</canvas>    
</div>
</div>
<canvas id="canvas2" width="540" height="177"></canvas>

最新更新