javascript svg hittest

javascript - Hit-testing formas SVG?



hittest (4)

El SVG 1.1 DOM tiene el método correcto (desafortunadamente aún no está implementado en mozilla):

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

Para ver un ejemplo completo de trabajo, vea here .

Los navegadores que han implementado partes de la especificación de SVG (Firefox, etc.) nos hacen pruebas de golpes gratis: si adjunto un oyente de mousedown en un objeto SVG, me notifican cada vez que se hace clic en la forma. Esto es sorprendente, especialmente para formas poligonales complejas.

Me pregunto si hay una forma en que pueda utilizar esta característica para un poco más de prueba de impacto. Quiero saber si un rectángulo dado cruza cualquiera de mis formas SVG.

Por ejemplo, agrego 3 polígonos complejos a mi elemento. Ahora quiero saber si el rectángulo (40, 40, 100, 100) se cruza con alguno de ellos. ¿Alguien tiene una idea de cómo podría engancharme al soporte de pruebas de golpes ya disponible, en lugar de agregar todo este código yo mismo?

Gracias


La versión de Chrome de checkIntersection (y getIntersectionList) prueba los cuadros de delimitación de elementos, en lugar de los elementos mismos. Pude escribir mi propia CheckIntersection que funciona en Chrome utilizando un lienzo con este enfoque bastante complicado que parece funcionar bien para rectángulos pequeños y será lento para grandes, por lo que es bueno para la prueba de golpes. Esta técnica funcionará como un polyfill para checkIntersection en Chrome, para rectángulos pequeños y posiblemente otros navegadores que tengan implementaciones rotas de checkIntersection.

  1. Cree una imagen que use un URI de datos que contenga el HTML externo de SVG (es posible que también deba incluir reglas de estilo), como ese (esta imagen no tiene que estar en la página). Puede usar un controlador de eventos onload para determinar cuándo se carga si es necesario.
  2. Cree un lienzo para usar en su rectángulo de prueba de golpe (este lienzo no necesita estar en la página)

Para probar si un rectángulo se cruza con alguna de sus formas, haga esto:

  1. Asegúrate de que el lienzo sea del mismo tamaño que tu rectángulo (establece su ancho y alto)
  2. Despeje el lienzo con el método canvas clearRect()
  3. Dibuje el SVG en el lienzo en -x, -y para que la parte de la imagen que se superpone al lienzo corresponda con el área que desea probar con drawImage()
  4. Obtenga el ImageData del lienzo usando getImageData() del contexto. Cada cuarto elemento de la matriz de datos es el byte alfa y un valor distinto de cero significa que parte de tu SVG se solapa con el rectángulo. Si todos los 4tos bytes son 0, entonces su SVG no se cruzó con el rectángulo.

No sé de ninguna forma de intersección de un rectángulo completo. Pero puedes intersectar un punto, por lo que podrías construir un control más complicado de eso:

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

le dará el elemento más apilado en una determinada coordenada relativa a la página. Obtendrás el elemento <svg> si no se golpean formas dentro del SVG.

Esta es una extensión de Mozilla no estándar, pero también funciona en WebKit. Lamentablemente, aunque existe en Opera, no se verá dentro de <svg> , por lo que en ese navegador el elemento siempre será SVGSVGElement.


getIntersectionList funciona bien en Opera. Mi problema es que las funciones en la especificación completa de SVG 1.1 con respecto a esto requieren que los elementos se deban representar (y posible objetivo para los eventos de puntero) para que se puedan detectar como aciertos. Desafortunadamente, esto hace que estas funciones sean inútiles para las pruebas de golpes en un mundo de juego donde solo una parte del mundo está actualmente visible.