2013-04-19 8 views
12

Visualizzo un codice HTML, con un file SVG incorporato. Voglio che rilevi gli eventi del mouse, ma non funziona sul cellulare (Android Jellybean). Funziona bene per un browser desktop.Can * you * get SVG sul browser mobile accetta eventi mouse/touch? Non riesco a

Questa è una pagina di dimostrazione: http://artsyenta.org/misc/ss/j.touchtry1.html.

Se si trascina il mouse sui cerchi, viene visualizzato un registro di voci del mouse negli elementi denominati "j_xxx". Funziona su Firefox e Chrome.

Apri il tuo tablet Android (l'ho provato anche sull'iPhone di qualcuno, con gli stessi risultati). Trascina il dito sulle cerchie e ottieni un evento touchenter solo di tanto in tanto. Nient'altro mostra.

È possibile visualizzare l'intera pagina e il codice visualizzando l'origine della pagina. Non è lungo, la parte più lunga è la definizione SVG. Le parti importanti sono:

$(document).ready(function() { 
    makeSomethingHappen("hello"); 
}); 
function makeSomethingHappen(svg) { 
    placeATop(true); 
    $('[class^=j_]') 
    .on("mouseover", function(event) { logAction(event, this); }) 
    .on("mouseout", function(event) { logAction(event, this); }) 
    .on("touchstart", function(event) { logAction(event, this); }) 
    .on("touchend", function(event) { logAction(event, this); }) 
    .on("touchenter", function(event) { logAction(event, this); }) 
    .on("touchleave", function(event) { logAction(event, this); }) 
    .on("touchEnter", function(event) { logAction(event, this); }) 
    .on("touchLeave", function(event) { logAction(event, this); }); 
} 

var cntAct = 0; 
function logAction(ev, ele) { 
    cntAct++; 
    var logSpan = $('#logTrace'); 
    logSpan.html("" + cntAct + ": " + ev.type + " '" + $(ele).attr("class") 
     + "'<br/>" + logSpan.html()); 
} 

Ecco parte del SVG:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
    id="jsvg" x="0px" y="0px" width="376.247px" height="364.318px" viewBox="140 110 130 120" 
    enable-background="new 0 0 376.247 364.318" xml:space="preserve"> 
    <g id="Layer_1"> 
    <path class="j_aa_" opacity="0.75" fill="#FFFFFF" stroke="#0071BC" stroke-width="0.9925" enable-background="new " d="M224.739,6.55l-6.414,23.957c-10.377-2.785-21.304-2.785-31.671,0L180.232,6.55C194.813,2.63,210.155,2.63,224.739,6.55z"/> 
    [snip] 
    </g> 
</svg> 

Ancora una volta, rilevo eventi del mouse su un browser desktop, ma non toccare o del mouse eventi per un browser mobile. C'è una tecnica mancante o qualcosa manca con i cellulari? Fallisce con il browser iPhone, Google Chrome su Jellybean e Firefox mobile.

Grazie in anticipo, Jerome.

+0

SVG sui browser mobili è molto limitata: http://caniuse.com/# search = svg – jgillich

+0

Prova a utilizzare il debugger remoto su Chrome mobile per vedere cosa succede passo passo. Tuttavia, dovrebbe funzionare, non penso che sia un problema SVG! –

+0

Per jgillich, per caniuse.com SVG dovrebbe funzionare su Chrome. Per F.X., ho provato un debug remoto su Chrome mobile. Ho due pagine, la j.touchtry1.html con semplice SVG e una che usa la libreria RaphaelJS (j.raphael6.html). La precedente pagina genera un occasionale evento da falso. L'ultima pagina genera alcuni "non definiti" (event.type non viene impostato quando viene generato l'evento). Ho disattivato un "ho cambiato in un altro percorso SVG/finestra?" rivelatore. Dovrei avere centinaia di eventi per me. Ne ricevo un po 'di tanto in tanto. Proverò a eseguire il debug delle demo di Raphael che * funzionano *. –

risposta

8

Dopo molte ricerche su eventi SVG semplici e eventi RaphaelJS, ho una soluzione praticabile per ciascuno. Ecco una soluzione RaphaelJS:

window.onload = function(e) { 
    document.getElementById("rsr").addEventListener("mousemove", 
     function(event) { 
      logAction(event, this, "m"); 
     }, false); 

    document.getElementById("rsr").addEventListener("touchmove", 
     function(event) { 
      if(event.preventDefault) event.preventDefault(); 
      // perhaps event.targetTouches[0]? 
      logAction(event.changedTouches[0], this, "t"); 
     }, false); 
}; 

Il codice non è a tenuta stagna, ma illustra i punti principali.

Prima di tutto, gli eventi devono essere registrati tramite la chiamata addEventHandler(). Usando RaphaelJS onmousemove(), ecc., I gestori non funzionano sul tablet.

In secondo luogo, per gli eventi di tocco è necessario scavare nella lista dei tocchi. La mia applicazione interessa solo un dito, e quindi l'evento [0] della lista è sufficiente. Ci sono un certo numero di elenchi: tocchi, targetTouches, changedTouches, quindi scegli uno appropriato.

In terzo luogo, determinare se la finestra deve creare una bolla per gli eventi. Ottengo più sensibilità ai tocchi se chiamo preventDefault().

L'ho provato su Google Nexus, iPad 3 e iPad Mini. Buoni risultati.

Ho anche una soluzione per SVG semplice. Si basa su questo sito: http://my.opera.com/MacDev_ed/blog/2010/02/01/how-to-get-all-svg-elements-intersected-by-a-given-rectangle

Le differenze per quello che uso e il javascript che usa sono, ancora una volta, per i tocchi che la lista dei tocchi deve accedere. "root" è l'ID dell'elemento svg per questo esempio. "logTrace" è un'estensione che riceve commenti.

var root = document.getElementById("root"); 
var evtt = evt.touches[0]; 

var rpos = root.createSVGRect(); 
rpos.x = evtt.clientX; 
rpos.y = evtt.clientY; 
rpos.width = rpos.height = 1; 
var list = root.getIntersectionList(rpos, null); 
var maxItemId = list.length <= 0 ? "(no match)" : list[list.length - 1].id; 

document.getElementById("logTrace").innerHTML = "screen: (" + evtt.clientX + ", " + evtt.clientY + ") ? uu(" + maxItemId + "): (" + uupos.x.toFixed(0) + "," + uupos.y.toFixed(0) + ")"; 

Ho testato con successo questa soluzione su un Nexus e un iPad. Tuttavia, si comporta male su un iPad Mini - perché comportarsi in modo diverso su due dispositivi iPad?

Ho anche notato che la soluzione "plain svg" non sembra rilevare con la stessa precisione della versione RaphaelJS. Vicino ai bordi dei miei elementi SVG il rilevamento non è molto buono con il semplice rilevamento svg. Ottengo costantemente buoni risultati per l'uso di RaphaelJS.

OTOH, l'uso di RaphaelJS è sensibile a SVG con (riempimento: nessuno). Il semplice SVG non interessa se (riempimento: nessuno) è impostato in un elemento. Scegli il tuo veleno.

+0

Grazie per aver spiegato questo in dettaglio. Domanda - Come funzionerà quando stai trascinando qualcosa da un altro oggetto e vuoi che l'evento tattile sia kick-in quando trascini l'elemento raphael. Per qualche ragione sul modulo eventi del mouse del browser viene fatto clic su Raphael, ma gli eventi touch non vengono chiamati su iPad. qualche idea? – Mutant

+0

Non ho lavorato molto con Raphael perché potevo accedere agli elementi SVG attraverso il DOM in modo semplice. Per me, Raffaello non era necessario. Ho provato a implementare qualcosa di trascinabile nel modello DOM/SVG. Incostante, un sacco di mancanza di risposta e balbuzie sul mio Android. Per quanto riguarda l'esperienza iPad, c'è chatter (fai una ricerca su iOS 8 e su come abilita gli eventi di scorrimento) che quando si fa scorrere l'iPad si spegne la pittura fino a un momento successivo. Forse lo fa anche durante il trascinamento. –

1

Ho avuto questo problema e si scopre che l'iPad considera l'opacità di un oggetto per la sua funzione hit-test, quindi se si dispone di qualcosa con riempimento: nessuno non registrerà un evento.

ho testato con successo un percorso con questo stile:

.st5 {fill:none;fill-opacity:0.01;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72} 

e due gestori di eventi immessi sul tag contenente il percorso:

<g ... onclick="top.load(3201);" ontouchend="top.load(3201);" > ...path here with style .st5 </g> 

la funzione load(id) è memorizzato in un file JS esterno.

Un altro problema è che lo SVG deve essere posizionato direttamente all'interno del HTML DOM e non si fa riferimento come <embed .../>, quest'ultimo provoca eccezioni sicurezza

supporto
+0

Grazie per la risposta. Ho anche notato che i miei elementi (iPad o Android) dovevano avere opacità o che l'evento assegnato non funzionava. –

Problemi correlati