【问题标题】:Returning un-transformed mouse coordinates after rotating an object on html5 canvas在 html5 画布上旋转对象后返回未转换的鼠标坐标
【发布时间】:2013-01-09 08:56:44
【问题描述】:

我正在围绕可变原点旋转 html5 画布中的对象。

如果用户单击新旋转矩形中的给定点,我需要将返回的鼠标坐标围绕同一原点旋转回来。

我做了一个非常快速的绘图,希望能更好地说明:

我本质上需要一个函数,它将实际单击的鼠标坐标作为 x 和 y,并将它们转换为旋转之前的对象位置。

var origin = {
        x: 100,
        y: 100
};

var angle = 45;

function transformCoordinates(x,y){

         //Perform calculation to transform coordinates

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

可用的变量将是旋转的变换原点和角度。以及画布上的鼠标点击坐标(相对于画布本身,0,0 是左上角等)

不幸的是,数学不是我的强项。希望有人可以提供帮助。

【问题讨论】:

  • 您的图片似乎不正确。您将“鼠标单击”文本放置在元素的“新”旋转位置,而不是旧位置。
  • 不,这实际上是我想要的行为。用户应该点击新对象,它应该返回坐标,就好像在旧的未旋转对象上点击了位置一样。我知道令人困惑。
  • 你还画了它旋转了 45 度,但实际上你旋转了 90 度。

标签: javascript canvas html5-canvas


【解决方案1】:

有一种比你做的方法更优雅的方法来解决这个问题,但你需要知道如何做matrix multiplication才能理解它。

您可以使用context.currentTransform 获取画布的transformation matrix。该矩阵表示由当前应用于上下文状态的所有缩放平移和旋转修改器产生的所有坐标修改。 Here is the documentation of the matrix.

要将内部坐标转换为屏幕坐标,请使用以下公式:

screen_X = internal_X * a + internal_Y * c + e;    
screen_Y = internal_X * b + internal_Y * d + f;

【讨论】:

  • 当 currentTransform 属性被广泛实现时,这将是非常棒的。在那之前,这只是 HTML5 不是“Flash 杀手”的另一个原因。
  • 我已经尝试过了,但它不起作用。我应该如何定义 internal_X 和 internal_Y?我使用 ```var rect = canvas.getBoundingClientRect();```var internal_X = (event.clientX - rect.left) *canvas.widht /rect.widht) 得到我的 internal_X 这是我的完整函数,它被称为 onMouseDown 以撤消画布转换 stackoverflow.com/questions/59245199/…
【解决方案2】:

尴尬的是,我问完这个问题就直接解决了。

如果其他人需要同样的功能,我是这样做的:

getTransformedCoords : function(coords){
    var self = this;
    var obj = self.activeObj;
    var angle = (obj.angle*-1) * Math.PI / 180;   
    var x2 = coords.x - obj.left;
    var y2 = coords.y - obj.top;
    var cos = Math.cos(angle);
    var sin = Math.sin(angle);

    var newx = x2*cos - y2*sin + obj.left; 
    var newy = x2*sin + y2*cos + obj.top;

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

【讨论】:

  • 我不明白,什么是 self.activeObj 你是怎么简单地要求 obj.angle 等等...请解释一下? P.S 我不能使用currentTransform,因为它是一个实验性功能。
【解决方案3】:

我也在很长一段时间内搜索这种查询。在我的例子中,当用户在画布上单击鼠标时,我正在尝试在画布上显示一个点,即使在旋转之后也是如此。问题是,在上下文旋转之后,错误显示的点。 我采用了gordyr提供的方法。

我已经为我的代码库稍微修改了代码。我已经把我的完整代码库here

let model = {
    ctx: {},
    canvas: {},
    width: 500,
    height: 500,
    angleInRad: 0
};
function getTransformedCoords(coords) {
    var angle = (model.angleInRad * -1);
    var x2 = coords.x;
    var y2 = coords.y;
    var cos = Math.cos(angle);
    var sin = Math.sin(angle);

    var newx = Math.floor(x2 * cos - y2 * sin);
    var newy = Math.floor(x2 * sin + y2 * cos);

    return new Position(newx, newy);
}

再次感谢 gordyr 提供代码。

【讨论】:

  • 我已经尝试过这些 - 但你是如何找到坐标值的?我正在使用var rect = canvas.getBoundingClientRect(); var coords.x = (event.clientX - rect.left) * canvas.widht /rect.widht),但这给出了错误的答案。您能否详细说明应如何计算原始坐标?为了清楚起见,我让用户在画布旋转后用鼠标在画布上绘图,所以 event.clientX 是鼠标事件。
  • 我之前已经分享了我的工作代码库。你可以检查一下。
  • 该代码的作用是,当用户单击画布时,程序将根据画布在浏览器中的位置计算鼠标点,然后如果有任何旋转,程序将重新计算鼠标点为了在画布上用户点击的确切位置显示它。
猜你喜欢
  • 1970-01-01
  • 2021-09-06
  • 2011-10-15
  • 2014-12-27
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
相关资源
最近更新 更多