簡體   English   中英

如何約束圓圈區域內的移動

[英]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));
}

你可以在這里看到結果:

http://jsfiddle.net/7Asn6/

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM