DEV Community

reyes2981
reyes2981

Posted on

what i learned last week: creating an animated 2d background with canvas and javascript

Hello and welcome to this weeks blog entry where I'll continue working on Angry Borgs, a 2D game I'm building using vanilla JavaScript for the frontend and Ruby on Rails on the backend. To review, I've successfully modeled physics to create a dynamic player object that can be controlled with the spacebar.

In this entry, I want to add more depth to Angry Borgs so I'm going to build an animated background. The final product for this blog will be a variation of this...

First, I'll retrieve the canvas reference and store it inside a similarly named variable. Next, I need to initialize the context of the canvas element and store that in a variable named ctx.

const canvas = document.querySelector('canvas');// reference to the CANVAS element
const ctx = canvas.getContext('2d');
Enter fullscreen mode Exit fullscreen mode

Next, I create a new instantiation of the Image() constructor and store it inside of a variable.

const backgroundImage = new Image();
Enter fullscreen mode Exit fullscreen mode

Note, the above code has the same functionality as the code below. There is no "correct way" to use either form rather up to the situation and your best judgement.

document.create('img');
Enter fullscreen mode Exit fullscreen mode

Second, I want to reference the image I'm going to use as the animated background. I can do this by calling src on backgroundImage and then storing the file path as a string.

backgroundImage.src = 'assets/bg5(1).jpg'; 
Enter fullscreen mode Exit fullscreen mode

So far the code should look something like this...

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg'; 
Enter fullscreen mode Exit fullscreen mode

Now that we have our variables all set up, what is the next step? We need to not only build out the logic of the program but also organize it. In this case, I'm going to create a draw() Function.

function draw() {
}
Enter fullscreen mode Exit fullscreen mode

Next, we are going to reference the canvas using clearRect() which is a method of the Canvas 2D API [that] erases the pixels in a rectangular area by setting them to transparent black. For this example I want to clear out the entire browser screen so I passed in the following arguments:.

x-coordinate = 0,
y-coordinate = 0,
width = canvas.width
height = canvas.height

clearRect(0, 0, canvas.width, canvas.height)
Enter fullscreen mode Exit fullscreen mode


Let's review all of the code I have so far and debug, debug, debug!

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg'; 

function draw() {
clearRect(0, 0, canvas.width, canvas.height)
}
Enter fullscreen mode Exit fullscreen mode

If we run the above code what do you think will happen on the browser side?
parllx1
NADA!
Let's call draw() and see what happens

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg'; 

function draw() {
clearRect(0, 0, canvas.width, canvas.height)
}
draw()
Enter fullscreen mode Exit fullscreen mode

parllx2
Sweet, we got an error!
parallx3
The error says clearRect is not defined but if you look at the code it's clearly there. Why is there an error? The answer - clearRect is a method of the Canvas 2D API. When I run the below code the program has no idea what that function is. How is this fixed?

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg'; 

function draw() {
clearRect(0, 0, canvas.width, canvas.height)
}
draw()
Enter fullscreen mode Exit fullscreen mode

You simply need to call clearRect() on your ctx variable. Remember, ctx initializes the context of the canvas element.

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
Enter fullscreen mode Exit fullscreen mode

Success!
parllx4

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg'; 

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
draw()
Enter fullscreen mode Exit fullscreen mode

Next, within draw() I'm going to be using the requestAnimationFrame()method which tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.

function draw() {
console.log('hello from the draw function')
ctx.clearRect(0, 0, canvas.width, canvas.height)
requestAnimationFrame(draw);
}
Enter fullscreen mode Exit fullscreen mode

Sweet, quick review of the code so far!

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg'; 

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
requestAnimationFrame(draw);
}
draw()
Enter fullscreen mode Exit fullscreen mode

Next, I'm going to use drawImage() which is a method of the Canvas 2D API [that] provides different ways to draw an image onto the canvas. I want to fill out the entire browser screen so I passed in the following arguments:.

image = backgroundImage,
x-coordinate = 0,
y-coordinate = 0,
width = canvas.width,
height = canvas.height

ctx.drawImage(backgroundImage, backgroundImage, 0, 0, canvas.width, canvas.height);
Enter fullscreen mode Exit fullscreen mode

Awesome, let's head over to the browser and check if we see the image.

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);

requestAnimationFrame(draw);
}
Enter fullscreen mode Exit fullscreen mode

parllx6

Finally, I don't need a static image I need a dynamic one and I can do that with the following code...

backgroundImage.x -= 0.1;
Enter fullscreen mode Exit fullscreen mode

The above code tells the program to move the backgroundImages x-axis an x-amount of distance. Let's see the final code for better, no pun intended, context.

const canvas = document.querySelector('canvas');// reference to the CANVAS element
const ctx = canvas.getContext('2d');
const backgroundImage = new Image();
backgroundImage.src = 'assets/bg5(1).jpg';

function draw() {
console.log('hello from the draw function')
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
backgroundImage.x -= 0.1;
requestAnimationFrame(draw);
}
draw();
Enter fullscreen mode Exit fullscreen mode

As you can see above, when the draw() function is called it initializes a canvas element, then draws out an image, next the image's x-axis is moved an x amount of distance and finally it "hits" the requestAnimationFrame() method where a loop is created.

FIN!

Thank you for reading.

Say Hi on LinkedIn! I'm always open to connecting, networking and new opportunities.

and/or

Checkout my Github.

RESOURCES
https://dev.to/ibrahima92/make-a-parallax-effect-with-10-lines-of-javascript-3hia
https://luka712.github.io/2018/12/02/Parallax-scrolling/
https://www.youtube.com/watch?v=Mg7ibYWhjPI

Top comments (0)