2012-01-13 73 views
4

好吧,這是越來越複雜...獲取畫布位置之後旋轉/平移和恢復

鑑於情況:
我的800x600尺寸的畫布。
我的鼠標位於畫布位置100x200(例如)。

我保存了我的畫布狀態。
現在我旋轉並翻譯畫布,畫一個正方形。
我恢復了我的畫布狀態。

有什麼方法可以確定我的鼠標是否在廣場上?
我想我必須翻譯/旋轉我的鼠標位置 - 在相反的方向,但我該怎麼做?

+0

你有沒有與你繪製的東西相關的對象?你有場景圖嗎?每個物體都有矩陣嗎?如果不是,你如何保存你所畫的位置和旋轉角度? – bennedich 2012-01-13 01:13:06

+0

是的,這個正方形也是一個物體,其值爲x,y,w,h,r。它變得越來越複雜的一點是,一個物體也可以有孩子繼承父母的位置和旋轉,並且自己根據父母的起源定位和旋轉。 – 2012-01-13 01:17:18

回答

4

您可以通過遞歸地應用這個公式得到一個對象的世界位置/旋轉的保持:

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; 

    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; 
} 

從長遠來看,最好是使用矩陣來學習。獲得世界正/反腐等值是一個世界矩陣。下面是關於矩陣的一些好的信息(在SVG文檔,但它是不相關):http://www.w3.org/TR/SVG/coords.html#NestedTransformations

這是你將如何處理矩陣(和GL-矩陣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); 
}; 

哦,我忘了,現在終於註冊一個點擊,你只需獲得鼠標的屏幕座標,並將它們與對象位置+畫布視口偏移進行比較。

+0

您的回答非常好!感謝您爲幫助我所做的一切努力:) 我直接採用矩陣方式 - 目前看起來有些複雜,但我希望長遠來看付出代價。 另外,我並沒有選擇使用gl-matrix,而是使用Sylvester。js,因爲gl矩陣在我的矩陣中做了一些奇怪的事情,並且離ctx.transform()等待的矩陣格式太遠了。 我希望我的大腦不會在矩陣的力量下融化x) – 2012-01-13 15:25:20

+0

好的答案,另一個查詢!這個問題考慮了三個因素,x,y和r;如果考慮所有轉換因素會怎麼樣?我的意思是如果應用縮放,平移,傾斜和旋轉轉換,算法會是什麼。算法的來源是什麼? – 2012-06-05 05:39:17

+0

@bennedich你可以看看這個問題嗎? http://stackoverflow.com/questions/10892267/html5-canvas-transformation-algorithm-finding-object-coordinates-after-applyin – 2012-06-05 05:54:50

-1

是的,您必須翻譯鼠標座標或爲您的形狀保留第二組座標。我建議保留第二組座標,因爲您將移動鼠標的次數超過您轉換對象的次數。嘗試使用對象,像這樣

function Box(x, y, w, h){ 
    this.x = x; 
    this.y = y; 
    this.tx = x; //transformed x 
    this.ty = y; //transformed y 
    this.w = w; 
    this.h = h; 

    this.mouseover = function(x, y){ 
     if (this.tx < x && this.tx + this.w > x && this.ty < y && this.ty + this.h > y){ 
      return true; 
     } 
     return false; 
    } 

    this.applyTransformation = function(transformation){ 
     switch(transformation){ 
     case 'rotation': 
      //update tx/ty to match rotation 
      break; 
     case 'translation': 
      //update tx/ty to match translation 
      break; 
     default: 
      //do nothing or raise exception 
    } 
}