在旋转/平移和恢复后获取画布上的位置 [英] Get position on canvas AFTER rotating/translating and restoring

查看:137
本文介绍了在旋转/平移和恢复后获取画布上的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,这变得越来越复杂...



给定情况:

我有一个尺寸为800x600的画布。

我的鼠标位于画布位置100x200(例如)。



我保存了画布状态。

现在我旋转并翻译画布,我画一个正方形。

我恢复我的画布状态。



有什么方法可以确定我的鼠标是否在广场上?

我想我必须翻译/旋转鼠标位置 -

您可以通过以下方式获取对象世界位置/旋转:

  worldX = parentX + x * Math.cos(parentR) -  y * Math.sin(parentR) ; 
worldY = parentY + x * Math.sin(parentR)+ y * Math.cos(parentR);
worldR = parentR + r;

JavaScript实现将是:

  var deg2rad,rad2deg,getXYR; 

deg2rad = function(d){return d * Math.PI / 180};
rad2deg = function(r){return r / Math.PI * 180};

getXYR = function(node){
var x,y,r,
parentXYR,pX,pY,pR,
nX,nY; b
$ b x = y = r = 0;

if(node){
parentXYR = getXYR(node.parent);
pX = parentXYR.x;
pY = parentXYR.y;
pR = deg2rad(parentXYR.r);
nX = node.x;
nY = node.y;

x = pX + nX * Math.cos(pR) - nY * Math.sin(pR);
y = pY + nX * Math.sin(pR)+ nY * Math.cos(pR);
r = rad2deg(pR + deg2rad(node.r));
}

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

尝试使用以下对象:

  el1 = {x:3,y:0,r:45}; 
el2 = {x:0,y:0,r:45};
el1.parent = el2;
getXYR(el1);

在计算两个对象之间的最短角度时不会很久两个对象之间的deltaX(x2-x1)和deltaY(y2-y1)可以得到与此函数的角度:

  var getAngle = function(dx,dy){
var r = Math.atan2(dy,dx)* 180 / Math.PI;
return(r> 180)? r-360:
(r <-180)? r + 360:
r;
}

从长远看,最好学习使用矩阵。获得世界pos / rot的等价性是一个世界矩阵。以下是关于矩阵的一些好信息(在SVG文档中,但不相关): http ://www.w3.org/TR/SVG/coords.html#NestedTransformations



这是你如何使用矩阵(和gl -matrix库 https://github.com/toji/gl-matrix ):

  var getWorldMatrix = function(node){
var parentMatrix;

if(!node)
return mat4.identity();

parentMatrix = getWorldMatrix(node.parent);
return mat4.multiply(parentMatrix,node.matrix);
};

哦,我忘了,现在终于注册一个点击你只是得到鼠标的屏幕坐标将它们与对象位置+画布视口偏移进行比较。


Okay, this is getting complicated...

Given situation:
I have a canvas with the dimensions of 800x600.
My mouse is at canvas position 100x200 (for example).

I save my canvas state.
Now I rotate and translate the canvas, I draw a square.
I restore my canvas state.

Is there any way to determine if my mouse is over the square?
I think I would have to translate/rotate my mouse position as well - in the opposite direction, but how would I do this?

解决方案

You can get hold of an objects world position/rotation by recursively applying this formula:

worldX = parentX + x * Math.cos( parentR ) - y * Math.sin( parentR );
worldY = parentY + x * Math.sin( parentR ) + y * Math.cos( parentR );
worldR = parentR + r;

A javascript implementation would be:

var deg2rad, rad2deg, getXYR;

deg2rad = function ( d ) { return d * Math.PI / 180 };
rad2deg = function ( r ) { return r / Math.PI * 180 };

getXYR = function ( node ) {
  var x, y, r,
      parentXYR, pX, pY, pR,
      nX, nY;

  x = y = r = 0;

  if ( node ) {
    parentXYR = getXYR( node.parent );
    pX = parentXYR.x;
    pY = parentXYR.y;
    pR = deg2rad( parentXYR.r );
    nX = node.x;
    nY = node.y;

    x = pX + nX * Math.cos( pR ) - nY * Math.sin( pR );
    y = pY + nX * Math.sin( pR ) + nY * Math.cos( pR );
    r = rad2deg( pR + deg2rad( node.r ) );
  }

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

Try it out with these objects:

el1 = {x:3,y:0,r:45};
el2 = {x:0,y:0,r:45};
el1.parent = el2;
getXYR(el1);

It won't be long before you want to calculate the shortest angle between two objects, if you get the deltaX (x2-x1) and deltaY (y2-y1) between the two objects you can get the angle with this function:

var getAngle = function ( dx, dy ) {
  var r = Math.atan2( dy, dx ) * 180 / Math.PI;
  return ( r > 180 )  ? r-360 :
         ( r < -180 ) ? r+360 :
         r;
}

In the long run it's better to learn using matrices instead. The equivalence of getting the world pos/rot is a world matrix. Here's some good info about matrices (in the SVG doc, but it's not relevant): http://www.w3.org/TR/SVG/coords.html#NestedTransformations

This is how you would do it with matrices (and the gl-matrix lib https://github.com/toji/gl-matrix):

var getWorldMatrix = function ( node ) {
    var parentMatrix;

    if ( !node )
        return mat4.identity();

    parentMatrix = getWorldMatrix( node.parent );
    return mat4.multiply( parentMatrix, node.matrix );
};

Oh, i forgot, now to finally register a click you just get the screen coordinates of the mouse and compare them to the objects position + the canvas viewport offset.

这篇关于在旋转/平移和恢复后获取画布上的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆