Android上缓慢的Javascript触摸事件

Android上缓慢的Javascript触摸事件,javascript,android,mobile,touch,Javascript,Android,Mobile,Touch,我正在尝试编写一个简单的基于html的绘图应用程序(下面附带独立的简化代码)。我已在以下设备上对此进行了测试: iPad1和iPad2:非常好用 运行Windows的华硕T101:效果非常好 三星Galaxy标签:速度极慢且不完整--无法使用 联想IdeaPad K1:速度极慢且不完整--无法使用 华硕Transformer Prime:与iPad相比明显滞后——接近可用 华硕平板电脑运行的是ICS,其他安卓平板电脑运行的是3.1和3.2。我使用Android股票浏览器进行了测试。我也试过A

我正在尝试编写一个简单的基于html的绘图应用程序(下面附带独立的简化代码)。我已在以下设备上对此进行了测试:

  • iPad1和iPad2:非常好用
  • 运行Windows的华硕T101:效果非常好
  • 三星Galaxy标签:速度极慢且不完整--无法使用
  • 联想IdeaPad K1:速度极慢且不完整--无法使用
  • 华硕Transformer Prime:与iPad相比明显滞后——接近可用
华硕平板电脑运行的是ICS,其他安卓平板电脑运行的是3.1和3.2。我使用Android股票浏览器进行了测试。我也试过Android Chrome测试版,但那更糟

下面是一段视频,演示了这个问题:

我的问题是,为什么安卓平板电脑速度如此之慢?我是做错了什么,还是Android操作系统或浏览器存在继承问题,或者在我的代码中我可以做些什么

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>

要真正了解代码在何处以及为什么表现不佳,唯一的方法就是对其进行评测

Chrome Mobile让您可以使用Chrome开发工具中使用的出色调试工具


一旦你连接到Chrome Mobile,分析一下你的脚本,看看哪些功能占用了CPU时间。然后,您将能够开始了解如何优化这些函数。

查看您的代码,您应该进行一些优化。一开始就不要使用jQuery的$.each()进行循环。此外,每次轮询某个对象的左侧、顶部、宽度或高度时,都会导致浏览器停止工作,重新绘制整个屏幕,并获取最准确的值。而是将这些值存储在javascript变量中。使用google chrome的时间线功能查找并消除不必要的油漆和回流焊。以下是一些有用的链接:

Nicholas C.Zakas为您提供了一些避免回流的技巧。

下面是扎卡斯向谷歌程序员的演讲:

保罗·爱尔兰(Paul Irish)在你眼前加速一个缓慢的JavaScript: 请注意,在拍摄该视频时,时间线是Chrome的测试版功能。它现在是Chrome 20的标准配置。如果你看不到,更新你的Chrome

不幸的是。。。即使有了这些优化。。。截至2012年

大多数安卓设备仍然运行缓慢:-(

触摸事件的启动速度不如苹果设备,因为苹果设备的硬件比大多数运行安卓操作系统的设备都要好。安卓平板电脑和手机的速度很快,但它们的价格通常与苹果设备一样高——可能是因为它们的硬件规格相似。苹果设备有特殊的功能除了主CPU之外,还有浮点数学芯片和图形芯片。许多Android设备不包含这些额外的芯片,而是有虚拟浮点数学芯片


为了适应较慢的Android设备,您唯一能做的就是检测它们,并优雅地降低用户体验。例如,我创建了一个可拖动的产品旋转木马。对于Android,我取消了拖动选项,并添加了可单击的滚动箭头,可将旋转木马一次向左或向右移动一组固定的像素。

怎么了使用jQuery的$.each()枚举集合?如果您正在做一些很少发生的事情,例如在domReady或pageResize之后,则$.each()没有任何问题。但是,如果您正在做动画,$.each()太慢了。它是一个封闭空间,所以它必须设置一个对象,执行一些crud,然后删除该对象。Zakas在他给Google程序员的演示中给出了一个很好的解释(见上文)。谢谢,因为我查找了一些jsPerf结果(),例如,$。每个结果看起来都比使用本机JavaScript方法慢得多。
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 });
});