繁体   English   中英

如何检查鼠标单击是否在JavaScript中的HTML5画布上的旋转文本内?

[英]How do I check if a mouse click is inside a rotated text on the HTML5 Canvas in JavaScript?

我在画布上以坐标X,Y绘制了文本并保存了它们。 我有一个简单的方法来检查文本边界内是否发生了鼠标单击。 问题是,当我将文本旋转45度时,无法检查在旋转的文本内是否发生了鼠标单击。

简而言之,如何检查鼠标单击是否位于旋转的文本或形状内?

创建一个与文本旋转相同角度但未绘制的矩形对象。

然后使用:

// set transforms here.
// add rect representing text region:
ctx.beginPath();
ctx.rect(x, y, w, h);  // region for text
if (ctx.isPointInPath(mx, my)) {
    // we clicked inside the region
}
ctx.setTransform(1,0,0,1,0,0);  // reset transforms after test

演示:

 var canvas = document.querySelector("canvas"), ctx = canvas.getContext("2d"), txt = "ROTATED TEXT", tw, region; // transform and draw some rotated text: ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.font = "32px sans-serif"; ctx.translate(150, 75); ctx.rotate(0.33); ctx.translate(-150, -75); ctx.fillText(txt, 150, 75); tw = ctx.measureText(txt).width; // define a region for text: region = {x: 150 - tw*0.5, y: 75 - 16, w: tw, h:32}; // approx. text region // function to check if mouse x/y is inside (transformed) region function isInText(region, x, y) { ctx.beginPath(); ctx.rect(region.x, region.y, region.w, region.h); return ctx.isPointInPath(x, y); } // test for demo canvas.onmousemove = function(e) { var rect = canvas.getBoundingClientRect(), x = e.clientX - rect.left, y = e.clientY - rect.top; // just to visualize: ctx.clearRect(0,0,300,150); ctx.fillStyle = isInText(region, x, y) ? "red" : "black"; ctx.fillText(txt, 150, 75); }; 
 <canvas></canvas> 

请勿直接使用以下代码。 在这里,我试图仅解释您如何处理此类问题的逻辑。 您可能必须根据您的问题编写代码,或将此解决方案扩展为适合您的问题

这是更多的数学问题,您必须找到一个点是否在旋转的矩形内部(与@ user1693593所说的一样)您可以找到一个覆盖文本的矩形(rect(x1:text.x1,y1:text .y1,x2:text.x2,y2:text.y2)假设(text.x1,text.y1)表示文本的左上角。现在以θ角度围绕其中心旋转矩形,找出x1,y1, x2,y2:

假设所有角度计算将以+ ve个角度进行。

if theta < 0 then theta = (360 - abs(theta))

现在计算中心点和点(x2,y2)之间的角度(从中心到rect的任意角的角度将相同,我们正在计算(x2,y2),因为它将给我们正角)

var width = (x2-x1);
var height = (y2-y1)
var hypotenuse = Math.pow(width*width + height*height, 0.5);
var innerAngle = Math.acos(x2 - x2 / hypotenuse);

现在计算从中心到最终角的角度

(x1, y1), angle((Math.PI + baseAngle) + angle) %(Math.PI*2)
(x2, y1), angle((Math.PI*2) - baseAngle + angle) % (Math.PI*2)}
(x1, y2), angle((Math.PI - baseAngle) + angle) % (Math.PI*2)}
(x2, y2), angle(baseAngle + angle) % (Math.PI*2)}

现在找出矩形的旋转点:

point.x = centre.x + (hypotenuse * Math.cos(point.angle));
point.y = centre.y + (hypotenuse * Math.sin(point.angle));

旋转点后可能会更改其顺序,以确保正确的顺序基于x轴对它们进行排序,如果两个点具有相同的x轴,则根据y轴对它们进行排序(使用任何排序),现在我们得到了排序点。 根据它们的位置p0,p1,p2,p3命名它们。从这些点找到旋转矩形的新边界,在x方向和y方向上找到边界:

var boundary_x1 = ( (p1.x - p0.x) / (p1.y - p0.y) ) * (mousePos.y - p0.y) + p0.x;
var boundary_x2 = ( (p3.x - p2.x) / (p3.y - p2.y) ) * (mousePos.y - p2.y) + p2.x;
var boundary_y1 = ( (p2.y - p0.y) / (p2.x - p0.x)) * (mousePos.x - p0.x) + p0.y;
var boundary_y2 = ( (p3.y - p1.y) / (p3.x - p1.x)) * (mousePos.x - p1.x) + p1.y;

在获得沿x和y方向的边界点之后,我们可以轻松地设置中点条件,并可以找到是否在rect中单击了一个点(鼠标点):

var clickedInside = (mousePos.x > boundary_x1 && mousePos.x < boundary_x2) && (mousePos.y > boundary_y1 && mousePos.y < boundary_y2);

如果clickedInside为true,则在rect内部发生mouseclick

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM