Mouse Move Glitch Collage Using HTML Canvas
As seen on the Azab site (or when you win at Solitaire), it's fairly straight forward to create a glitch-style collage that draws the image again and again whenever your user moves their mouse. In this video, we build up how to make a site that has a HTML canvas slideshow that reveals each image on click and has a tweening movement.
(upbeat music)- [Rik] Today we're going to be talking aboutthis 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 solitairestyle 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 styleof 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 imagesand just draw one image whenever we move the mouse.So this image will be hooked exactlyto the mouse to begin with.Our number two, what we'll talk about is howwe click to change, so when I click,the image changes to a different onethat we're trying to draw.And the third one is we'll add this kind of movementin as well so it doesn't go instantly to the mouse,we kind of get this effect where it movestowards the mouse over time.So we'll talk about this in this project.(upbeat music)
So I've just set up a quick projectthat looks something like this.At the moment, if I move my mouseon 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 tagwith Oil paintings in here and then a link to our Instagramand 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 rightcorner 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 1200and 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 itand exported it in that way.So the first thing we're gonna do is actually add a canvastag 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.
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.
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 acrossthe entire page but we could tell itto be a certain number instead, it's up to us.We don't know the certain number because we don't knowwhat 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 dois we're gonna set up a canvas.widthand 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 setthis up for retina as well,so what I'm gonna do is justmultiply both by two, so times two, times two.
But the downside of doing thisis it makes our canvas tag really big.You can see these scroll bars startto appear up and down the page.So how do we fix that?So to fix this, what we're gonna do is saythe 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 aboveis 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 pagewithout any scroll bars which is kind of what we want.There is a tiny little scroll bar thatyou might notice down here and the reasonfor that is our canvas element is an inline tagwhich 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 sheetand in our style sheet, we're just gonna say, canvas,a vertical alignment on our inline tagis 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 wayswe can actually draw in a canvas.So the next thing we're gonna do is set upa 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 seein 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 hereis 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.
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 variablethat 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 aroundthe 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 documentand 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 functionround brackets, curly brackets.So just watch out for the curly bracketsand 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 bitmore room to breath in here and what we want to dois just draw this on our canvas.Now how do we do that?Well the first thing we need to listen outfor 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 herehas 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 outand the next thing we want to do is draw itin a certain place on the page.So for now we're just gonna draw it inmaybe 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 justone 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 drawnin a certain place at certain times.What do we need to listen out for?Well, with this whole function thatwe have from here to here, this gives us some moreinformation 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 inin 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 pageand 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 cornerbecause 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 pagexis 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 usin the middle of the page like this.(upbeat music)
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 herefor each one called image and this is gonna be equalto 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 ineach time using this src which is what we've just made up.So we don't want to do this 'cause this is hard codedfor 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 wantto turn the input and send it back out.We want to return back the original image.So this is gonna make an image tagfor 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 imagesthat 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 dois 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 changeswhich 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 thatwe're talking about, the number in the listthat 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 aboutis 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 imagesand 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 basicallythe 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 anypart 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 tagand not the document is I still want to clickthe 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 justincrease that value of i.The new value of i is going to be equalto 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 fivethat we're talking about.So what we wanna do is add a little bit more code in herethat 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 thanthe 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 iis 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 matterhow many images that we put in here,the only thing that we need to changein our code now is this list.So if we add a fifth, this is the only placethat we need to go because we've set up our codeto only listen out for certain numbers like how longis this list that we're talking about.(upbeat music)
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 cursorwas to trend it towards the aim.So here we're gonna do a current x of nulland a current y of null.Now I've kept them all as lets rather than constantbecause they're going to change if I move my mouse,this wants to change.Now what I'm gonna do to start withis 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 aimto be where this mouse movement is.So in here, what I'm gonna do is say my aim xis 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 sayif 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 betweenanything 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 commentedout code a little bit later but for nowwhat we're gonna say is I basically wantto make some kind of drawing loop.So I'm gonna make a constant called draw.Now constants and lets don't have to be equalto 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 basicallydraw 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 xand 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 hereand I'm gonna un-comment it.There we go.Now again, you can just remove those little commentsin 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 positionand the current y position.
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 timesthis 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 mousevery, 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 yis the old version plus the difference betweenthe 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 hereand what we'll get on the pageis 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...