我有一個已使用matrix3d
進行轉換的元素,以給它透視。它代表了手持設備的屏幕。獲取已轉換元素的本地座標中的已觸摸位置
有一個背景圖像顯示手持設備本身,這是不會改變。放置該元素的元素被定位,並且屏幕元素完全位於其中,位於left: 0; top: 0;
處,然後進行轉換,並在容器的左上角有一個原點。這對我來說是最簡單的方法,可以將它與背景圖像完美對齊(我使用this very handy tool來提供矩陣),並將屏幕元素從角落移開。
我希望能夠通過鼠標和觸摸事件與屏幕進行交互。爲此,在點擊或觸摸事件時,我需要在屏幕元素的本地座標系中找到座標 - 即轉換髮生之前的座標。換句話說,當點擊手持設備屏幕的左上方(而不是頁面上其邊框的左上方!)時,我想要[0, 0]
,並且在點擊屏幕的右上角時這個轉換的情況實際上是在頁面上以及在右邊,我想要[untransformedWidth, 0]
。
鼠標事件提供offsetX
和offsetY
據稱這是做的(下面更多),但觸摸事件沒有這些屬性,所以我需要一種方法來自己計算它們。
使用math.js我可以輸入轉換矩陣並將其反轉。我有some code to loop over the CSS rules得到transform: matrix3d(...)
規則(我不想在我的代碼中重複它,如果我不需要),我將跳過 - 我知道它的工作原理是因爲數字匹配CSS。
注意CSS在列順序矩陣元素,所以matrix3d(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
看起來正規矩陣符號是這樣的:
┌ ┐
│ a e i m │
│ b f j n │
│ c g k o │
│ d h l p │
└ ┘
同時,math.js希望其矩陣的行申報行,像[[a, e, i, m], [b, f, j, n]...
。
於是開始在那裏我有從matrix3d(...)
表達式中的一些元素的列表,CSS順序,我建立和反相這樣的矩陣:
var rows = [[], [], [], []];
for (var i = 0; i < elements.length; i++) {
rows[i % 4][Math.floor(i/4)] = elements[i];
}
var matrixTransform = math.matrix(rows);
var invertedMatrixTransform = math.inv(matrixTransform);
我然後設置鼠標屏幕元素事件處理程序:
screen.addEventListener('mousedown', function (event) {
var rect = container.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
如果我移動標記(相對於容器)這一點[x, y]
,它在那裏我點擊顯示準確。所以我知道這很多工作。
var vector = math.matrix([x, y, 0, 1]);
var result = math.multiply(inverseMatrixTransform, vector);
如果我提出另一個標記(這一個相對於屏幕元件),以所得到的矢量的值[result.get([0]), result.get([1])]
它移動到大致相同的位置:然後我通過逆變換矩陣相乘這些座標的矢量作爲上一個標記,但它不太正確。似乎離我的起源越遠,錯誤就越多,直到它對右邊和底邊非常不好。
但是如果我檢查offsetX
和offsetY
怎麼辦?那麼,事實證明,答案取決於瀏覽器。
在Firefox中,使用offset*
找到的座標也與所點擊的位置不匹配。它們與我的計算結果並不完全相同,但僅有幾個像素不同。它們與我的計算值相距真正的點擊點。
但在Chrome中發現offset*
的座標是完美的。
這裏有一個jsfiddle。
有什麼我做錯了我的計算?有沒有辦法讓我模仿Chrome的結果,但沒有offset*
屬性?
我懷疑在Firefox和Chrome'event.offset *'之間的不匹配可能是一個錯誤。我已經[在Firefox跟蹤器上報告過](https://bugzilla.mozilla.org/show_bug.cgi?id=1261645)。但是如果它*是一個Firefox錯誤,我的代碼中存在相同的錯誤,我想找到它。 – tremby
這個錯誤似乎在Firefox 50.0.2版本中得到解決,儘管我仍然對實際的解決方案在這裏感興趣。 – Thomas
更正:我可以確認錯誤仍然存在,我的測試是錯誤的。如果這個問題得到解決,會很好。 – Thomas