2012-08-30 15 views
5

Próbuję znaleźć najlepszy sposób uzyskania obwiedni dowolnego elementu SVG w pikselach ekranu, aby poprawnie nałożyć element HTML. Moje dotychczasowe podejście polegało na użyciu .getBBox() i .getCTM() w celu pobrania ramki ograniczającej obiektu i macierzy transformacji, a następnie zastosowania transformacji do punktów ramki granicznej zgodnie z opisem w zaakceptowanej odpowiedzi na this question.Uzyskiwanie granic obracanego elementu SVG w pikselach ekranu?

// get the element 
var el = $(selector)[0], 
    pt = $(selector).closest('svg')[0].createSVGPoint(); 

// get the bounding box and matrix 
var bbox = el.getBBox(), 
    matrix = el.getScreenCTM(); 

pt.x = bbox.x; 
pt.y = bbox.y; 
var nw = pt.matrixTransform(matrix); 
pt.x += bbox.width; 
pt.y += bbox.height; 
var se = pt.matrixTransform(matrix); 

// make a div in the screen space around the object 
var $div = $('<div class="bbox"/>').css({ 
     left: nw.x, 
     top: nw.y, 
     width: se.x - nw.x, 
     height: se.y - nw.y 
    }) 
    .appendTo('body'); 

Można zobaczyć mój test TUTAJ: http://jsfiddle.net/nrabinowitz/zr2jX/

Jednak, jak wynika z badań, takie podejście wydaje się niepowodzeniem, gdy istnieje obrót zawarte w transformacji - wygląda jak obwiednia jest obliczana pre- obracanie, więc nie działa narożnik obróconego obwiedni.

Jak poprawnie obliczyć nieobrotowy obwiednia transformowanych elementów?

Odpowiedz

4

Po kilku badań, tutaj są najlepsze opcje znalazłem:

  • getBoundingClientRect() wydaje się działać dobrze dla elementów SVG w nowoczesnych przeglądarkach, i to dość szybko, ale wyniki mogą się nieco różnić od platformy platforma (szczególnie jeśli masz znaczną szerokość obrysu). Jednakże, dla punktu @ Sergiu, nie uwzględnia to zmian kształtu i daje granice obróconego obwiedni, a nie rzeczywistą ścieżkę lub obiekt, więc może być dość nieprecyzyjny - see criticism here. Przykład skrzypce: http://jsfiddle.net/stevenbenner/6M5zf/

  • Moim głównym celem było uzyskanie pozycyjnych narożniki i punkty środkowe prostokąta obwiedni, iw końcu zdecydowałem, że za pomocą obwiedni obróconego może być nawet lepsze niż „prawdziwy” Obwiednia z obrócony kształt. Udało mi się to zrobić za pomocą powyższego podejścia, a następnie jeździć na rowerze, aby uzyskać jak najbliżej pozycji N, S, E, W. Można zobaczyć mój przykład skrzypce tutaj: http://jsfiddle.net/nrabinowitz/sPtzV/

3

Nie sądzę, że jest to możliwe, ponieważ pochylenie i obrót dotyczą zmiany profilu lub tego, jak wyglądają projekcje kształtu na dwóch osiach.

Można obliczyć macierz transformacji, która zignoruje część obrotową WZT, ale wtedy nie macie żadnej gwarancji, że nowy BBox nadal będzie otaczał obrócony element. Na przykład, jeśli masz okrąg, obrót nie wpływa na wymiary obwiedni. Jeśli, z drugiej strony, masz diament jako ścieżkę podstawową, a obrócisz go o 45 stopni, tak, że w końcu jest to tylko kwadrat, ramka ograniczająca jest inna: początkowo mierzyłeś przekątną, a teraz musisz uzyskać ramkę ograniczającą, która mierzy długość boku. Bez względu na to, jak korzystasz z WZT, nie możesz brać pod uwagę zmiany kształtu.

Tak więc rotacja jest rzeczywiście bardzo ważna, ignorowanie jej nie jest opcją; ale tylko lokalne pole graniczne i macierz transformacji nie mówią nic o tym, jak zmienia się profil kształtu po obróceniu.

+0

To dobry punkt, ale a) najlepiej byłoby, gdybym mógł uzyskać podstawowe granice obwiedni obróconym, oraz b) Mam nadzieję, że istnieje coś, co nie wiem w interfejsie API SVG, który może dać mi nową ramkę ograniczającą na podstawie przekształconego kształtu. – nrabinowitz

+0

Teoretycznie można użyć [checkEnclosure] (http://www.w3.org/TR/SVG11/struct.html#__svg__SVGSVGElement__checkEnclosure), aby wykonać binarne wyszukiwanie najmniejszego prostokąta, który całkowicie otoczy twój element.Niestety [nie jest jeszcze zaimplementowany w Firefoksie] (https://bugzilla.mozilla.org/show_bug.cgi?id=501421). –

Powiązane problemy