2012-03-29 23 views
9

Sto provando a scrivere una semplice applicazione di disegno basata su HTML (codice semplificato standalone allegato qui sotto). Ho provato questo sui seguenti dispositivi:Eventi di tocco lento lento su Android

  • iPad 1 e 2: Grandi opere
  • ASUS T101 con Windows: grandi opere
  • Samsung Galaxy Tab: estremamente lento e irregolare - inutilizzabile.
  • Lenovo IdeaPad K1: Estremamente lento e irregolare - inutilizzabile.
  • Asus Transformer Prime: lag notevole rispetto all'iPad - vicino a utilizzabile.

Il tablet Asus esegue ICS, gli altri tablet Android sono in esecuzione 3.1 e 3.2. Ho provato usando il browser Android di serie. Ho anche provato l'Android Chrome Beta, ma era anche peggio.

Ecco un video che dimostra il problema: http://www.youtube.com/watch?v=Wlh94FBNVEQ

Le mie domande è il motivo per cui sono le tavolette Android così lento? Sto facendo qualcosa di sbagliato o è un problema ereditario con sistema operativo Android o browser, o c'è qualcosa che posso fare al riguardo nel mio codice?

multi.html:

<html> 
<body> 

<style media="screen"> 
    canvas { border: 1px solid #CCC; } 
</style> 

<canvas style="" id="draw" height="450" width="922"></canvas> 

<script class="jsbin" src="jquery.js"></script> 
<script src="multi.js"></script> 

</body> 
</html> 

multi.js:

var CanvasDrawr = function(options) { 
    // grab canvas element 
    var canvas = document.getElementById(options.id), 
    ctxt = canvas.getContext("2d"); 

canvas.style.width = '100%' 
    canvas.width = canvas.offsetWidth; 
    canvas.style.width = ''; 

    // set props from options, but the defaults are for the cool kids 
    ctxt.lineWidth = options.size || Math.ceil(Math.random() * 35); 
    ctxt.lineCap = options.lineCap || "round"; 
    ctxt.pX = undefined; 
    ctxt.pY = undefined; 

    var lines = [,,]; 
    var offset = $(canvas).offset(); 

    var eventCount = 0; 

    var self = { 
    // Bind click events 
    init: function() { 
     // Set pX and pY from first click 
     canvas.addEventListener('touchstart', self.preDraw, false); 
     canvas.addEventListener('touchmove', self.draw, false); 
    }, 

    preDraw: function(event) { 
     $.each(event.touches, function(i, touch) { 

     var id = touch.identifier; 

     lines[id] = { x  : this.pageX - offset.left, 
         y  : this.pageY - offset.top, 
         color : 'black' 
        }; 
     }); 

     event.preventDefault(); 
    }, 

    draw: function(event) { 
     var e = event, hmm = {}; 

     eventCount += 1; 
     $.each(event.touches, function(i, touch) { 
     var id = touch.identifier, 
     moveX = this.pageX - offset.left - lines[id].x, 
     moveY = this.pageY - offset.top - lines[id].y; 

     var ret = self.move(id, moveX, moveY); 
     lines[id].x = ret.x; 
     lines[id].y = ret.y; 
     }); 

     event.preventDefault(); 
    }, 

    move: function(i, changeX, changeY) { 
     ctxt.strokeStyle = lines[i].color; 
     ctxt.beginPath(); 
     ctxt.moveTo(lines[i].x, lines[i].y); 

     ctxt.lineTo(lines[i].x + changeX, lines[i].y + changeY); 
     ctxt.stroke(); 
     ctxt.closePath(); 

     return { x: lines[i].x + changeX, y: lines[i].y + changeY }; 
    }, 
    }; 

    return self.init(); 
}; 


$(function(){ 
    var drawr = new CanvasDrawr({ id: "draw", size: 5 }); 
}); 

risposta

8

Guardando il tuo codice, dovresti fare un po 'di ottimizzazione. A prima vista, non usare mai $ .each() di jQuery per fare loop. Inoltre, ogni volta che esegui il polling a sinistra, in alto, in larghezza o in altezza di qualcosa, stai facendo in modo che il browser interrompa ciò che sta facendo, ridisegna l'intero schermo e recupera i valori più accurati. Memorizza questi valori in variabili javascript. Utilizza la funzione cronologia di google chrome per trovare ed eliminare vernici e riflessi non necessari. Ecco alcuni link utili:

Nicholas C. Zakas offre alcuni suggerimenti su come evitare i riflessi. http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html

Qui sta Zakas dare la sua presentazione al Google programmatori: http://www.youtube.com/watch?v=mHtdZgou0qU

Paul Irish Accelera un lento JavaScript davanti ai vostri occhi: http://www.youtube.com/watch?v=Vp524yo0p44 Si prega di notare, al momento della quel video, la cronologia era una funzione beta in Chrome. Ora è standard in Chrome 20. Se non lo vedi, aggiorna Chrome.

Purtroppo ... Anche con tutte queste ottimizzazioni ... dal 2012 ...

maggior parte dei dispositivi Android sono ANCORA :-(SLOW

Gli eventi touch non vengono attivati ​​più rapidamente come fanno nei dispositivi Apple perché i dispositivi Apple hanno un hardware migliore rispetto alla maggior parte dei dispositivi con sistema operativo Android. Ci sono veloci tablet e telefoni Android là fuori, ma di solito costano tanto quanto i dispositivi Apple - probabilmente perché hanno un hardware simile Le periferiche Apple hanno speciali chip matematici a virgola mobile e chip grafici oltre alla CPU principale.Molti dispositivi Android non contengono quelli ext ra chips, invece hanno chip matematici virtuali in virgola mobile.

L'unica cosa che puoi fare per ospitare dispositivi Android più lenti è rilevarli e degradare con grazia l'esperienza dell'utente. Ad esempio, ho creato un carosello di prodotto trascinabile. Per Androids, elimino l'opzione di trascinamento e aggiungo frecce di scorrimento cliccabili che spostano il carosello a sinistra oa destra di un insieme fisso di pixel alla volta.

+0

Cosa c'è che non va con $ .each() di jQuery per enumerare una raccolta? – simbolo

+0

Se stai facendo qualcosa che accade raramente, come dopo un domReady o pageResize, allora non c'è niente di sbagliato con $ .each(). Tuttavia, se stai facendo un'animazione, $ .each() è troppo lento. È un recinto, quindi deve creare un oggetto, fare un po 'di sporco, quindi rimuovere l'oggetto. Zakas fornisce una buona spiegazione nella sua presentazione ai programmatori di Google (vedi sopra). – mrbinky3000

+0

Grazie, da allora ho cercato alcuni risultati di jsPerf (http://jsperf.com/jquery-each-vs-regular-for-vs-optimized-for-vs-foreach/3), ad esempio $ .each sembra essere molto più lento rispetto all'utilizzo di metodi JavaScript nativi. – simbolo

3

L'unico modo per sapere davvero dove e perché il codice è poco efficiente è quello di profilo it.

Chrome Mobile ti consente di effettuare il connect to the WebKit inspector from your desktop, dando accesso ai fantastici strumenti di debug a cui sei abituato negli Strumenti per sviluppatori di Chrome.

Una volta connesso a Chrome Mobile, crea un profilo per il tuo script e scopri quali funzioni stanno masticando il tempo della CPU. Quindi sarai in grado di iniziare a capire come ottimizzare quelle funzioni.