一个导致矩形从画布的顶部移动到底部的函数,唯一可以改变的是矩形的x位置...所以说createRect(x)。每次调用时,指定x位置的新矩形都会从上到下移动。
想要一个存储一系列不同x值的数组,然后以正确的顺序调用该函数。时间更复杂。我希望能够指定说第一个是5秒,之后是10秒,依此类推。这是我挣扎的一点,因为据我所知,我可以通过一个循环遍历数组并为每个值创建矩形,但不确定时间。
示例数组数据:
结果可能是多个矩形同时移动或一起出现在画布上。提前谢谢你的帮助, 丹
答案 0 :(得分:0)
制作动画时,您需要与显示器刷新率保持同步,以便您的动画非常流畅。
不要返回
从渲染函数返回到空闲状态实际上是更新DOM的请求。
您不能只在自己的时间内设置时间事件并在每个项目上呈现。每次将函数退出到空闲上下文(没有代码运行)时,浏览器都会假定您完成了渲染并将显示所有更改。这将减慢一切,减少剪切,闪烁,丢失渲染和janky play等动画制品。使用计时器为各个项目制作动画是一种非常糟糕的动画制作方式。
统治所有人的一项功能
要制作任何动画,您必须通过一次通话完成。当你退出时,你应该完全重新渲染你的场景,它应该准备好呈现给显示器。
这可以使用requestAnimationFrame(callBack)
(rAF)这个函数来完成,正如名称所暗示的那样,是专为动画而设计的。
你这样使用它
function mainLoop(time){ // when this function is call the time is provided
// by the browser.
// from this point to the end of the function nothing will reach the
// display
// render everything you need to
// request the next frame
requestAnimationFrame(mainLoop);
// only after you exit will what you have rendered be presented to the
// display. The browser will make sure it is present in sync with the
// display hardware refresh rate and the rest of the DOM
}
// start the animation
requestAnimationFrame(mainLoop);
rAF函数就像一个setTimeout但没有你设置时间。当它调用您的函数时,它还会在页面加载后的ms
1/1000中添加时间。您可以使用此计时器来控制动画。 (我发现从其他来源获取时间,日期或表现不如时间参数准确。)
<强>代码强>
以下是使用rAF和每帧一次调用解决问题的方法。
<强>箱强>
保留方框的一些代码。什么时候开始。框开始{x :?,y:?}
以及框需要移动多长时间。
var boxes = [];
function addBox(when,where,howLong){
var b;
boxes.push(b = {
when : when,
where : where,
len : howLong,
});
return b;
}
主循环
主要更新功能。管理时间和调用渲染功能&quot; updateAll()&#39;
var globalTime; //as time is important make a global for it
var startTime; // we need to have a referance point
function mainLoop(time){
if(startTime === undefined){
startTime = time;
}
globalTime = time-startTime; // set time
updateAll(); // call the main logic
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
<强>设置强>
代码随机添加框,因为我很懒。
const boxSize = 20; // pixel size
const playFor = 30; // how long all this will take
const numBoxes = 20;
function setup(){
var i
for(i = 0; i < numBoxes; i ++){
addBox(
Math.random() * (playFor-1) * 1000 + 1000, // get time to start box
{
x :Math.floor(Math.random() * (canvas.width - boxSize)) + boxSize / 2,
y : canvas.height + boxSize / 2 // start below bottom
},
Math.random() * 5 * 1000 + 1000 // play for over 1 sec less than 6
);
}
}
setup(); // make some random boxes
全部更新...
现在更新功能。这会渲染,并在需要时移动框。当一个盒子完成它的东西将它从数组中删除,所以我们不必处理它。
function updateAll(){
ctx.clearRect(0,0,canvas.width,canvas.height); // clear the screen
// iterate box array and check for new starts
for(var i = 0; i < boxes.length; i ++){
var b = boxes[i];
if(!b.moving){ // is box not moving ???
// check th time
if(b.when < globalTime){ // it needs to start
b.moving = true; // flag it to move
}
}
if(b.moving){ // move boxes that need it
var pos = globalTime - b.when; // get pos in time
if(pos < b.len){ // not at end yet
pos /= b.len; // normalize time pos
pos = (b.where.y - (-boxSize /2)) * pos; // distance to past the top
// now draw the box;
ctx.fillRect(b.where.x - boxSize /2, b.where.y - boxSize - pos, boxSize, boxSize);
}else{ // box has reached the end dont need it no more
// any last words Box!!
boxes.splice(i,1); // Bang
i -= 1; // clean up the loop counter
}
}
}
}
这就是你所需要的。这些盒子都会在正确的时间移动,即使丢帧也会保持完美的时间,更新频率并不重要。
演示
该演示展示了它的实际效果。当盒子耗尽时,演示会继续运行,它会增加更多时间并重置时间(没有任何演示无效)
const boxSize = 30; // pixel size
const playFor = 60; // how long all this will take
const numBoxes = 120;
var canvas = document.createElement("canvas");
canvas.style.position = "absolute"; // pos absolute to avoid scroll bars
canvas.style.top = canvas.style.left = "0px";
canvas.width = innerWidth;
canvas.height = innerHeight;
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
var boxes = [];
function addBox(when,where,howLong){
var b;
boxes.push(b = {
when : when,
where : where,
len : howLong,
});
return b;
}
var globalTime; //as time is important make a global for it
var startTime; // we need to have a referance point
function mainLoop(time){
if(startTime === undefined){
startTime = time;
}
globalTime = time-startTime; // set time
updateAll(); // call the main logic
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
function setup(){
var i
for(i = 0; i < numBoxes; i ++){
addBox(
Math.random() * (playFor-1) * 1000 + 1000, // get time to start box
{
x :Math.floor(Math.random() * (canvas.width - boxSize)) + boxSize / 2,
y : canvas.height + boxSize / 2 // start below bottom
},
Math.random() * 5 * 1000 + 1000 // play for over 1 sec less than 6
);
}
}
setup(); // make some random boxes
function updateAll(){
ctx.clearRect(0,0,canvas.width,canvas.height); // clear the screen
// iterate box array and check for new starts
for(var i = 0; i < boxes.length; i ++){
var b = boxes[i];
if(!b.moving){ // is box not moving ???
// check th time
if(b.when < globalTime){ // it needs to start
b.moving = true; // flag it to move
}
}
if(b.moving){ // move boxes that need it
var pos = globalTime - b.when; // get pos in time
if(pos < b.len){ // not at end yet
pos /= b.len; // normalize time pos
pos = (b.where.y - (-boxSize /2)) * pos; // distance to past the top
// now draw the box;
ctx.fillRect(b.where.x - boxSize /2, b.where.y - boxSize - pos, boxSize, boxSize);
}else{ // box has reached the end dont need it no more
// any last words Box!!
boxes.splice(i,1); // Bang
i -= 1; // clean up the loop counter
}
}
}
if(boxes.length === 0){ //no more boxes so add more
setup();
startTime = undefined; // reset start time for new boxes.
}
}
&#13;