2010-02-01 10 views
22

Les navigateurs qui ont implémenté des parties de la spécification SVG (Firefox, etc.) nous testent gratuitement - si j'attache un écouteur mousedown sur un objet SVG, je reçois une notification chaque fois que la forme est cliquée. C'est incroyable, surtout pour les formes polygonales complexes.Formes SVG de test de coup?

Je me demande si je peux utiliser cette fonctionnalité pour un test un peu plus poussé. Je veux savoir si un rectangle donné intersecte l'une de mes formes SVG.

Par exemple, j'ajoute 3 polygones complexes à mon élément. Maintenant je veux savoir si le rectangle (40, 40, 100, 100) croise l'un d'eux. Est-ce que quelqu'un a une idée de comment je pourrais peut-être accrocher dans le support de hit-test déjà bien disponible, au lieu d'ajouter moi-même tout ce code?

Merci

Répondre

13

Je ne connais aucun moyen d'intersection d'un rectangle entier. Mais vous pouvez croiser un point, de sorte que vous pourriez construire une vérification plus complexe de ce que:

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

vous donnera l'élément le plus empilés à coordonner page-relative particulière. Vous obtiendrez l'élément <svg> si aucune forme à l'intérieur du SVG n'est atteinte.

Il s'agit d'un Mozilla extension non standard, mais il fonctionne également sur WebKit. Malheureusement, bien qu'il existe dans Opera, il ne regarde pas à l'intérieur <svg>, donc sur ce navigateur, l'élément sera toujours le SVGSVGElement.

+2

Merci de signaler que votre solution n'était pas standard à ce moment-là. C'est toujours un brouillon de travail, mais heureusement, cette méthode l'a fait dans la spécification CSSOM (très pratique!): Http://dev.w3.org/csswg/cssom-view/#dom-document-elementfrompoint – natevw

+0

beaucoup de mercis pour cela ... – Sudarshan

+0

Les coordonnées utilisées dans elementFromPoint() sont absolues, donc à moins que votre SVG commence à 0,0, vous devrez ajuster entre les coordonnées absolues et relatives –

21

Le SVG 1.1 DOM a juste la bonne méthode (malheureusement, il est pas encore mis en œuvre mozilla):

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

Pour un exemple de travail complet, voir here.

+0

génial! Donc, entre nous, nous avons tous les principaux navigateurs. Eh bien, sauf pour * celui-là *, évidemment ... – bobince

+0

Ok, donc nous devons juste attendre que cela soit implémenté dans webkit puis, à la suite de ce safari et du chrome, puis besoin de sortir une nouvelle version construite contre ces changements. – user246114

+1

L'article de blog est parti. –

0

getIntersectionList fonctionne correctement dans Opera. Mon problème est que les fonctions dans le SVG 1.1 Spécification complète à ce sujet nécessite que les éléments doivent être rendus (et une cible possible pour les événements de pointeur) afin d'être détecté comme hit. Malheureusement, cela rend ces fonctions inutiles pour les tests de succès dans un monde de jeu où seule une partie du monde est actuellement visible.

+2

'opacity: 0' ou' visibility: hidden' signifie toujours que les éléments en question sont rendus selon svg, mais les éléments seront invisibles. Vous devriez être capable de modifier 'les événements-pointer' pour appliquer juste très bien à ces éléments invisibles. –

0

La version de chrome de checkIntersection (et getIntersectionList) teste les zones de délimitation des éléments, plutôt que les éléments eux-mêmes. J'ai été capable d'écrire mon propre checkIntersection qui fonctionne sur chrome en utilisant une toile avec cette approche assez impliquée qui semble bien fonctionner pour les petits rectangles et sera lente pour les grands, donc c'est bien pour les tests de hit. Cette technique fonctionnera comme un polyfill pour checkIntersection dans Chrome, pour les petits rectangles et éventuellement d'autres navigateurs qui ont des implémentations cassées de checkIntersection.

  1. Créer une image qui utilise un URI de données contenant votre outerHTML de SVG (vous devrez peut-être inclure des règles de style en elle aussi), comme so (cette image ne doit pas être dans la page). Vous pouvez utiliser un gestionnaire d'événement onload pour déterminer quand il est chargé si vous en avez besoin.
  2. Créer une toile à utiliser pour votre rectangle hit-test (cette toile n'a pas besoin d'être dans la page)

Pour tester si un rectangle croise l'une de vos formes, faites ceci:

  1. Assurez-vous que la toile est la même taille que votre rectangle (définir sa largeur et hauteur)
  2. Effacer la toile en utilisant le contexte de toile clearRect() méthode
  3. Dessiner le SVG sur la toile à -x, -y si que la partie de la image qui chevauche la toile correspond à la zone que vous souhaitez tester en utilisant drawImage()
  4. Récupère le fichier ImageData du canevas à l'aide du getImageData() du contexte. Chaque 4ème élément du tableau de données est l'octet alpha et une valeur non nulle signifie qu'une partie de votre SVG chevauche le rectangle. Si tous les 4 octets sont 0, votre SVG n'a pas coupé le rectangle.