2015-03-31 8 views
5

Próbuję wykryć mousemove wydarzenia na częściowo nakładających się elementów SVG, jak w tym obrazieWykrywanie Zdarzenia myszy na wielu nakładających się elementów SVG

enter image description here

fiddle

<svg> 
    <rect id="red" x=10 y=10 width=60 height=60 style="fill:#ff0000" /> 
    <rect id="orange" x=80 y=10 width=60 height=60 style="fill:#ffcc00" /> 
    <rect id="blue" x=50 y=30 width=60 height=60 style="fill:#0000ff; fill-opacity: 0.8" /> 
</svg> 

$('rect').on('mousemove', function() 
{ 
    log(this.id); 
}); 

Teraz, po najechaniu kursor myszy nad niebieskim/czerwonym przecięciem Chciałbym wykryć zdarzenia myszy na obu tych elementach, i to samo dla kombinacji niebiesko-pomarańczowej. Jak widać w dziennikach, w tych przypadkach zdarzenie jest obecnie uruchamiane tylko dla niebieskiego pola, tak jak jest na górze.

Ma to związek ze wskaźnikami zdarzeń, ponieważ mogę uzyskać czerwone i pomarańczowe elementy, które wystrzeliwują zdarzenie, a najechanie na niebieski element przez setting the blue element's pointer-events to none. Ale nie dostaję zdarzeń dla niebieskiego pudełka, więc nie jest to opłacalna opcja.

Będę używać tej biblioteki, która rozwiązuje ten problem. Przyjrzałem się wydarzeniu bulgotającemu jak w this d3 example, ale działa to tylko dla elementów zagnieżdżonych w DOM. Mam wiele niezależnych elementów, które mogą nakładać się z wieloma innymi elementami i dlatego nie mogą w ten sposób strukturyzować mojego DOM.

Domyślam się, że ostatnią deską ratunku jest znalezienie elementów znajdujących się w bieżącej pozycji myszy i ręczne wywoływanie zdarzeń. W związku z tym przyjrzałem się document.elementFromPoint(), ale dałoby to tylko 1 element (i może nie działać w SVG?). Znalazłem funkcję jQuerypp, która znajduje elementy w danej pozycji, patrz here. Ten przykład wygląda świetnie, z wyjątkiem DIV, a nie w SVG. Podczas zastępowania elementów div prostymi elementami svg, skrzypce wydają się być break.

Co mam zrobić ?!

+2

Wygląda na to, że jquerypp używa 'offsetWidth' i' offsetHeight', które (przynajmniej w chrome) zwracają 0 dla rects. –

+1

Czy możesz liczyć na każde "" mające atrybuty szerokości i wysokości? Jeśli tak, możesz wywołać 'parseInt (el.attr (" width "))', aby użyć szerokości jako liczby całkowitej. Sprawdź, czy [to skrzypce] (http://jsfiddle.net/amullins/5c88b8yf/) będzie działało dla ciebie. –

+0

@JamesMontagne Dobry punkt. Prawdopodobnie zostanie to naprawione, a następnie zadziała. Przyjrzę się temu. –

Odpowiedz

5

Świetne komentarze tutaj dały mi odpowiedź: Możliwe jest ręczne propagowanie zdarzenia do odpowiednich elementów poprzez znalezienie ich przy użyciu pozycji getIntersectionList() w pozycji kursora.

$('svg').on('mousemove', function(evt) 
{ 
    var root = $('svg')[0]; 
    var rpos = root.createSVGRect(); 
    rpos.x = evt.clientX; 
    rpos.y = evt.clientY; 
    rpos.width = rpos.height = 1; 
    var list = root.getIntersectionList(rpos, null); 

    for(var i = 0; i < list.length; i++) 
    { 
     if(list[i] != evt.target) 
     { 
      $(list[i]).mousemove(); 
     } 
    } 
}); 

przykład robocza: http://jsfiddle.net/michaschwab/w0wufbtn/6/

Jeśli pozostali słuchacze potrzebować oryginalny obiekt zdarzenia, sprawdź http://jsfiddle.net/michaschwab/w0wufbtn/13/.

Wielkie dzięki!

+2

To działa dobrze w IE, Chrome i Opera (i prawdopodobnie Safari), ale zauważ, że getIntersectionList nie jest jeszcze zaimplementowana w Firefoksie, zobacz https://bugzilla.mozilla.org/show_bug.cgi?id=501421. –

+1

Również wywoływana myszka nie ma informacji o oryginalnym zdarzeniu, więc na przykład pomarańczowy rect nie otrzymuje informacji o myszach. Przejście w 'mousemove (evt)' również tego nie rozwiązuje. – thund

+0

Dzięki za komentarze. @thund: To ma związek z jQuery i można je rozwiązać, wywołując 'trigger()' zamiast 'mousemove()'. Zobacz http://jsfiddle.net/michaschwab/w0wufbtn/12/ dla zaktualizowanej odpowiedzi. –

Powiązane problemy