我正在html5 canvas上构建用于对象管理的小型库。每个对象都有x和y属性,说明对象应该在画布上的位置。我想复制DOM属性修改(当我做elm.style.left ='100px',更改立即反映)到我的库。渲染是在特殊函数中管理的,所以我想在每次修改任何对象时调用此函数(+其他一些函数,如设置的碰撞检测,......)。
<小时/> 编辑: 我有一个像这样的对象:
{
x: 10,
y:10,
...
}
当我obj.x = 20;
时,我需要用新的对象坐标重绘画布。
答案 0 :(得分:0)
[根据提问者评论更改了答案]
您可能会从多个来源发生对象属性更改:
要处理此问题,请设置一个包含对象数组和一些状态属性的主对象:
var universe={
objects:[],
requiresRender:false,
};
然后你可以像这样组织你的render()函数:
渲染函数示例:
function render(universe){
// if there's no work to do then return
if(!universe.requiresRender){ return; }
// do physics resolutions
doPhysics(universe.objects);
// if any source changed any objects properties then redraw
if(universe.requiresRender){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<universe.objects.length;i++){
// redraw object[i] now
}
universe.requiresRender=false;
}
}
doPhysics()函数根据您的物理变化对象属性:
function doPhysics(objects){
// do your physics now (collision tests, etc)
// (don't redraw here...just change object properties)
// if you changed any property on any object
// then request re-rendering
universe.requiresRender=true;
}
物理学的一个方面是改变1个物体可能会对其他物体造成连锁效应。
例如,矩形A可能会与矩形B发生碰撞,因此A会反弹B.当A反弹时,它可能会进一步与矩形C发生碰撞。
这意味着您可能必须递归调用doPhysics()来解析所有对象交互。
通常没有足够的时间/资源来解决所有对象交互,因此物理引擎通常会执行固定数量的物理重复,而不是尝试完全解析所有对象交互。
在除了琐碎的物理环境之外,渲染函数还必须限制它解析物理的程度。
所以你的render()函数可能看起来像这样:
var universe={
objects:[],
requiresRender:false,
physicsIterations=3,
};
function render(universe){
// if there's no work to do then return
if(!universe.requiresRender){ return; }
// do the required number of physics resolutions
for(var i=0;i<universe.physicsIterations;i++){
doPhysics(universe.objects);
}
// if any source changed any objects properties then redraw
if(universe.requiresRender){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<universe.objects.length;i++){
// redraw object[i] now
}
universe.requiresRender=false;
}
}
如果用户更改了任何对象属性,请设置requiresRender标志:
universe.requiresRender=true;
如果您的javascript更改了任何对象属性,请设置requiresRender标志:
universe.requiresRender=true;
通过使用requiresRender标志,您可以依赖循环来定期调用render()以保持正确绘制对象。
这样,您不需要对每个属性更改进行render()(每次属性更改都会降低性能)。
您可以使用requestAnimationFrame有效地将渲染与硬件显示的刷新周期同步。因此requestAnimationFrame可以实现高效渲染。
此requestAnimationFrame循环每秒最多执行60次。
function loop(time){
// keep the loop going
requestAnimationFrame(loop);
// use javascript to make any desired object property changes
// do a render
render();
}
同时强>
您可以查看物理引擎如何处理属性更新+物理+重绘。
Box2d就是一个很好的例子:http://box2d-js.sourceforge.net/