2010-02-01 7 views
22

I browser che hanno implementato parti delle specifiche SVG (Firefox, ecc.) Eseguono gratuitamente hit-test - se collego un listener Mousedown su un oggetto SVG, ricevo una notifica ogni volta che si fa clic sulla forma. Questo è sorprendente, specialmente per forme poligonali complesse.Forme SVG a prova di successo?

Mi chiedo se c'è un modo in cui posso utilizzare questa funzione per un po 'più di successo. Voglio sapere se un determinato rettangolo interseca una delle mie forme SVG.

Ad esempio, aggiungo 3 poligoni complessi al mio elemento. Ora voglio sapere se il rettangolo (40, 40, 100, 100) interseca uno di essi. Qualcuno ha un'idea di come sia possibile collegare il già disponibile supporto per i test di successo, invece di aggiungere tutto questo codice da solo?

Grazie

risposta

13

Non conosco alcun modo di intersecare un intero rettangolo. Ma si può intersecare un punto, quindi si potrebbe costruire un controllo più complicato di quanto segue:

var el= document.elementFromPoint(x, y); 

vi darà l'elemento più alto impilati in una particolare pagina-relative coordinate. Otterrai l'elemento <svg> se non vengono colpite forme all'interno di SVG.

Questo è uno standard non standard Mozilla extension, ma funziona anche su WebKit. Sfortunatamente, sebbene esista in Opera, non guarderà all'interno di <svg>, quindi su quel browser l'elemento sarà sempre SVGSVGElement.

+2

Grazie per aver sottolineato che la soluzione non era standard al momento. È ancora una bozza di lavoro, ma fortunatamente questo metodo è entrato nella (molto utile!) Specifica CSSOM: http://dev.w3.org/csswg/cssom-view/#dom-document-elementfrompoint – natevw

+0

molte grazie per questo ... – Sudarshan

+0

Le coordinate utilizzate in elementFromPoint() sono assolute, quindi, a meno che SVG non inizi a 0,0, sarà necessario regolare tra le coordinate assolute e relative –

21

Lo SVG 1.1 DOM ha appena il giusto metodo (purtroppo non è ancora implementato in Mozilla):

var nodelist = svgroot.getIntersectionList(hitrect, null); 

Per un esempio funzionante completo vedi here.

+0

fantastico! Quindi, tra di noi abbiamo tutti i principali browser. Bene eccetto per * quell'uno *, ovviamente ... – bobince

+0

Ok quindi non ci resta che aspettare che questo sia implementato nel webkit quindi, seguendo quel safari e chrome, allora è necessario rilasciare una nuova versione costruita contro queste modifiche. – user246114

+1

Il post del blog è sparito. –

0

getIntersectionList funziona bene in Opera. Il mio problema è che le funzioni nella specifica SVG 1.1 Full riguardo a ciò richiedono che gli elementi debbano essere renderizzati (e possibile target per gli eventi del puntatore) per essere rilevati come colpiti. Sfortunatamente ciò rende queste funzioni inutili per i test di successo in un mondo di gioco in cui solo una parte del mondo è attualmente visibile.

+2

'opacity: 0' o' visibility: hidden' vuol dire che gli elementi in questione sono renderizzati secondo svg, ma gli elementi saranno invisibili. Dovresti essere in grado di modificare 'pointer-events' per applicarlo bene a questi elementi invisibili. –

0

La versione di Chrome di checkIntersection (e getIntersectionList) verifica le caselle di delimitazione degli elementi, anziché gli stessi elementi. Sono stato in grado di scrivere il mio checkIntersection che funziona su chrome usando una tela con questo approccio abbastanza coinvolto che sembra funzionare bene per i piccoli rettangoli e sarà lento per quelli grandi, quindi è bello per i test di successo. Questa tecnica funzionerà come polyfill per checkIntersection in Chrome, per piccoli rettangoli e possibilmente altri browser che hanno implementazioni errate di checkIntersection.

  1. creare un'immagine che utilizza un URI dati contenente outerHTML del formato SVG (potrebbe essere necessario includere regole di stile in esso pure), come so (questa immagine non deve essere nella pagina). È possibile utilizzare un gestore di eventi onload per determinare quando viene caricato, se necessario.
  2. Creare una tela da utilizzare per il rettangolo di hit-test (questa tela non ha bisogno di essere nella pagina)

per verificare se un rettangolo interseca con le tue forme, fare questo:

  1. assicurarsi che la tela è la stessa dimensione come il vostro rettangolo (impostarne la larghezza e l'altezza)
  2. Cancella la tela utilizzando il contesto di tela clearRect() metodo
  3. Disegnare lo SVG sulla tela a -x, -y così che la parte del l'immagine che si sovrappone alla tela corrisponde all'area che si desidera testare utilizzando drawImage()
  4. Scarica l'immagine del canvas usando il contesto getImageData(). Ogni quarto elemento dell'array di dati è il byte alfa e un valore diverso da zero significa che parte del tuo SVG si sovrappone al rettangolo. Se tutti i 4 byte sono 0, il tuo SVG non interseca il rettangolo.