平滑动画在HTML5画布
Smooth Animation in HTML5 Canvas
所以我在画布上用HTML和Javascript创造了一款游戏。我想做一款类似于小鸟的游戏,但是当我按下一个键时,玩家的动画看起来很不流畅。看一下:
body {
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="Style.css"/>
</head>
<body onload="startgame()">
<canvas id="canvas"></canvas>
<script>
canvas.height=window.innerHeight;
canvas.width=window.innerWidth;
function startgame() {
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var x = 900;
var y = 300;
var w = 25;
var h = 500;
var yperson = 20;
var xperson = 200;
document.addEventListener("keydown", function() {
yperson -= 150;
});
function updateperson() {
yperson = yperson;
}
setInterval(createobject, 10);
function createobject() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
x -= 1;
yperson += 0.5;
yperson *= 1.003;
ctx.fillStyle = "#009999";
ctx.fillRect(x,y,w,h);
ctx.fillStyle = "black";
ctx.fillRect(xperson,yperson,30,30);
if (x <= 50) {
if (yperson < 280 && xperson === x-30) {
x -= 1;
} else if (yperson > 280){
x += 1;
}
}
}
}
</script>
</body>
</html>
我想让它有一个平滑的动画。我看到一些人说它应该用requestanimationframe,但我不知道如何使用它。
requestAnimationFrame
详细信息请参见MDN window.requestAnimationFrame
由于前面的答案缺少一些信息,这里有一个基本用法的注释示例。
// A flag to indicate that the animation is over
var stop = false; // when true the animation will stop
// define main loop update
// the callback that is the main loop
// the browser treats this function as special in terms of display items including
// the canvas, and all DOM items.
// It will ensure that any changes you make to the page are synced to the display
function update(time){ // time is the time since load in millisecond 1/1000th
// time is high precision and gives the time down to
// microseconds (1/1,000,000) as fraction 0.001 is one microsecond
// you can stop the animation by simply not calling the request
// so if the flag stop is true stop the animation
if(!stop){
requestAnimationFrame(update); // request the next frame
}
}
requestAnimationFrame(update); // request the very first frame
// or you can start it with a direct call. But you will have to add the time
update(0);
更新函数每秒将被调用60次。如果代码不能跟上(即渲染时间超过1/60秒),那么更新功能将等待下一帧,有效地将帧率降低到1/30。如果渲染缓慢,它将继续跳过帧。
因为你不能控制帧率,你可以做下面的动作来减慢动画到所需的帧率。
const FRAMES_PER_SECOND = 30; // Valid values are 60,30,20,15,10
// set the mim time to render the next frame
const FRAME_MIN_TIME = (1000/60) * (60 / FRAMES_PER_SECOND) - (1000/60) * 0.5;
var lastFrameTime = 0; // the last frame time
function update(time){
if(time-lastFrameTime < FRAME_MIN_TIME){ //skip the frame if the call is to early
requestAnimationFrame(update);
return; // return as there is nothing to do
}
lastFrameTime = time; // remember the time of the rendered frame
// render the frame
requestAnimationFrame(update);
}
如果您将焦点更改为另一个选项卡,浏览器将不再调用请求,直到焦点返回到该选项卡。
像其他计时器事件一样,调用requestAnimationFrame返回一个ID,可以用来取消回调事件
var id = requestAnimationFrame(update);
// to cancel
cancelAnimationFrame(id);
你可以每帧调用requestAnimationFrame不止一次。只要所有请求都能在1/60秒内呈现,它们都将同步并同时呈现到显示器上。但是你必须小心,因为如果渲染时间太长,它们可能会不同步。
RequestAnimationFrame通过双重缓冲更改防止闪烁(在渲染未完成时显示画布)。与显示硬件同步并防止剪切(当显示在帧中间更新时,显示的上半部分显示旧框架,底部显示新框架)。有更多的好处取决于浏览器。
我是这样设置我的游戏的:
// DEFINE OBJECTS UP HERE
var update = function(modifier) {
// update all the object properties
// multiply values that depend on time (like speeds) by modifier
};
var render = function() {
// draw everything
};
var main = function() {
var now = Date.now();
var change = now - then;
update(change/1000); // update based on frame rate, change in milliseconds/second
render();
then = now;
requestAnimationFrame(main);
};
// ADD EVENT LISTENERS HERE
requestAnimationFrame = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.msRequestAnimationFrame
|| window.mozRequestAnimationFrame;
// ABOVE CODE GIVES CROSS-BROWSER COMPATIBILITY
var then = Date.now();
main();
requestAnimationFrame告诉浏览器基于帧率执行循环。就我个人而言,我不明白它是如何工作的,尽管如果这里有人知道的话,我会很有兴趣知道更多。setInterval允许您设置循环运行的速度,但最佳速率将取决于浏览器。"then"answers"now"变量用于确定自上次执行循环以来经过了多长时间。这个值可以传递给更新函数,并用于依赖于帧速率的计算,尽管有时你不需要它,可以直接使用:
var update = function() {
//STUFF
};
// if using that variation just ignore then and now and call:
update();
//in your main
- Canvas Html5绘图应用程序,移动画布会导致重大问题
- HTML5在画布中加载较小的图像并保存实际大小的图像
- JavaScript HTML5画布未显示
- html5画布动画无法正常工作
- 在HTML5画布上添加按钮和控件
- 如何在运行时在HTML5画布中绘制正方形
- 多层画布HTML5
- 如何在画布 html5 中呈现套接字数据
- 存储来自画布 html5 的大尺寸图像
- 如何在画布 HTML5 中使用触摸事件
- 画布 html5 中的透明度上下文.填充样式
- 在画布HTML5中查找上传的宽度和高度图像.(带文件读取器)
- 将文本字段添加到画布 HTML5
- 从画布 html5 中上传的图像中删除拖动属性(将区域设置为上传的图像)
- 在鼠标画布HTML5上
- 图像画布HTML5
- 在没有闪烁的情况下重新绘制画布html5
- 模板的画布html5/jquery/javascript
- 拖放到画布 HTML5 上
- 如何绘制一个动画线出现在画布html5