Ad

Safari Drawing Images Not Working Properly

- 1 answer

I am trying to make a game, where I draw images to a canvas. Here is a small code snippet:

class Sprite {
    constructor(x, y, width, height, src, xDirection, yDirection) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.src = src;
        this.xDirection = xDirection;
        this.yDirection = yDirection;
    }

    update() {
        var image = new Image();
        image.src = this.src;
        context.imageSmoothingEnabled = false;
        context.drawImage(image, this.x, this.y, this.width, this.height);

        this.x += this.xDirection;
        this.y += this.yDirection;
    }
}

const player = new Sprite(0, 0, 100, 100, "Images/Game/sprite-right.png", 0, 0);
const mainInterval = setInterval(() => {
    player.draw();
}, 1);

This is only a small code snippet and I am also drawing many more images to the screen in the main interval. In Google Chrome and in Firefox, this works perfectly, as all of the images are correctly drawn to the screen. However, in Safari, the image is not drawn. I tried changing the 'update' method to this...

update() {
    var image = new Image();
    image.src = this.src;
    image.onload = () => {
        context.imageSmoothingEnabled = false;
        context.drawImage(image, this.x, this.y, this.width, this.height);

        this.x += this.xDirection;
        this.y += this.yDirection;
    };
}

...this works, but since I am drawing lots of things to the screen in the main interval, all of the images appear to sort of 'flash' and flicker. I need help with coming up with a way of drawing lots of images to the screen, without them flickering (bearing in mind that the method at the top only doesn't work in Safari, as far as I know). Thanks very much.

  • PrimeCubed
Ad

Answer

Not exactly sure why it isn't working on Safari but here are a few things that can be improved:

  1. It's better to load all the images before you actually start drawing them.
  2. You should use requestAnimationFrame for drawing frames.
  3. Call the draw function only when all the resources have loaded. window.onload = draw;

Here is a snippet with these changes and this works on Safari too.

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');

var image = new Image();
image.src = "https://placekitten.com/100/100";

class Sprite {
    constructor(x, y, width, height, image, xDirection, yDirection) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.image = image;
        this.xDirection = xDirection;
        this.yDirection = yDirection;
    }

    update() {
        context.imageSmoothingEnabled = false;
        context.drawImage(this.image, this.x, this.y, this.width, this.height);
        this.x += this.xDirection;
        this.y += this.yDirection;
    }
}

const player = new Sprite(0, 0, 100, 100, image, 0, 0);

function draw() {
    player.update();
    requestAnimationFrame(draw);
}

window.onload = draw;
<canvas />

Ad
source: stackoverflow.com
Ad