2016-04-02 41 views
5

Bir bakış açısı vermek için matrix3d ile dönüştürülmüş bir öğem var. Taşınabilir bir cihazın ekranını temsil eder.Dönüştürülmüş bir öğenin yerel koordinatlarında dokunma konumunu alma

Avuçiçi cihazın kendisini gösteren bir arka plan resmi vardır ve bu dönüştürülmez. Bunu tutan eleman konumlandırılmıştır ve ekran elemanı left: 0; top: 0; numaralı telefona tam olarak yerleştirilmiş ve daha sonra kabın sol üst köşesinde bir orijine dönüştürülmüştür. Bu, arka plan resmiyle mükemmel bir şekilde hizalamamın en kolay yoluydu (matrisle gelmek için this very handy tool'u kullandım) ve ekran elemanını köşeden uzaklaştırır.

Ekrandaki fare ve dokunma olaylarıyla etkileşimde bulunmak istiyorum. Bunu yapmak için, bir tıklama veya dokunma olayında, ekran elemanının yerel koordinat sisteminde koordinatları bulmam gerekir - yani, dönüşüm gerçekleşmeden önceki koordinatlar. Başka bir deyişle, avuçiçi cihazın ekranının sol üst kısmına tıkladığınızda ( sayfadaki sınırlayıcı kutunun sol üst köşesinde değil!) [0, 0] istiyorum ve ekranın sağ üst köşesine tıklandığında Bu dönüşümün durumu aslında sayfada olduğu kadar sağda da, [untransformedWidth, 0]'u istiyorum.

Fare olayları ileri sürülen tam olarak bu (daha aşağıda) yapmak offsetX ve offsetY sağlar, ancak dokunmatik olaylar bu özellikleri yok, bu yüzden onları kendim hesaplamak için bir yol gerekir.

math.js Kullanarak dönüştürme matrisini besleyebilir ve tersine çevirebilirim. transform: matrix3d(...) kuralı için some code to loop over the CSS rules kuralım var (bunu yapmak zorunda kalmazsam kodumda tekrarlamak istemiyorum), ki atlayacağım. - Sayıların CSS ile eşleşmesi nedeniyle çalıştığını biliyorum. CSS, kolon sırayla onun matris unsurlar içerdiğini

Not yüzden matrix3d(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) gibi normal matris gösteriminde arar:

┌   ┐ 
│ a e i m │ 
│ b f j n │ 
│ c g k o │ 
│ d h l p │ 
└   ┘ 

arada math.js [[a, e, i, m], [b, f, j, n]... gibi onun matrisleri satır temelinde ilan edilmesini istiyor.

Ben matrix3d(...) ifadesi içinden numara unsurların bir listesi var nereye Yani, bina ve bunun gibi matrisi tersini ediyorum CSS sırayla, başlangıç: Sonra bir fare kurmak

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

ekran elemanı üzerine olay işleyicisi: Bu noktaya [x, y] (konteyner göreceli) bir işaret taşırsanız Tıkladım'ı nerede

screen.addEventListener('mousedown', function (event) { 
    var rect = container.getBoundingClientRect(); 
    var x = event.clientX - rect.left; 
    var y = event.clientY - rect.top; 

, tam olarak görünür. Bu yüzden bunun işe yaradığını biliyorum. Sonuçta elde edilen vektörün değerleri [result.get([0]), result.get([1])] için (ekran elemanına bu göre) Bir marker hareket halinde

var vector = math.matrix([x, y, 0, 1]); 
    var result = math.multiply(inverseMatrixTransform, vector); 

bu yaklaşık aynı pozisyon hareket: Daha sonra ters dönüşüm matrisi ile bu koordinatların bir vektör çarpma önceki işaretçi olarak, ancak oldukça doğru değil. Gittiğim kaynaktan daha ileriye doğru, sağ ve alt kenarlara doğru oldukça kötü olana kadar daha fazla hata var gibi görünüyor.

Ama sonra ne offsetX ve offsetY karşı kontrol ederlerse? Peki, cevabın tarayıcıya bağlı olduğu ortaya çıkıyor.

Firefox'ta, offset* ile bulunan koordinatlar ya tıklanan pozisyonu uymuyor. Hesaplamamla aynı değiller ama sadece birkaç pikselle farklılar. Hesaplanan değerlerim kadar gerçek tıklama noktasından çok uzaklar.

Sample output in Firefox 45

Ama offset* ile bulunan koordinatlarda Krom içinde

mükemmeldir.

Sample output in Chrome

İşte jsfiddle bu.

Hesaplamada yanlış yaptığım bir şey var mı? Chrome'un sonucunu taklit etmenin bir yolu var mı, ancak offset* özellikleri olmadan mı? Ben teori hakkında tamamen emin değilim

+0

Ben bir hata olabilir Firefox ve Chrome 'event.offset *' arasındaki uyumsuzluk şüpheli. [Firefox izleyicide bunu bildirdim] (https://bugzilla.mozilla.org/show_bug.cgi?id=1261645). Ama eğer * bir Firefox hatasıysa, kodda aynı hata var ve onu bulmak istiyorum. – tremby

+0

Bu hata, Firefox'un 50.0.2 sürümünde sabitlenmiş gibi görünüyor, yine de gerçek çözümün burada neyle ilgilendiğimi hala düşünüyorum. – Thomas

+0

Düzeltme: hatanın hala orada olduğunu onaylayabilirim, testlerim yanlış. Bu çözülürse harika olur. – Thomas

cevap

2

, ben de benzer bir problem üzerinde çalışıyordu bu süre hakkında okuyun, ama burada ne buldum. Matrislerin çarpımı (3d dönüşümün matrisi - homojen koordinatlar ve imlecin konumu) x ve y'den başka iki değer daha üretir. Birincisi z, diğeri ise 3d nesneyi 2d düzlemde yansıtmak için kullanılan w'dir.

W ile X ve vektörün y değerleri koordinat bölmek ise

, Kartezyen düzlemde imlecin doğru konumu/eşleme alır.

Yani, bunlarla, çizgiler, sizin keman içinde 69-70 kodunu değiştirmek olacaktır: https://jsfiddle.net/x3ruc3tL/1/

Ve sonra gerek yoktur: Burada

var x = result.get([0]); 
var y = result.get([1]); 
var w = result.get([3]); 
screenCrosshair.style.left = x/w + 'px'; 
screenCrosshair.style.top = y/w + 'px'; 

güncelleme keman olduğunu Doğru konumu bulmak için tarayıcının offsetX ve offsetY değerlerini.

fazla bilgi için aşağıdaki makalelere okuyunuz:

https://en.wikipedia.org/wiki/3D_projection#Perspective_projection http://deltaorange.com/2012/03/08/the-truth-behind-homogenous-coordinates/

+0

İşte bu kadar! Çok teşekkürler! Görünüşe göre, Mozilla kodlarında tam olarak aynı hatayı barındırıyor, böylece onları çözümünüze yönlendireceğim. – tremby