2012-07-25 21 views
0

當我修改CSS中多個html元素的位置時,iOS5的web應用程序中有一個巨大的性能問題。我也想手動移動我的元素。我不想使用CSS轉換,因爲無法停止動畫(我們正在製作高度敏感的遊戲)。移動html元素在iOS上的位置緩慢

我的例子在Android上的桌面瀏覽器(Chrome,Firefox等)上正常工作。但是iPad 2和iPhone 4S(都運行iOS 5.1)速度非常慢。 在Phonegap應用程序中運行html5代碼比直接在瀏覽器中運行要好,但速度仍然很慢。

你有什麼建議改善事情?
editable example
full screen example

+0

你有沒有想過這個想法?這不是jquery,有iOS和移動元素髮生了什麼...... – Kevin 2013-11-02 20:49:37

+0

@Kevin Nope。我放棄了這個項目,並且減少了資源消耗......我的結論是,html5還沒有準備好用於高性能遊戲。 – poiuytrez 2013-11-04 13:29:48

回答

0

,你可以做一個明顯的一點就是緩存你的選擇,而不是每次都執行它:

// some css    
    $('#ballcanvas' + i).css("position", "absolute"); 
    $('#ballcanvas' + i).css("left", balls[i].x + "px"); 
    $('#ballcanvas' + i).css("top", balls[i].y + "px"); 
    $('#ballcanvas' + i).css("background-color", "#000000"); 

應該是這樣的:

var thisBall = $('#ballcanvas' + i) 
thisBall.css("position", "absolute"); 
... rest of your code .... 

旁白:何苦使用document.getElementById,當你已經有Jquery $

+0

他不需要選擇器。 $('#ballcanvas'+ i)剛剛創建。他必須在ballcanvas [i]上採取行動。但它不是問題,因爲這個函數只是初始化動畫。問題出現後。首先,在循環條件中使用'.length'。 Downvote是因爲當他要求速度的時候,告訴他使用jQuery。避免jQuery本來是一個很好的答案。 – dievardump 2012-07-25 13:57:58

1

首先,如果你想要的東西不慢,避免所有的jQuery調用你可以。

這是我怎麼會重寫(真的很快),你的代碼:

// shim layer with setTimeout fallback 
window.requestAnimFrame = (function(){ 
    return window.requestAnimationFrame  || 
      window.webkitRequestAnimationFrame || 
      window.mozRequestAnimationFrame || 
      window.oRequestAnimationFrame  || 
      window.msRequestAnimationFrame  || 
      function(callback){ 
      window.setTimeout(callback, 1000/60); 
      }; 
})(); 

var canvas = document.getElementById('canvas-test'); 
    canvas.height = 500; 
    canvas.width = 500; 
    var context = canvas.getContext('2d'); 

    // in this example, the fillstyle is always the same. no need to change it at every loop 
    context.fillStyle = "#FF0000"; 


var balls = []; 
var ballcanvas = []; 
var ballctx = []; 

// create 30 balls in canvases 
var eDivBody = document.getElementById('divbody'); 
for (var i = 0; i < 30; i++){ 
    balls[i] = { 
     x : 250, 
     y : 100 + i * 2, 
     dx : 3, // direction 
    }; 

    // create the canvas 
    var eBall = document.createElement('canvas'); 
    eBall.id = 'ballcanvas' + i; 
    eBall.width = 75; 
    eBall.height = 75; 
    eDivBody.appendChild(eBall); 

    // some css 
    // no need for jQuery 
    eBall.style.position = "absolute"; 
    eBall.style.left = balls[i].x + "px"; 
    eBall.style.top = balls[i].y + "px"; 
    eBall.style.backgroundColor = "#000000"; 

    // associate the element to the ball, no need to go threw the DOM after 
balls[i].element = eBall; 
} 


var ball_test = { 
    x : 250, 
    y : 300, 
    dx : 3 // direction 
}; 


function loop(ball_test, balls, canvas, context, ballcanvas, ballctx){ 
    //change of direction on the sides 
    if (ball_test.x > 400 || ball_test.x < 100) 
     ball_test.dx *= -1; 
    // movement 
    ball_test.x += ball_test.dx; 

    // the same for balls in canvases 
    // never use array.legth in a loop condition. put it in a variable then compare. 
    for (var i = 0, j = balls.length; i < j; i++){ 
     // balls are following the test ball, no need to re-check the bounds 
     // we take the test ball direction 
     balls[i].dx = ball_test.dx; 

     //movement 
     balls[i].x += balls[i].dx; 
     // change left style - No need for jQuery 
     balls[i].element.style.left = balls[i].x + "px"; 
    } 

    // display ball_test 
    displayBallTest(ball_test, canvas, context); 

    // Prefer the use of requestAnimationFrame 
    requestAnimFrame(function(){ 
     loop(ball_test, balls, canvas, context, ballcanvas, ballctx); 
    }); 
}; 

// no need to recalculate Math.PI * 2 for every loop. 
// do it just the first time then use the value 
var pi2 = Math.PI * 2; 

function displayBallTest(ball, canvas, context){ 
    // clear canvas  
    // you don't need to clear all the canvas, just the zone where you now the ball is. 
    // must need some calculation to be the most efficient possible 
    context.clearRect(ball.x - 50 , ball.y - 50, 100, 100); 

    context.beginPath(); 
    context.arc(ball.x, ball.y, 40, 0, pi2); 
    context.fill(); 
}; 

// start main loop 
loop(ball_test, balls, canvas, context, ballcanvas, ballctx); 

我評論的代碼,但這裏是我所做的:

  • 完全避免的jQuery。沒有必要,除非是準備好,如果你選擇使用requestAnimationFrame時可能
  • 避免值的重新計算或復位時,他們是全球 (Math.PI * 2不要把你的腳本在內容
  • 結束, context.fillStyle ...)
  • 避免使用。長度,如果for循環條件

但我覺得你的問題,從要移動,而不是畫嗎更有內容到30種畫布元素的事實來主要畫布。 iOS使用Canvas繪圖時已知速度很快。 對我而言,如果您選擇在主畫布上繪製而不是移動DOM元素,則可以解決性能問題。

+0

我們使用30畫布,因爲它在Android上非常緩慢地在主畫布上繪製多個項目(http://stackoverflow.com/questions/11557651/html5-canvas-animation-slow-on-android)。我們希望爲多個設備提供相同的代碼庫。 – poiuytrez 2012-07-25 15:02:04