[英]How to constrain movement within the area of a circle
這可能更像是幾何相關的問題,但我試圖將控制器限制在一個圓的區域內。 我知道我必須觸及Math.sin()和Math.cos()方法,但到目前為止我的嘗試都沒有結果。
這是jsfiddle:到目前為止,我已經能夠將它約束到一個看不見的方塊。 http://jsfiddle.net/maGVK/
所以我終於能夠在每個人的幫助下完成這個。
var pointerEl = document.getElementById("pointer");
var canvasEl = document.getElementById("canvas");
var canvas = {
width: canvasEl.offsetWidth,
height: canvasEl.offsetHeight,
top: canvasEl.offsetTop,
left: canvasEl.offsetLeft
};
canvas.center = [canvas.left + canvas.width / 2, canvas.top + canvas.height / 2];
canvas.radius = canvas.width / 2;
window.onmousemove = function(e) {
var result = limit(e.x, e.y);
pointer.style.left = result.x + "px";
pointer.style.top = result.y + "px";
}
function limit(x, y) {
var dist = distance([x, y], canvas.center);
if (dist <= canvas.radius) {
return {x: x, y: y};
}
else {
x = x - canvas.center[0];
y = y - canvas.center[1];
var radians = Math.atan2(y, x)
return {
x: Math.cos(radians) * canvas.radius + canvas.center[0],
y: Math.sin(radians) * canvas.radius + canvas.center[1]
}
}
}
function distance(dot1, dot2) {
var x1 = dot1[0],
y1 = dot1[1],
x2 = dot2[0],
y2 = dot2[1];
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
你可以在這里看到結果:
var pointerEl = document.getElementById("pointer");
var canvasEl = document.getElementById("canvas");
var canvas = {
width: canvasEl.offsetWidth,
height: canvasEl.offsetHeight,
top: canvasEl.offsetTop,
left: canvasEl.offsetLeft
};
canvas.center = [canvas.left + canvas.width / 2, canvas.top + canvas.height / 2];
canvas.radius = canvas.width / 2;
window.onmousemove = function(e) {
var result = limit(e.x, e.y);
if (!result.limit) {
pointer.style.left = result.x + "px";
pointer.style.top = result.y + "px";
}
}
function limit(x, y) {
var dist = distance([x, y], canvas.center);
if (dist <= canvas.radius) {
return {x: x, y: y};
} else {
return {limit: true};
}
}
function distance(dot1, dot2) {
var x1 = dot1[0],
y1 = dot1[1],
x2 = dot2[0],
y2 = dot2[1];
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
這可以做的工作,雖然運動不順暢....這將需要更多的幾何知識......
小提琴: http : //jsfiddle.net/cRxMa/
只要你規范化每個數據點(預期位置),這個算法是微不足道的,我試圖在下面的函數中做到這一點:
function locatePoint(canvas_size, next_position) {
// canvas_size & next_position are both 2-element arrays
// (w, h) & (x, y)
dist = function(x, y) {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
};
x = next_position[0];
y = next_position[1];
rescaledX = x/(canvas_size[0]/2);
rescaledY = y/(canvas_size[1]/2);
if (distance(x, y) <= 1) {
// the base case; position is w/in the circle
}
else {
// position is outside the circle, so perhaps
// do something like random select a new position, then
// call this function again (recursively) passing in
// that new position
}
}
所以在下面的簡單圖中,我剛剛在一個邊是r * 2的正方形內刻了一個單位圓(r = 1)。 您的畫布尺寸不一定是正方形。 為了進一步簡化計算,你只需要考慮四個象限中的一個 -右上象限,讓我們說。 原因是歐幾里德距離公式對每個坐標值進行平方,因此負值變為正值。
換句話說,最簡單的方法是想象一個刻在畫布上的圓圈,其中心也是畫布的中心(所以(0,0)是中心而不是左上角); 接下來,帆布和圓圈都縮小,直到圓圈的半徑= 1.希望我已經在上面的函數中捕獲了它。
您好,感謝您分享您的解決方案。
你的jsfiddle幫助我約束旋轉手柄的運動。
這是我使用jQuery的解決方案:
function getBall(xVal, yVal, dxVal, dyVal, rVal, colorVal) { var ball = { x: xVal, lastX: xVal, y: yVal, lastY: yVal, dx: dxVal, dy: dyVal, r: rVal, color: colorVal, normX: 0, normY: 0 }; return ball; } var canvas = document.getElementById("myCanvas"); var xLabel = document.getElementById("x"); var yLabel = document.getElementById("y"); var dxLabel = document.getElementById("dx"); var dyLabel = document.getElementById("dy"); var ctx = canvas.getContext("2d"); var containerR = 200; canvas.width = containerR * 2; canvas.height = containerR * 2; canvas.style["border-radius"] = containerR + "px"; var balls = [ getBall(containerR, containerR * 2 - 30, 2, -2, 20, "#0095DD"), getBall(containerR, containerR * 2 - 50, 3, -3, 30, "#DD9500"), getBall(containerR, containerR * 2 - 60, -3, 4, 10, "#00DD95"), getBall(containerR, containerR * 2 / 5, -1.5, 3, 40, "#DD0095") ]; function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); for (var i = 0; i < balls.length; i++) { var curBall = balls[i]; ctx.beginPath(); ctx.arc(curBall.x, curBall.y, curBall.r, 0, Math.PI * 2); ctx.fillStyle = curBall.color; ctx.fill(); ctx.closePath(); curBall.lastX = curBall.x; curBall.lastY = curBall.y; curBall.x += curBall.dx; curBall.y += curBall.dy; var dx = curBall.x - containerR; var dy = curBall.y - containerR; var distanceFromCenter = Math.sqrt(dx * dx + dy * dy); if (distanceFromCenter >= containerR - curBall.r) { var normalMagnitude = distanceFromCenter; var normalX = dx / normalMagnitude; var normalY = dy / normalMagnitude; var tangentX = -normalY; var tangentY = normalX; var normalSpeed = -(normalX * curBall.dx + normalY * curBall.dy); var tangentSpeed = tangentX * curBall.dx + tangentY * curBall.dy; curBall.dx = normalSpeed * normalX + tangentSpeed * tangentX; curBall.dy = normalSpeed * normalY + tangentSpeed * tangentY; } xLabel.innerText = "x: " + curBall.x; yLabel.innerText = "y: " + curBall.y; dxLabel.innerText = "dx: " + curBall.dx; dyLabel.innerText = "dy: " + curBall.dy; } requestAnimationFrame(draw); } draw();
canvas { background: #eee; }
<div id="x"></div> <div id="y"></div> <div id="dx"></div> <div id="dy"></div> <canvas id="myCanvas"></canvas>
希望這能有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.