HTML5画布中的平滑动画 [英] Smooth Animation in HTML5 Canvas

查看:150
本文介绍了HTML5画布中的平滑动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我在HTML和Javascript的画布上创建了一个游戏。我想做一些飞鸟的鸟游戏,但当我按下一个键,播放器的动画看起来真的口吃。看看:

So I was creating a game on the canvas in HTML and Javascript. I wanted to make some kind of flappy bird-ish game but when I press a key, the animation of the player looks really stuttering. Take a look:

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完成,但我不知道如何使用它。

I want it to have a smooth animation up. I have seen some people saying it should be done with requestanimationframe but I don't know how to use it.

提前感谢。

推荐答案

requestAnimationFrame

requestAnimationFrame

有关详细信息,请参阅 MDN window.requestAnimationFrame

For full details see MDN window.requestAnimationFrame

由于前面的答案缺少一些信息,这里是基本用法的注释例子。

As the previous answer is lacking some information, here is annotated example of the basic usage.

// 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。如果渲染速度很慢,它将继续跳过帧。

The update function will be called up to 60 times a second. If the code can not keep up (ie it take more than 1/60th of a second to render) then the update function will wait for the next frame effectively reducing the frame rate to 1/30. It will continue skipping frames if the render is slow.

由于您无法控制帧速率,因此您可以执行以下操作将动画速度降低到所需的帧速率。

Because you can not control the frame rate you can do the following to slow the animation down to a required frame rate.

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);
}

如果将焦点更改为另一个选项卡,浏览器将不再调用

If you change the focus to a another tab the browser will no longer call the request until focus is returned to the tab.

与其他计时器事件一样,调用requestAnimationFrame会返回一个可用于取消回调事件的ID

Like other timer events the call requestAnimationFrame returns a ID that can be used to cancel the callback event

var id = requestAnimationFrame(update);
// to cancel 
cancelAnimationFrame(id);

你实际上可以每帧多次调用requestAnimationFrame。只要所有请求都能在1/60秒内呈现,它们都将同步并同时呈现给显示器。

You can actually call requestAnimationFrame more than once per frame. As long as all the requests can render within the 1/60th of a second they all will by synced and presented to the display at the same time. But you must be careful because they can come out of sync if the rendering time is too long.

RequestAnimationFrame可防止闪烁(在呈现未完成时显示画布),但是您必须小心,因为如果呈现时间太长,双缓冲变化。与显示硬件同步,并防止剪切(当显示在一帧中途更新时,并且显示屏的上半部分显示旧帧,下半部分显示新帧)。有更多的好处,取决于浏览器。

RequestAnimationFrame prevents flickering (displaying the canvas when the rendering is not complete) by double buffering changes. Syncs to the display hardware and prevents shearing (caused when the display is updated midway through a frame and the top half of the display shows the old frame and bottom the new frame). There are more benefits depending on the browser.

这篇关于HTML5画布中的平滑动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆