2012-03-29 14 views
9

Estoy tratando de escribir una aplicación de dibujo basada en HTML simple (código simplificado independiente adjunto a continuación). He probado esto en los siguientes dispositivos:Eventos Slow JavaScript touch en Android

  • iPad 1 y 2: Funciona muy bien
  • ASUS T101 con Windows: funciona muy bien
  • Samsung Galaxy Tab: Extremadamente lenta y desigual inutilizable
  • Lenovo IdeaPad K1: Extremadamente lento y desigual - inutilizable.
  • Asus Transformer Prime: Lag sensible se compara con el iPad - cerca de utilizable.

La tableta Asus funciona con ICS, las otras tabletas Android funcionan con 3.1 y 3.2. Probé usando el stock del navegador de Android. También probé Android Chrome Beta, pero eso fue incluso peor.

Aquí hay un video que demuestra el problema: http://www.youtube.com/watch?v=Wlh94FBNVEQ

Mi pregunta es ¿por qué son las tabletas de Android es tan lenta? ¿Estoy haciendo algo mal o es un problema heredado con el sistema operativo Android o el navegador, o hay algo que pueda hacer al respecto en mi código?

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 }); 
}); 

Respuesta

8

En cuanto a su código, debe hacer algo de optimización. Desde el primer momento, nunca use $ .each() de jQuery para hacer bucles. Además, cada vez que sondeas la izquierda, la parte superior, la anchura o la altura de algo, estás haciendo que el navegador detenga lo que está haciendo, vuelva a pintar toda la pantalla y obtenga los valores más precisos. Almacene estos valores en las variables de JavaScript en su lugar. Utilice la función de línea de tiempo de google chrome para buscar y eliminar pinturas y reflujos innecesarios. Aquí hay algunos enlaces útiles:

Nicholas C. Zakas le da algunos consejos para evitar reflujos. http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html

Aquí se Zakas da su presentación a los programadores de Google: http://www.youtube.com/watch?v=mHtdZgou0qU

Paul Irish acelera una lenta JavaScript delante de sus ojos: http://www.youtube.com/watch?v=Vp524yo0p44 Tenga en cuenta, en el momento de ese video, la línea de tiempo fue una función beta en Chrome. Ahora es estándar en Chrome 20. Si no lo ves, actualiza tu Chrome.

desgracia ... A pesar de todas estas optimizaciones ... a partir de 2012 ...

mayoría de dispositivos Android todavía están :-(LENTO

Los eventos de toque no se activan con la mayor rapidez como lo hacen en los dispositivos Apple porque los dispositivos Apple tienen mejor hardware que la mayoría de los dispositivos con sistema operativo Android. Hay tabletas y teléfonos Android rápidos, pero generalmente cuestan tanto como los dispositivos Apple, probablemente porque tienen un hardware similar. especificaciones. Los dispositivos de Apple tienen chips matemáticos especiales de coma flotante y chips gráficos además de la CPU principal. Muchos dispositivos Android no contienen esos ext. ra chips, en su lugar tienen chips matemáticos virtuales de punto flotante.

Lo único que puede hacer para acomodar dispositivos Android lentos es detectarlos y degradar con gracia la experiencia del usuario. Por ejemplo, creé un carrusel de producto arrastrable. Para Androids, elimino la opción de arrastre y agrego flechas de desplazamiento que se pueden hacer clic que mueven el carrusel hacia la izquierda o hacia la derecha, un conjunto fijo de píxeles a la vez.

+0

¿Qué pasa con $ .each() de jQuery para enumerar una colección? – simbolo

+0

Si está haciendo algo que ocurre con poca frecuencia, como después de domReady o pageResize, entonces no hay nada de malo en $ .each(). Sin embargo, si está haciendo una animación, $ .each() es demasiado lento. Es un recinto, por lo que tiene que configurar un objeto, hacer algo de crud, luego quitar el objeto. Zakas da una buena explicación en su presentación a los programadores de Google (ver arriba). – mrbinky3000

+0

Gracias, he buscado algunos resultados de jsPerf (http://jsperf.com/jquery-each-vs-regular-for-vs-optimized-for-vs-foreach/3) por ejemplo, $ .each aparece como ser mucho más lento que usar métodos nativos de JavaScript. – simbolo

3

La única manera de saber realmente dónde y por qué su código está dando la talla es el perfil it.

Chrome Mobile te permite connect to the WebKit inspector from your desktop, que te da acceso a las fantásticas herramientas de depuración a las que estás acostumbrado en las herramientas para desarrolladores de Chrome.

Una vez que esté conectado a Chrome Mobile, perfile su secuencia de comandos y vea qué funciones están masticando el tiempo de la CPU. Entonces podrá comenzar a descubrir cómo optimizar esas funciones.