简体   繁体   中英

PNG image choppy when I try to move it in HTML5 Canvas

So I am working on a game using HTML5 Canvas and pure Javascript when I came across an annoying problem. When I try to move my picture move with setInterval it works but the picture twitches like it's choppy. My guess is that it has to do with the fact that the image needs to be loaded every 10 milliseconds. Please help me fix this problem.

Sample code below:

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta charset = "UTF-8" />
    </head>
    <body>
        <canvas id = "myCanvas" width = "1000" height = "500" style="border:1px solid #000000;">
        </canvas>
        <script type = "text/javascript">
            var canvas = document.getElementById("myCanvas");
            var ctx = canvas.getContext("2d");
            var x = 0;
            var image = new Image();
            image.src = 'spaceship.png';

            function draw(){
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                image.src = 'spaceship.png';
                image.onload = function(){
                    ctx.drawImage(image, x, 0);
                }
                x += 2;
            }
            setInterval(draw,10);
        </script>
    </body>
</html> 

First of all, an interval of 10ms is way too short. Even with 60fps you would have an interval of ~16.67ms.

Also, when available, you shouldn't use setInterval but rather requestAnimationFrame when doing animations. That should lead to much smoother animations on browsers supporting it.

And the last thing that should be optimized is the fact that you are moving the image by 2px every frame. You can't be sure that each frame is called after the same time interval. Like this you would have faster animations on fast computers and a slow animation on slow computers. You should work with the current time and the time delta that passed since your last animated frame (for example with Date.now() )

The last thing to note is that the image's onload callback should only be called once. And that's before any animation or drawing is performed. So only after the image is loaded, the animation should start.

Example of a moving ball:

 var canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d"), lastTimestamp, imageX = 0; canvas.width = 300; canvas.height = 300; var image = new Image(); image.onload = function () { requestAnimationFrame(draw); }; image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAAAolBMVEUAAAARqu4YrO4bre4aq+wbrOocrOocq+sbreobquocrOkcrOobq+oaqugdresir+sosewus+w0te01tu06t+0+ue4/ue5GvO5Ov+9cxPBfxfFoyPFwy/J0zPJ4zvN6z/OA0fSE0vSG0/SJ1PSQ1vWR1/WT1/WV2PWY2faZ2vad2/ai3fej3fel3ven3/ev4vix4/i45vm65vm85/m+6PnA6fpEpw5TAAAADnRSTlMADx8vX29/j5+vv8/f79ErPTAAAADdSURBVBgZBcELThsxFADAef5sQkAVEr3/JcsSNrafOxNAKT2wRyYIiFsPwB7XRqC+FY9Smpnjks9FEO/l7c8BOP+NPLfKe/34qgDHx5VtqI7j9hcQrdV9/917lbj5BGhHa618ukVp8TgAGpr7I1rpDgAbyaGXagMYyxpstYUyOmAtuIpouFavAOYr0XZkmbO2FthzJGm31ebBWhcA0yrDAgBYRlmuBADmr1XytU8AkKdXVqvvbAFgnplPldVz9gDM79zPVNmjuUTBvH6sMwmIewdwvTYCqL0H9msk+A8oZ3I4nbdKXwAAAABJRU5ErkJggg=="; function draw() { var now = Date.now(), timeDelta = (now - (lastTimestamp || now)) / 1000; // in seconds imageX += timeDelta * 30; // meaning: 30px per second ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(image, imageX, 0); lastTimestamp = now; requestAnimationFrame(draw); } 
 <canvas id="canvas" /> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM