Javascript 在iOS上缓慢移动html元素
当我修改CSS中多个html元素的位置时,我在iOS html5 webapp上有一个巨大的性能问题。我还想手动移动我的元素。我不想使用CSS转换,因为它是不可能停止动画(我们正在制作一个高度响应的游戏) 我的示例在Android上的桌面浏览器(chrome、firefox等)上运行良好。但在iPad2和iPhone4S(都运行iOS5.1)上速度非常慢。 在Phonegap应用程序中运行html5代码比直接在浏览器中运行要好,但速度仍然很慢 你有什么改进的建议吗?Javascript 在iOS上缓慢移动html元素,javascript,jquery,css,ios,html,Javascript,Jquery,Css,Ios,Html,当我修改CSS中多个html元素的位置时,我在iOS html5 webapp上有一个巨大的性能问题。我还想手动移动我的元素。我不想使用CSS转换,因为它是不可能停止动画(我们正在制作一个高度响应的游戏) 我的示例在Android上的桌面浏览器(chrome、firefox等)上运行良好。但在iPad2和iPhone4S(都运行iOS5.1)上速度非常慢。 在Phonegap应用程序中运行html5代码比直接在浏览器中运行要好,但速度仍然很慢 你有什么改进的建议吗? 您可以做的一件显而易见的事
您可以做的一件显而易见的事情是缓存选择器,而不是每次都执行它:
// 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 ....
旁白:既然你已经有了Jquery
$
,为什么还要麻烦使用document.getElementById
,首先,如果你想要不慢的东西,尽量避免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);
//使用setTimeout回退填充层
window.requestAnimFrame=(函数(){
return window.requestAnimationFrame | |
window.webkitRequestAnimationFrame | |
window.mozRequestAnimationFrame | |
window.oRequestAnimationFrame | |
window.msRequestAnimationFrame | |
函数(回调){
设置超时(回调,1000/60);
};
})();
var canvas=document.getElementById('canvas-test');
高度=500;
画布宽度=500;
var context=canvas.getContext('2d');
//在本例中,fillstyle始终相同。不需要在每次循环中都更改它
context.fillStyle=“#FF0000”;
var=[];
var=[];
var-ballctx=[];
//在画布中创建30个球
var eDivBody=document.getElementById('divbody');
对于(变量i=0;i<30;i++){
球[i]={
x:250,
y:100+i*2,
dx:3,//方向
};
//创建画布
var eBall=document.createElement('canvas');
eBall.id='ballcanvas'+i;
eBall.width=75;
eBall.height=75;
eDivBody.appendChild(eBall);
//一些css
//不需要jQuery
eBall.style.position=“绝对”;
eBall.style.left=balls[i].x+“px”;
eBall.style.top=球[i].y+“px”;
eBall.style.backgroundColor=“#000000”;
//将元素与球相关联,无需将DOM扔到后面
balls[i]。元素=eBall;
}
var ball_试验={
x:250,
y:300,
dx:3//方向
};
函数循环(ball_测试、balls、canvas、context、ballcanvas、ballctx){
//转向
如果(球|u试验x>400 |球|u试验x<100)
ball_test.dx*=-1;
//运动
ball_test.x+=ball_test.dx;
//画布上的球也是如此
//切勿在循环条件中使用array.legth。将其放入变量中,然后进行比较。
对于(变量i=0,j=balls.length;i
我对代码进行了注释,但以下是我所做的:
- 完全避免jQuery。没有必要,除非准备好了,如果你选择不把你的脚本放在内容的末尾
- 尽可能使用requestAnimationFrame
- 避免重新计算或重置全局值 (Math.PI*2,context.fillStyle…)
- 避免使用.length if for循环条件
对我来说,如果您选择在主画布上绘制而不是移动DOM元素,性能问题将得到解决。他不需要选择器$(“#ballcanvas”+i)是在之前创建的。他必须按计划行事。但这不是问题,因为此函数只是初始化动画。问题随之而来。首先,在循环条件中使用
.length
。向下投票,因为当他要求快速时,您告诉他使用jQuery。避免使用jQuery可能是一个很好的答案。我们使用30画布,因为在Android上在主画布上绘制多个项目非常慢()。我们希望在多台设备上使用相同的代码库。你有没有弄明白这一点?这不是jquery,是iOS和移动元素的问题…@Kevin Nope。我放弃了这个项目,做了一些资源消耗更少的东西。。。我的结论是html5还没有为高性能游戏做好准备。