I'm trying to write a simple html based drawing application (standalone simplified code attached bellow). I've tested this on the following devices:
The Asus tablet is running ICS, the other android tablets are running 3.1 and 3.2. I tested using the stock Android browser. I also tried the Android Chrome Beta, but that was even worse.
Here's a video which demonstrates the issue: http://www.youtube.com/watch?v=Wlh94FBNVEQ
My questions is why are the Android tablets so slow? Am I doing something wrong or is it an inherit problem with Android OS or browser, or is there anything I can do about it in my code?
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 });
});
Looking at your code, you should do some optimizing. Right off the bat, never use jQuery's $.each() to do loops. Also, every time you poll the left, top, width or height of something, you're causing the browser to stop what it's doing, repaint the entire screen, and fetch you the most accurate values. Store these values in javascript variables instead. Use google chrome's timeline feature to find and eliminate unecessary paints and reflows. Here are some helpful links:
Nicholas C. Zakas Gives You Some Tips on avoiding Reflows. http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
Here is Zakas giving his presentation to Google programmers: http://www.youtube.com/watch?v=mHtdZgou0qU
Paul Irish Speeds up a slow JavaScript in front of your eyes: http://www.youtube.com/watch?v=Vp524yo0p44 Please note, at the time of that video, the timeline was a beta feature in Chrome. It's now standard in Chrome 20. If you don't see it, update your Chrome.
Unfortunately... Even with all these optimizations... as of 2012 ...
MOST ANDROID DEVICES ARE STILL SLOW :-(
The touch events don't fire as rapidly as they do in Apple devices because Apple devices just have better hardware than most devices running Android's OS. There are fast Android tablets and phones out there, but they usually cost as much as much as the Apple devices--probably because they have similar hardware specs. Apple devices have special floating-point math chips and graphics chips in addition to the main CPU. Many Android devices do not contain those extra chips, instead they have virtual floating-point math chips.
The only thing you can do to accommodate slower Android devices is to detect them and gracefully degrade the user experience. For example, I created a draggable product carousel. For Androids, I eliminate the drag option and add clickable scroll arrows that move the carousel to the left or right a fixed set of pixels at a time.
The only way to really know where and why your code is underperforming is to profile it.
Chrome Mobile lets you connect to the WebKit inspector from your desktop, giving you access to the fantastic debugging tools you're used to in Chrome's Developer Tools.
Once you're connected to Chrome Mobile, profile your script and see what functions are chewing up CPU time. Then you'll be able to start figuring out how to optimize those functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With