繁体   English   中英

椭圆 - 鼠标碰撞检测

[英]Ellipse - Mouse collision detection

我试图找出如何判断鼠标是否在HTML5 Canvas上的椭圆上。 我需要比边界框检查更精确。

对不起,这是一个模糊的问题。 我完全难过了。

任何帮助将不胜感激。

到目前为止我有这个:

// This is a pretend object. m.x and m.y will have the position of the mouse.
var m = {
    x:245,
    y:341,
    onEnter: function(){}
};

m.onEnter = function () {
    console.log('The mouse entered the ellipse!');
};

// The important parts of my ellipse object
var e = {
    width:100,
    height:50,
    x:132,
    y:143
};

// This is already working - I use a bounding-box first to increase performance.
if (m.x >= e.x - (e.width/2) && m.x <= e.x + (e.width/2) && m.y >= e.y - (e.height/2) && m.y <= e.y + (e.height/2)) {

    if (/* I havn't got the slightest idea what to put here. */) {
        m.onEnter();
    }

}

@pvg的重复答案是可以的,但重复的答案应该指出他们使用的变量是如何计算的:

// Given cx,cy,a,b defining an ellipse 
function isInEllipse(mouseX,mouseY){
    var dx=mouseX-cx;
    var dy=mouseY-cy;
    return ((dx*dx)/(a*a)+(dy*dy)/(b*b)<=1);
}

这是示例代码和演示:

 var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var cw=canvas.width; var ch=canvas.height; function reOffset(){ var BB=canvas.getBoundingClientRect(); offsetX=BB.left; offsetY=BB.top; } var offsetX,offsetY; reOffset(); window.onscroll=function(e){ reOffset(); } window.onresize=function(e){ reOffset(); } var PI=Math.PI; var PI2=PI*2; var cx=cw/2; var cy=ch/2; var a=120; var b=80; var points=getPointsOnEllipse(cx,cy,a,b); $("#canvas").mousemove(function(e){handleMouseMove(e);}); drawEllipse(points); function dot(x,y,color){ ctx.beginPath(); ctx.arc(x,y,3,0,PI2); ctx.closePath(); ctx.fillStyle=color; ctx.fill(); } function isInEllipse(x,y){ var dx=x-cx; var dy=y-cy; return ((dx*dx)/(a*a)+(dy*dy)/(b*b)<=1); } function drawEllipse(points){ ctx.beginPath(); ctx.moveTo(points[0].x,points[0].y); for(var j=0;j<points.length;j++){ ctx.lineTo(points[j].x,points[j].y); } ctx.closePath(); ctx.lineWidth=1; ctx.strokeStyle='forestgreen'; ctx.stroke(); } function getPointsOnEllipse(cx,cy,a,b){ var startAngle=-PI/2; var lastX=cx-(a*Math.cos(startAngle)); var lastY=cy+(b*Math.sin(startAngle)); var points=[]; for(var i=0;i<1000;i++){ var angle=startAngle+PI2/1000*i; var x=cx-(a*Math.cos(angle)); var y=cy+(b*Math.sin(angle)); var dx=x-lastX; var dy=y-lastY; var length=parseInt(Math.sqrt(dx*dx+dy*dy)); var eAngle=(Math.atan2(dy,dx)+PI2)%PI2; if(length>0){ points.push({x:x,y:y,angle:eAngle}); lastX=x; lastY=y; } } return(points); } function handleMouseMove(e){ // tell the browser we're handling this event e.preventDefault(); e.stopPropagation(); mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); var hit=isInEllipse(mouseX,mouseY); var color=(hit)?'red':'green'; dot(mouseX,mouseY,color); } 
 body{ background-color: ivory; } #canvas{border:1px solid red; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <h4>Move mouse in & out of ellipse.<br>Red mouse dots are inside ellipse, Green outside.</h4> <canvas id="canvas" width=300 height=300></canvas> 

2DRenderingContext有一个方法来检测一个点是否在路径中:

CanvasRenderingContext2D.isPointInPath()

您可以将其用于各种路径,与几何形状无关。 一个缺点:它只能在绘图时使用,因此您必须在mouseevent中重绘场景。 对于静态场景,这可能是不需要的,但如果你有动画,这应该不是问题。

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath

对于模糊的初步答案表示道歉,这需要改进,但要让球滚动......

假设椭圆是围绕两个焦点(F1和F2)的平面上的曲线,所述焦点被定义为使得到两个焦点的距离的总和对于曲线上的每个点是恒定的。

也就是说,对于椭圆上的任何点P,两个距离F1P + F2P是常数。 该常数(明显且有益地)等于所述椭圆的较长(主)轴A的长度。

因此,对于这个问题,我怀疑椭圆的重要部分不是宽度,高度,x,y而是它的两个焦点F1和F2(两个点与椭圆中心等距离定义它)和长度主轴。

然后......对于任何给定的鼠标单击点M,如果提供2个距离F1M + F2M <A的总和,则鼠标点击点在椭圆内。

暂无
暂无

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

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