How to make a mouse-move glitch collage using HTML canvas and Javascript

By | March 6, 2020


(upbeat music) – [Rik] Today we’re
going to be talking about this effect on the Azab website. So when I move my mouse around the page, we get this drawing effect so
you can see as I move around, the image gets drawn
again and again and again. So it almost looks like it layers up. Now this might remind you
of the winning solitaire style thing from Microsoft in the 90s, so we have this kind of same style effect, we’re drawing lots of
things over each other. Now, our site is gonna
look something like this. So when I move my mouse around the page, it draws multiple times. Now we’re gonna add in
some different style of effects as well, so
if I click on the page, we’ll change the image as well. Now I’m using some photos
by Pawel Czerwinski, using from Unsplash so
you can just grab them, any of your own, you can even
use your own in this project. We’re gonna talk about this
in three different parts. The first part is we’ll
set up a canvas tag, which is how we draw these images and just draw one image
whenever we move the mouse. So this image will be hooked exactly to the mouse to begin with. Our number two, what
we’ll talk about is how we click to change, so when I click, the image changes to a different one that we’re trying to draw. And the third one is we’ll
add this kind of movement in as well so it doesn’t
go instantly to the mouse, we kind of get this effect where it moves towards the mouse over time. So we’ll talk about this in this project. (upbeat music) So I’ve just set up a quick project that looks something like this. At the moment, if I move my mouse on the page, nothing happens. So let’s just talk about what
I’ve done to set this page up. So quickly, all I’ve
done is added a h1 tag with Oil paintings in here and
then a link to our Instagram and if I look at our style sheet, what we have is basically
a web font in here, and we’ve got some basic styling, black background, white text. My h1 is fixed to the top left corner. My a tag with my Instagram
is in the top right corner and at the bottom, I just kinda wanna have this
mix blend mode different, which we’ll talk about a little bit later. I’ve also added in all of my images. Each of my images is sized to 800 by 1200 and that’s because I want to
make them retina friendly. We’re gonna do this at half the size, we’re gonna do it at
400 by 600 when we draw, so at the moment we’ve just doubled it and exported it in that way. So the first thing we’re gonna
do is actually add a canvas tag to my HTML because I want
to basically draw on my page. So in my index.html, I’m
gonna add in a canvas tag. Now at the moment, nothing
goes inside of this, it just exists as a tag and if we look at the page right now, it kinda looks the same. Now what I want to do is style this to be across the entire page itself. How do I do that? I need to add some code that
tells canvas what to do, what do we want to draw on the page, where do we want to draw on the page, how should this even work. So this is what I need to
do with a JavaScript file. Now I’m gonna make a new script tag here and I’m gonna call it
something like drawer. So you can call this whatever you’d like, something that draws
things is a drawer.js file. It just needs to be something
that kinda makes sense to you. At the moment I’ve got an empty file. I need to add this to my index.html. Where do I do this? I’m gonna do this below my canvas tag. So I’m gonna add a
script tag first of all. Script, and I need to
pull in my drawer.js file. So in here, I’m gonna pull
in using the source, src, this is gonna be equal
to something quotes, what do I want this to be equal to? Well I just made a file
called drawer.js, drawer.js. Now currently my drawer.js
is currently blank, there’s nothing in there. So nothing will happen at the moment. So if I go back to my page, move on the page,
obviously nothing happens. But let’s start to think about what we need to add into my JavaScript. Well the first thing I need to do is add some code that sets up my canvas. So the first thing I need to do is grab this canvas tag and set it up. Now I want to set it up for
both retina and non-retina as well, so I need to think
about that as we start. So the first thing we’re going
to do is grab our canvas tag. So I’m gonna save this to a constant, a constant called canvasTag. Now we’ve just made that name up, it doesn’t mean anything, I
can call it whatever I want. It could be called canvas, it could be called potato, it’s up to us. This is going to be equal to something. What do we want to pick out of our page? Well, we need to pick
something out of our page. So on the page in JavaScript
it’s called a document and what do we want to use? What do we want to grab off the shelf within JavaScript, to grab tags? So here what we want to
grab is the query selector, so we’re gonna use .querySelector. Now this is just a tool
built into JavaScript, but we want to use this. So to use this, we use round brackets. What do we want to use? Well, we want to grab a certain tag. Which tag? Well, canvas. Canvas isn’t a special word in JavaScript, so we’re gonna put it in quotes, canvas. So this just basically holds
onto one thing, a canvas tag. So at the moment, nothing happens in here. The next thing we want
to do is set this up, we want to give it a
certain width and height. Now this is going to be across the entire page but we could tell it to be a certain number
instead, it’s up to us. We don’t know the certain
number because we don’t know what our user is looking
at the project on. They could be looking at
it on a mobile device, a tablet or a live screen like this. So we need to set it up for that user. To do that, the first
thing we’re going to do is we’re gonna set up a canvas.width and this is gonna be equal to,
oops sorry, canvasTag.width, and this is gonna be equal
to how wide the screen is, window.innerWidth. We also want to set up a
height for this as well, so canvasTag.width and height, and this one is going to be
equal to the window.innerHeight. Now one thing we need to do is set this up for retina as well, so what I’m gonna do is just multiply both by two,
so times two, times two. But the downside of doing this is it makes our canvas tag really big. You can see these scroll bars start to appear up and down the page. So how do we fix that? So to fix this, what we’re gonna do is say the CSS style of this canvas,
not the canvas drawing area, is gonna be half the size. So our canvasTag is going
to have a style.width, so this one is our CSS and the one above is just our drawing area. This one is going to be exactly
the window width plus in px, because obviously it’s CSS,
it needs some unit with this. And also, similar, what we
need is a height as well, and this one is innerHeight plus px. Now what we’ll get at the
moment is this sets up our page without any scroll bars which
is kind of what we want. There is a tiny little scroll bar that you might notice down here and the reason for that is our canvas
element is an inline tag which means there’s a little
bit of space at the bottom. So to get rid of that, we’re
going to go to our style sheet and in our style sheet,
we’re just gonna say, canvas, a vertical alignment on our inline tag is right at the bottom. So it doesn’t sit on the baseline of text, it sits right at the bottom,
so there’s no underneath space. So now we should see that
if we scroll in either way, our canvas is set up. The next thing we want to do
is set up our canvas’ context. Now what do I mean by that? Canvas can have multiply
ways of doing things. It can do things in 3D,
it can do things in 2D, and there’s a lot of different ways we can actually draw in a canvas. So the next thing we’re gonna do is set up a new constant based on this canvas tag. So what I’m gonna do is a
new constant called context. Now this is a common thing that you’ll see in any kind of canvas documentation. Which context are we drawing things in? Are we doing it in two-dimensions, three-dimensions, four-dimensions? Which doesn’t exist, but we could have that in 2030, let’s say. So what we’re gonna say here is we want to draw our canvasTag, we want to get the context
in brackets, in a 2D way, so we want to draw in a 2D canvas tag. Now with this, we also want
to say a certain scale, like we’re gonna do
things based on retina, which is in double, the pixel density, so our context also has a
scale two across and two down. So basically this is the coordinates that we’re setting up here. We’ve got a double, so
we’re saying to our context, this is already double so we kind of get retina friendly canvases. Now this is just basic
setup that we would do for any canvas tag that
we want to draw inside of. If you want to draw lines or circles or squares or rectangles, this
is how we do the same thing. Now what do we want to
draw in here instead? Well we want to draw in our
whole canvas tag, an image. Which image do we want to draw? Well we want image1 to start with, or image2, or image3 or image4. So let’s get one of these to start with. So my images aren’t tied
up with my index.html or my drawer.js at the moment. So what do we want to do? Well in my JavaScript, I want to make a new
image tag from scratch. So to do that, we’re gonna make
a new constant called image and this is gonna be equal
to, well it’s not just going to be image1.jpg, we
want to make an image tag. So to do that, in our
page, in our document, we want to get something
from the shelf, using a dot, and we want to make something, want to do something using JavaScript. Now a part of JavaScript we
can use is a createElement. What do we want to do with createElement? Well we want to run it, so we want to run it using round brackets. And then what do we want to put in here, what kind of tag is this? Well if we did an image tag
in HTML, we would use img, so we need this in quotes,
img isn’t a special word. Now this is gonna create an
image thing that we’re holding, an image constant, an image variable that we can do stuff with. Now what do we want to do with this image? Well, at the moment it’s
just an empty image tag. We want to tell it what
source it should be. So just like we did with our script tag, our image has an src, a source,
that’s equal to something. We want it to be equal to
the first image for now. So in quotes, we’re gonna say, image1.jpg. So we’ve got our canvas set up, we’ve got our context set up, we’ve got our image set up. Now how do we actually
draw things on the page? What I want to do is when
I move my mouse around the entire document or the entire page, I want to draw on my canvas tag. But in which context? In the 2D context. So that’s the next thing
I’m gonna think about. So, on my document I
want to move my cursor, so I want to listen out
for any mouse movements. So to do that, I’m gonna do on my document and addEventListener, and I wanna do two things in here. I want to run this and say
listen out for in quotes, mousemove, and when you
listen to a mousemove, as soon as it does move, do something. So after this quote we’re
gonna do comma function round brackets, curly brackets. So just watch out for the curly brackets and round brackets here. There should just be one round
brackets, one curly brackets. This one here is just
attached to that one. Now we’re gonna give
ourselves a little bit more room to breath in
here and what we want to do is just draw this on our canvas. Now how do we do that? Well the first thing we need to listen out for is has the image been loaded yet. If this is quite a large image, it may not even be able to be drawn yet. So we’re also gonna add
in here an if statement. If, round brackets, curly brackets. What do we want to do in our if statement? So we want to check for
if this image tag up here has been completed,
has it been loaded yet. So, our image.complete,
has it been loaded yet. Now at the moment, it’s
complaining, but don’t worry, we’re just gonna open
these curly brackets out and the next thing we
want to do is draw it in a certain place on the page. So for now we’re just gonna draw it in maybe about 100 by 100. So for now we’re just gonna
say on our 2D context, ’cause we got the context in 2D, what we want to do is something, we want to do something to this drawing, we want to draw an image. In this image there’s a
few things that go in here. We want to draw in our context, this image that we’ve loaded. Where do we want to
draw this image though? Well for now what we’ll
do is a comma, 100 by 100, and we’re also going to give
it a certain size and width. So the width is 600 and the
height is 400 at the moment. So what we should see now is just one image that’s always in the same place. So soon as I move this,
it pops out, there we go. Now obviously what we
want is this to be drawn in a certain place at certain times. What do we need to listen out for? Well, with this whole function that we have from here to here,
this gives us some more information that passes
along from the browser. So it gives us coordinates,
where is the mouse right now. So what we can do is pass those
extra bits of information in in these round brackets,
so in these round brackets, I’m gonna make a variable called event. Now this could be called
whatever you like, it doesn’t need to be called event, it could be called anything. But what I can get as part
of this event is two things, where the mouse is across the page and where the mouse is
up and down the page. So instead of this being
always at 100 by 100, what I can do instead is
replace 100 with event, or whatever this is called, dot pagex and for this
one, I can do event.pagey. So what we’ll get on the page right now, is if I move around, this suddenly starts to
draw it in the right place. Now this is always in the top left corner because I always draw
from that top left corner. So how do I shift this over? Well all I need to do is
remove some values from this. So here what I’m gonna do in pagex is just remove 200, half the width. In page y, I’m gonna remove 300. So what we’ll get from here
is just this mouse follows us in the middle of the page like this. (upbeat music) So at the moment it’s always
going to be one image. But what happens if you want
to show multiple images, how do we even think about this? Well the idea of what I
want to do is when I click, I want to replace this image. So at the moment, everything is currently
fixed to this single image. So how do we go about changing this? Well at the moment, there is
only one image that’s been loaded on this page and we want multiple images to be loaded. So what we’re gonna do just quickly is we’re gonna get rid of two things. Now there might be some complaints, you might see some JavaScript
complaints coming up, but what we want to
replace it with is what? Well we want to replace
it with a list of images. So how do we do that? We’re gonna make a new
constant called images, which is plural, and this
is going to be equal to a list of something,
or an array of things. Now in my array, what I’m
gonna put in is quote, image1.jpg and then a
comma, with image2.jpg, and I’m gonna fill this
out into all four of these. Now at the moment what
this will do is it will just make some strings, some
list of characters basically and this actually doesn’t
load any images into our page so at the moment, this code will not work. So how do we actually
load these images in? So we want to turn this list of just sources into real images. So to do that, we’re gonna
use another JavaScript tool, especially for lists in
this case, called .map. A map basically takes the input and turns it into something new, so we’re gonna do something
to each image one by one. In our map, what we’re gonna
say is each of these srcs, which is image1, image2, image3,
image4.jpg does something. So we’re gonna take the original
and turn it into something. Now I’m just gonna add some space, just to make this a
little bit easier to read. But what I wanna do in here
is basically make an image. Now this code will only run
between these curly brackets, it won’t be able to get it from outside. So what I’m gonna do is
a constant within here for each one called image
and this is gonna be equal to document.createElement. We want to create a new image tag. And just like before, each
image tag has a source, and this usually equals
something like image1.jpg, but we know what image1.jpg
is because it’s passed in each time using this src which
is what we’ve just made up. So we don’t want to do this
’cause this is hard coded for images which are all image1.jpg. We want to replace this
with the source each time. And the last thing we
want to do is we want to turn the input and send it back out. We want to return back the original image. So this is gonna make an image tag for each one of these four things. Now at the moment, this
is gonna do something. But it will still break
when we try and do the mouse ’cause we don’t know which of these images that we’re talking about at the moment. So we need to keep track of something, we need to keep track of which
image is the current one. So above this, what I’m gonna do is hold the the current image. Now I’m gonna do this using
a variable, not a constant. We want something that’s gonna change. These images don’t change, we can’t do any code that changes this. But we want to do code that changes which one we’re talking about on a click. So we want to do let
something equal something, just like constant equals something. We’re gonna do i, i just
means the index that we’re talking about,
the number in the list that we’re currently talking
about, equal to zero. Now it’s zero because
lists count from zero, not one like humans. But what we’re trying to talk about is the first image in here. Now what I wanna do in here
is not talk about image, because image doesn’t exist
outside of this whole box. Image exists in this box,
but we can’t get to that box. So what we wanna do is images and then find which one
we’re talking about in here. To do that, we’re just
gonna change if images, square brackets because we’re
talking about a list now, which one of this list
are we talking about, the index in this list. Now this is just finding this image, this image, this image, or
this image at the moment, and we want to draw that
image in the same way. So I’m gonna take that code
and replace it with this. Now at the moment what we’ll
see on our page is basically the same thing as what we had from before. We have things that move, but
nothing happening on click. Well that kind of makes
sense because at the moment, nothing happens on click. So what do we want to do on click? Well what I’m gonna do is on any part of the canvas tag, if we click it, then we want to change which
image that we’re talking about. So underneath it, we want to
make a new addEventListener. What do we want to attach it to? We want to attach it to the canvas tag. Now the reason for doing
it on the canvas tag and not the document is
I still want to click the Instagram link to go to Instagram. I just want to do it on this bit instead. So on this canvasTag I’m
gonna add an event listener. What do I want to listen out for? A click. What do I do when I’ve clicked? Well I want to run some code. I want to run a function,
round brackets, curly brackets. What do I want to do? Well what I want to do is I want to just increase that value of i. The new value of i is going to be equal to the old value of i plus one. So zero becomes one, as soon as I click, which talks about a different
one, it talks about image2. If I click again, it talks about image3. If I click again, it talks about image4. So let’s see this in action. There we go, we can see this changing. But as soon as I get to the
fourth one and click again, it breaks and that’s because
there isn’t an image five that we’re talking about. So what we wanna do is add a
little bit more code in here that says if we run out of
numbers, go back to the start. So how do we do that? Well I know that there’s
four things in this list, so if this i gets bigger than the amount of things in the list, go to the start. So if brackets, curly brackets. So on the round brackets,
what we’re gonna say is if i is bigger or equal to images.length, so if we wanted to add a fifth image, this code would still work. And if it is, then what? I goes back to zero. So it’s gonna do some
calculation in here each time. So let’s just see if this works. One, two, three, and there
we go, back to the start. So we’re basically making
something that loops around now. And as you can see, it
doesn’t really matter how many images that we put in here, the only thing that we need to change in our code now is this list. So if we add a fifth,
this is the only place that we need to go because
we’ve set up our code to only listen out for
certain numbers like how long is this list that we’re talking about. (upbeat music) So at the moment you might notice that as soon as I move my mouse, it draws instantly and I can
almost shake this off as well, it just sticks to the mouse at all points. Now I’ve kind of covered
this in a previous video called Smooth moments with JavaScript and the idea behind that is
we have this kind of effect that moves as we kind of move the mouse. So we’re gonna be using similar
code to that in this project and the idea of what we want to do is not move this exactly to the mouse, now what we want to do is kind of trend this towards the mouse, almost like tween it
towards the mouse instead. So this needs a little
bit of re-engineering. Now it’s not too much, it’s not too bad. But basically the issue that we have is we only do things on mouse move. So if I move my cursor
really, really quickly, then I’m only doing this next drawing. But we want to have the states
in between there as well. So how do we have those
states in between that? So I’m gonna add in some more code. I’m gonna do this above the let i is zero and we’re gonna add four things in here. What we wanna do is hold an aim for the x. Now when we load the page, we might not even have
our cursor on the page. So we’re just gonna say null,
which is empty, nothing. It’s kinda like zero without
it being anything at all. And then we’re gonna have an aim for y. Where is this meant to go to? But what we have is where
our cursor currently was, so we kinda want to hold where the cursor was to trend it towards the aim. So here we’re gonna do a current x of null and a current y of null. Now I’ve kept them all as
lets rather than constant because they’re going to
change if I move my mouse, this wants to change. Now what I’m gonna do to start with is I’m gonna get rid of
this thing that draws. So I’m just gonna get rid of this. Now the idea of y is because I want my aim to be where this mouse movement is. So in here, what I’m
gonna do is say my aim x is exactly where the event pagex is. So if I move my mouse really quickly, I want to trend towards
my new mouse movement. And the same thing for y. I want this in two directions. Now I’m also going to say if the current x position is empty, just make the current x the same thing. So if current x is equal to null, then that should be the same as well. We want to have a starting point as well. But if it’s not then we want to tween it, or transition it between the two. So for now this is just
in an if statement. Now how do we draw on the page itself? Well at the moment we
draw, or we did draw, on any mouse movement. But we kind of want to draw
between mouse movements as well, so we’ve got a problem. How do we draw things between anything happening on the page, any event happening on
the page completely? So we need to think about
this in a different way. What we’re gonna do is we’re
gonna use this commented out code a little bit later but for now what we’re gonna say is I basically want to make some kind of drawing loop. So I’m gonna make a constant called draw. Now constants and lets
don’t have to be equal to numbers or lists or strings, they can also be equal to
things that do stuff, functions. Function, round bracket, curly bracket. And what I’m gonna do in here is basically draw the image where is it currently. So I need to have some
current value first of all, so if current x is a thing, so we’ll just leave it as if current x and add curly brackets after that. So if there is a current
x that isn’t null, then what do we want to do? Well we want to draw stuff. How do we draw stuff? We use the code from up here. So I’m just gonna grab this
commented out bit of code, I’m gonna take it and put it between here and I’m gonna un-comment it. There we go. Now again, you can just
remove those little comments in the SuperHi Editor it’s
command and forward slash, and what I’ve got here is not event pagex, but instead I want it to
be the current x position and the current y position. The thing is, this draw
function never runs. We’ve set it up, but we never ever run it. Where do we want to run this? Well we want to run this on page load, but we also want to keep running this, we want to run this in a loop that happens over and over and over again. So the first thing we’re gonna do is we’re gonna run it on page load. Now to run things on page load, we just don’t go inside any boxes, so no boxes like
addEventListener for instance, we’re just gonna keep
it outside everything. We’re just gonna write draw. So this will run this
draw function just once. But we want to run this
on every single frame. So in my draw function, I’m gonna create a loop
that runs and runs and runs on every single frame. To do that we’re gonna use a
JavaScript call tool called requestAnimationFrame and
here what we’re gonna do in animation frame is draw. So this will draw it first time ’round, and then it will do this bit of work, and then go, wait for the next frame, and then do this again. And then on the next frame, do it again and on the frame
after that, do it again. So what we’ll see right now
on the page is if I move, it just happens the once. And the reason for that is we never updated the aim position, it’s just always the current position. Now how do we change the current position? Well basically I want to
trend it towards the aim. So what I want to do in my if statement, and notice I’m still with if current x ’cause I still want to update things, well what do I want to do in here? Well this depends on
the current x position. So my current x, and what I want to do is change this to be something. I want to change this to be equal to the old version of current x and some distance between
where the current x position is and the new aim position is. So in brackets, I’m gonna
put in aim x minus current x. So aim x plus current
x is just the distance, so this plus, minus this,
plus aim x, is equal to aim x. But we don’t want to
just go straight there. We want to have some
distance between them, so what I’m gonna do is times this last bit by some small number. The small number I’m gonna use is 0.1. So we’ll have this is just the
one direction at the moment. So if I just see it right now, what we’ll get, is this
will draw in one way. Now notice how this does
it based on the speed now, the speed is 0.1. I could change that to
be slower if I wanted. So for instance, 0.01 will
make this even slower, and there we go, it’s kinda
trending towards the mouse very, very slowly now. Now of course we want to do
it in the y direction too. So in the y direction,
we’re gonna do current y is the old version plus
the difference between the aim y minus the current y, so how far is that gap, but we don’t want all of
the gap straight away, we kind of want to have
some kind of padding, or tweening, between the two. So we’re gonna just add
this last little bit in here and what we’ll get on the page is this is the kind of slow version, and there we go, it
starts to tween between, and if I click again, it
will change these images. So if I want to change the speed of this, all I need to do is
change these two numbers. Maybe I just want to make it
10 times quicker, so now… It should go a lot quicker. So this is how we can make something that looks really, really good. It’s only a short amount of JavaScript. There is some complex JavaScripts in here, but we’ve basically got 55
lines of JavaScript in total. We’re setting up the canvas tag, setting up the context we want to draw in, setting up our images, when we move our mouse, we
want to go to a certain place. If I click, we want to change the image. And I’m gonna keep drawing a loop whenever we want to draw the next frame and then we’re gonna do some
calculations to work out where the next current position should be. And there we have it, it’s
a few bits of JavaScript. It’s not too complex, it’s you know, a little bit of thinking, but once we kind of build
these techniques up together, we can build very powerful
sites very, very quickly. If you’re interested in learning more about these kinds of techniques, join our JavaScript for Designers course where we talk about
six different projects, all very similar using
lots of fun techniques just like the ones that
we’ve been teaching. (upbeat music)

Leave a Reply

Your email address will not be published. Required fields are marked *