围绕点旋转画布并获得新的x,y偏移

时间:2013-10-16 00:18:52

标签: javascript canvas rotation html5-canvas trigonometry

我正在使用html5画布编写多点触控拼图,您可以在其中旋转各个点。每件作品都有自己的画布,大小与其边框相同。当旋转发生时,画布大小必须改变,我能够计算并且正在工作。我无法弄清楚的是,如果我想让它看起来围绕枢轴(第一个接触点)旋转,如何找到新的x,y偏移量。

这是一张图片,可以更好地解释我想要实现的目标。请注意,枢轴点并不总是中心,否则我可以将新边界与旧边界之间的差异减半。

enter image description here

所以我知道原始x,y,宽度,高度,旋转角度,新边界(rotateWidth,rotateHeight)以及与原始对象相关的轴X,Y。我无法弄清楚如何得到的是新边界的x / y偏移(使得看起来物体围绕枢轴点旋转)

提前致谢!

2 个答案:

答案 0 :(得分:7)

  • 首先,我们需要找到从枢轴点到角落的距离。
  • 然后计算枢轴和角落之间的角度
  • 然后根据前一个角度+新角度计算绝对角度。
  • 最后计算新角落。

Snapshot from demo
下面演示的快照,显示从枢轴到角落的直线 使用
旋转矩形时计算红点 翻译。

以下是使用绝对角度的示例,但您可以轻松地将其转换为转换旧角度和新角度之间的差异。为简单起见,我将角度保持为度数而不是弧度。

演示首先使用画布的内部平移和旋转来旋转矩形。然后我们使用纯数学来得到与我们为角点计算正确的新x和y点的证据相同的点。

<强> Live demo here

/// find distance from pivot to corner
diffX = rect[0] - mx; /// mx/my = center of rectangle (in demo of canvas)
diffY = rect[1] - my;
dist = Math.sqrt(diffX * diffX + diffY * diffY); /// Pythagoras

/// find angle from pivot to corner
ca = Math.atan2(diffY, diffX) * 180 / Math.PI; /// convert to degrees for demo

/// get new angle based on old + current delta angle
na = ((ca + angle) % 360) * Math.PI / 180; /// convert to radians for function

/// get new x and y and round it off to integer
x = (mx + dist * Math.cos(na) + 0.5)|0;
y = (my + dist * Math.sin(na) + 0.5)|0;

最初,您可以通过查看它们与为矩形(50,100)定义的初始角完全相同的值来验证打印的x和y。

<强>更新

似乎我错过了单词in:offset bounds ...对不起,但你可以做的是计算到每个改为角落。

这将为您提供边界的外部限制,您只需使用最小值和最大值“混合并匹配”这些距离值的角落。

<强> New demo here

Bounds

新部件包含一个函数,可以为您提供角落的x和y:

///mx, my = pivot, cx, cy = corner, angle in degrees
function getPoint(mx, my, cx, cy, angle) {

    var x, y, dist, diffX, diffY, ca, na;

    /// get distance from center to point
    diffX = cx - mx;
    diffY = cy - my;
    dist = Math.sqrt(diffX * diffX + diffY * diffY);

    /// find angle from pivot to corner
    ca = Math.atan2(diffY, diffX) * 180 / Math.PI;

    /// get new angle based on old + current delta angle
    na = ((ca + angle) % 360) * Math.PI / 180;

    /// get new x and y and round it off to integer
    x = (mx + dist * Math.cos(na) + 0.5)|0;
    y = (my + dist * Math.sin(na) + 0.5)|0;

    return {x:x, y:y};
}

现在只需为每个角落运行该函数,然后执行最小/最大值来查找边界:

/// offsets
c2 = getPoint(mx, my, rect[0], rect[1], angle);
c2 = getPoint(mx, my, rect[0] + rect[2], rect[1], angle);
c3 = getPoint(mx, my, rect[0] + rect[2], rect[1] + rect[3], angle);
c4 = getPoint(mx, my, rect[0], rect[1] + rect[3], angle);

/// bounds
bx1 = Math.min(c1.x, c2.x, c3.x, c4.x);
by1 = Math.min(c1.y, c2.y, c3.y, c4.y);
bx2 = Math.max(c1.x, c2.x, c3.x, c4.x);
by2 = Math.max(c1.y, c2.y, c3.y, c4.y);

答案 1 :(得分:0)

要围绕画布的中心点旋转,可以使用以下功能:

function rotate(context, rotation, canvasWidth, canvasHeight) {
    // Move registration point to the center of the canvas
    context.translate(canvasWidth / 2, canvasHeight/ 2);

    // Rotate 1 degree
    context.rotate((rotation * Math.PI) / 180);

    // Move registration point back to the top left corner of canvas
    context.translate(-canvasWidth / 2, -canvasHeight/ 2);
}