2012-03-29 18 views
9

Próbuję napisać prostą aplikację do rysowania opartą na html (samodzielny uproszczony kod dołączony poniżej). Przetestowałem to na następujących urządzeniach:Powolne zdarzenia dotykowe JavaScript na Androidzie

  • iPad 1 i 2: Działa świetnie
  • ASUS T101 z systemem Windows: Działa świetnie
  • Samsung Galaxy Tab Niezwykle powolny i niejednolity - nie nadaje się do użytku.
  • Lenovo IdeaPad K1: Niezwykle powolny i niejednolity - bezużyteczny.
  • Asus Transformer Prime: Zauważalne opóźnienie w porównaniu z iPadem - blisko użyteczne.

Tablet firmy Asus korzysta z usługi ICS, a inne tablety z systemem Android działają w wersji 3.1 i 3.2. Testowałem przy użyciu standardowej przeglądarki Android. Próbowałem też Androida Chrome Beta, ale było jeszcze gorzej.

Oto film, który pokazuje problem: http://www.youtube.com/watch?v=Wlh94FBNVEQ

Moje pytania jest dlaczego Android tabletki tak wolno? Czy robię coś złego, czy jest to dziedziczny problem z systemem operacyjnym Android lub przeglądarką, czy jest coś, co mogę zrobić w moim kodzie?

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

Odpowiedz

8

Patrząc na swój kod, powinieneś dokonać optymalizacji. Od samego początku nigdy nie używaj pętli jQuery $ .each() do robienia pętli. Ponadto za każdym razem, gdy odpytujesz lewą, górną, szerokość lub wysokość czegoś, powodujesz, że przeglądarka zatrzymuje to, co robi, odświeża cały ekran i pobiera najdokładniejsze wartości. Zapisz te wartości w zmiennych javascript. Użyj funkcji osi czasu Google Chrome, aby znaleźć i wyeliminować niepotrzebne farby i zmiany przepływu. Oto kilka pomocnych linków:

Nicholas C. Zakas daje kilka wskazówek dotyczących unikania zmian przepływu. http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html

Oto Zakas podając jego prezentacji dla programistów Google: http://www.youtube.com/watch?v=mHtdZgou0qU

Paul Irish Przyspiesza powolny JavaScript w twoich oczach: http://www.youtube.com/watch?v=Vp524yo0p44 Należy pamiętać, że w momencie w tym filmie, oś czasu była funkcją beta w Chrome. Jest teraz standardem w Chrome 20. Jeśli go nie widzisz, zaktualizuj Chrome.

Niestety ... Nawet z tymi wszystkimi optymalizacje ... od 2012 ...

Większość android urządzenia są nadal powolne :-(

Zdarzenia dotykowe nie ogień tak szybko podobnie jak w urządzeniach Apple, ponieważ urządzenia Apple mają po prostu lepszy sprzęt niż większość urządzeń z systemem Android. Są tam szybkie tablety i telefony z Androidem, ale zwykle kosztują tyle samo, co urządzenia Apple - prawdopodobnie dlatego, że mają podobny sprzęt Specyfikacja: urządzenia Apple mają specjalne układy matematyczne z liczbami zmiennoprzecinkowymi i układy graficzne oprócz głównego procesora. Wiele urządzeń z Androidem nie zawiera tych urządzeń ra chipy, zamiast tego mają wirtualne układy matematyczne zmiennoprzecinkowe.

Jedyne, co możesz zrobić, aby pomieścić wolniejsze urządzenia z systemem Android, to wykryć je i zręcznie obniżyć jakość obsługi. Na przykład stworzyłem przeciągalną karuzelę produktu. W przypadku Androidów eliminuję opcję przeciągania i dodam klikalne strzałki przewijania, które przesuwają karuzelę w lewo lub w prawo o ustalony zestaw pikseli naraz.

+0

Co jest nie tak z $ .each(), aby wyliczyć kolekcję jQuery? – simbolo

+0

Jeśli robisz coś, co zdarza się rzadko, jak po domReady lub pageResize, to nie ma nic złego w $ .each(). Jeśli jednak robisz animację, $ .each() jest zbyt wolny. Jest to obudowa, więc musi ustawić obiekt, zrobić trochę crudu, a następnie usunąć obiekt. Zakas daje dobre wyjaśnienie w swojej prezentacji programistom Google (patrz wyżej). – mrbinky3000

+0

Dzięki, odszukałem niektóre wyniki jsPerf (http://jsperf.com/jquery-each-vs-regular-for-vs-optimized-for-vs-foreach/3), np. $ .each wydaje się być znacznie wolniejsze niż przy użyciu natywnych metod JavaScript. – simbolo

3

Jedynym sposobem, aby naprawdę wiedzieć, gdzie i dlaczego Twój kod jest nierentowny jest jej profil.

Chrome Mobile pozwala na connect to the WebKit inspector from your desktop, zapewniając dostęp do fantastycznych narzędzi do debugowania, do których przyzwyczailiście się w Narzędziach programistycznych Chrome.

Po nawiązaniu połączenia z Chrome Mobile zrób profil swojego skryptu i zobacz, jakie funkcje przeżuwają czas procesora. Wtedy będziesz mógł zacząć zastanawiać się, jak zoptymalizować te funkcje.

Powiązane problemy