Transcripts
1. Why You Should Take This Class: Parallax is awesome 3D effect you can see in tons of websites, games, and apps. It's an interaction delight and it attracts people like crazy. In this class, I'm going to show you how to hand code your own parallax experience using JavaScript. It may appear like voodoo and dark magic, but it's actually pretty simple and hugely rewarding. My name is Rich Armstrong and I've been making things move with code since 2006. In this class, we go step-by-step through consecrated parallax experienced by responding to the mouse move and documents scroll events. The class is packed with theoretical and practical videos and by the end, you'll be able to amaze your friends and bring life and magic into your web projects. I design the class for someone who knows their way around, HTML, CSS, and JavaScript. Severe keen to create some parallax interactions. I'll see you in the next video.
2. Parallax Explained: So what exactly is the parallax effect? If you've heard this term before, what may come to mind is a website that make stuff move at different speeds as you scroll. This is a good starting point. The parallax effect is really an illusion of depth that occurs when two or more objects move at different but related speeds, making us believe that there's a distance between them, that there's depth. One dictionary defines parallax as the apparent displacement of an observed object due to the change in the position of the observer. I added the emphasis. In real life when we move, everything around us appears to be moving and all at different speeds. Think about when you're looking out of a window and a car or a train, or even move your head or walk around right now, can you see how things appear to be moving around you? You'll see that the things that are further away seems to be moving at a slower speed and the things that are closer. Of course it's us that's moving. This may seem pretty obvious to you. The question then is, how can we replicate this in a digital world when our screens are actually flat without any depth? Well, we have to create an illusion of depth. We have to make people believe there is depth where there is none. We get to be illusionist and magicians. This is pretty cool, right? To create the parallax illusion in a simple way. We could make things move at different speeds. This is what animation offers, but it has nothing to do with the observer. It isn't controlled by the user. It isn't interactive. Where the Parallax effect really comes alive is when the elements move based on a user's movements, like when they scroll or when they move their mouse or when they tilt their phone, and this is what we're going to be getting into in this class.
3. How This Class Is Going To Work: There are two parts to this class, really. The parallax side of things and the coding side of things. We're going to be mashing those two worlds together. You can take this class and apply it to whatever coding language you like, but we'll be doing it in HTML, CSS, and JavaScript. Why? Because it's super accessible, it's super fun, and you can make some things really quickly with it. This means we'll be covering a lot of HTML, CSS, and JavaScript topics and how they relate to each other, which is fundamental to interaction design on the web. In this class, there are three main things we're going to cover. The first is what I like to call, inputs. We're going to learn how to track the user's movement and use it to inform how our objects on our screen move around. The second is what I like to call, outputs. This is where we'll learn to manipulate how our objects move based on our inputs. The third is we're going to learn about parallax, which we've already done. But we're also going to learn how to use the inputs and outputs to create an interactive parallax experience. What's really important is that you learn how to make these parallax experiences based on theory and not just by copying code. We'll be hand coding everything in this class and if you're serious about learning best, I'd suggest you write your own code as you go. I learn best by following along, pausing the video when I'm trying to grapple with what they've just said or when I want to understand something. Write your own code, try things out, break things and even try things out before I get to them. Shout if you don't understand anything or if you have any questions at all. I'm going to use an online service called CodePen to do all my coding with in this class. I like teaching with it because we can see the HTML, the CSS, and the JavaScript all in one place and it reloads the preview as I type. I recommend that you use it too. It's free, it's easy to create new pens, deviate from existing one using the fork functionality, and because it's already online, it's really easy to share. Which means if you have any issues, you can just share the URL with me and it also means you can share your awesome work with other students, with your mom and with anyone else. The only thing you won't be able to do with the free version of CodePen is upload images, but that can easily be overcome and I'll show you how to do it later in the class. If you want to write your code on your computer though, using your code editor, that's totally cool. I'd recommend using Sublime Text, it's my favorites or Visual Studio Code, it's made by Microsoft. I'd also use GitHub for backing up your code and GitHub Pages for sharing. That's free to. If you have your own website, you can upload it there too. So let's get going, we're going to have a lot of fun.
4. Inputs And Outputs: What are inputs and outputs? I'd like to see inputs as things that can be tracked and responded to. Then I like to see an output as something we can control. In a world of coding, it helps when an input has a range. It means we can track it a lot easier and then respond accordingly. Think of an oven dial. It has a minimum and a maximum value, or a start and an end value. These values correspond to a temperature range. With code, we can change object properties based on an input. The ones that are the most fun and the most realistic, are the ones the user has most control over. In this class, we are going to be working with the user's mouse position and documents scroll position, as our user inputs. Then we're going to be changing object's position based on this input.
5. Capturing Mouse Movement: Let's get started. What we're going to do in this video is end up with two input values that we can use to connect our output values to. They're going to be fraction values conveying the mouse's X and Y position. We're using fraction values because it will make it easy to connect our future output values to. To get a fraction value, we need to get the mouse's current position and compare it to its maximum position. I'll work with the X position for now, but the same applies with the Y position. The maximum position in this case will be the windows width. All we need to do is divide the current mouse position by the maximum position. It's a fairly easy calculation. But this assumes that we want to track the mouse from the start of the window to the end of the window. What if you want to track the mouse position from 100 pixels from the left to 200 pixels from the right. How do we calculate the fraction value then? Let's write down some values. We want the fraction value to be zero when the mouse's position is at 100 pixels and the fraction value to be one when the mouse is position is that the windows width -200 pixels. We need to calculate the value between the end and the start values. We can do this by subtracting the start value from the end value, which we'll call our input range and then when we get our current mouse position, we can subtract the start value from it to negate the start positions value. This means that if our mouse's position is 100 pixels, it will actually be zero in our calculation. Now, we compare that value to our range to get an accurate fraction value. Using this calculation we'll always get the correct fraction value. The calculation is now slightly different to before, but we can also use this calculation if we want to track from the left of the window all the way to the right. You may now be asking what happens if the mouse position is between zero and 100 pixels? What kind of fraction value will we get then? We'll get negative values and if the mouse position is beyond the inputs end value, then the fraction value we'll get will be bigger than one. These values will be really important later on but for now, we could restrict the fraction values to values ranging between zero and one with a little bit of code. If you need a moment to digest these calculations, I'd suggest pausing the video right here and getting a pen and paper and work it out for yourself. It makes a world of difference when you actually understand it. That's the input theory. Now, let's implement it in code. We don't have any HTML so far, and that's great. We'll write a little bit towards the end of the video and I've got a little bit of CSS that I've applied to the body. It's got a background color and it's got a margin of zero. We won't write too much CSS either so we're going to close that for now. Let's start writing some JavaScript. I'm going to create a variable called input, where I'll set up all of my input information and this is going to be an objects and inside of this object we're going to say there's a mouseX object and mouseY object. This will contain all the information for mouseX and for mouseY. I'm just going to work with mouseX primarily and then at the end of the video, I'll update everything to work with mouseY too. We've got our start position, we're just going to set this at zero for now. We've got our end position, which is going to be our screen's width or our window's width. So I'm going to say window.innerwidth and then I'm going to set my current value at zero initially and then I also need to put in my range, and I need to put in my fraction value. I'm going to do this outside of this initial setup so that we can also update it later on. Input.mouseX.range = Input.mouseX.end - input.mouseX.start. The mouseX's range is equal to the mouseX's end minus the mouseX's start, which in this case will literally just be the end value. This looks a lot like that initial calculation, but we'll update the start and the end position, which will make the range way more useful. Then we can calculate our fraction value but our fraction value is not going to be much use unless we can actually calculate the current X and Y position of our mouse. How do we do that in JavaScript? Well, we have these things called event listeners and we can add them to a bunch of different objects. One of the objects that we can add an event listener to is the window. I'm going to say window.addEvent listener and this function accepts a bunch of different arguments or information that we can pass to it. The first thing that we can pass to it is the type of events that we want to listen to. I'm going to listen for the mouse move events and then what I want to pass in here is what to do when the mouse move events occurs and this is a function. When the mouse move events occurs, run the code inside of this function and for now, we'll just write console.log and we'll just make sure that we spell everything correctly and we'll say, "Working." Then we open up our console, which is the CodePen console, and we move our mouse around and we see that the console has a bunch of working messages coming through. That means it's working, which is fantastic. Now, I don't want to stall this piece of code over here because this is an anonymous function, it means that we cannot access it outside of the mouse move events. I might cut this and I'm going to store that piece of code inside a variable called handle mouse move. You could also store it inside of a named function. I like storing things inside of variables. I'm going to paste it there. That means that I can copy and paste this and that means that when the mouse move events occurs, which happens all the time it'll call this variable which then runs this piece of code. Fantastic. If we clear the console and we move our mouse around just to double check that it is in fact working. Now, the next thing that we need to achieve as we need to get the mouse's X value or the mouse's Y value. How do we do this? Well, in JavaScript, we get this event object that is passed to our function. You could call this whatever you want. Some people go for E, Some people go for EV. If you really wanted to, you could call it Bob. I like events because it described exactly what it is. Instead of logging, working, I'm going to log my event and then my events object. The reason why I've got event in the string is that I know exactly what I'm logging at any given time. If you've got a bunch of console logs throughout your code and you don't have an indicator of what it is it may get really confusing. Lets clear our console and move our mouse around. CodePen will say that the log has been skipped. It'll say that it's too large for their console and you might need to use the browser console instead. CodePen's console isn't this powerful. So we're going to have to use Chrome's console instead. So we go to View Developer and then we go for JavaScript console and let's just move our console a little bit down so that we can move our mouse around up here. You'll see that as you scroll down in Chrome's console, there's a bunch more events coming through. Let's see what this event object is. Is a bunch of keys and values here. Let's just make this a little bit higher, like so and we've got layerX, layerY, we've got client X, client X. We've also got offset X offset Y, pageX, pageY. All of these look really good X and Y. We've got a bunch of other information too but I'm most interested in these X and Y values. What I'd like you to do is pick one of these and see if it works. I'm going to go for client X and client Y, or perhaps pageX and pageY. They all look really similar at the moment. Let's close this and let's log event.clientsX and let's make sure it goes there to. Clear our console here and move around and we're getting some values which looks really promising. So if you go all the way to the left, we should expect a zero, which it is and if we go all the way to the right, we should expect a pretty large number, 572. Now, we can check if this is actually the value by putting in window.innerwidth which is undefined and that's because we spelled width with a big I, 573. This is a little bit suspect, don't you think? Well, for now we're going to work with this, it's pretty good. Now, we've got our clientX which means that we can actually go and update our input.mouseX.current which equals our event.clientX. It means that we can also update our fraction value. So input.mouseX.fraction equals. Can you remember what our calculation for this was? Well, it's our input.mouseX.current minus the start value. We're going to put this inside of some braces so it works that out first. We're then going to divide that by the input.mouseX.range. This is quite a long piece of code. That's just because we're being overly verbose about it, we're saying input.mouseX.current. That's just so that you guys knowing exactly what's going on with all these values at any given time. We've got our current value, we've got our fraction value. Well, let's see if this is actually working. Let's log out our fraction value and input.mouseX.fraction. Let's make this a little bit bigger. We go from left all the way to right. That's weird that it's going to 1.36. What is going on here? Well, you may have seen that I resized my screen a bit. I would've always start at zero. But depending on my screen width, it might get to a value way bigger than one. What's actually going on here? We'll, check this out. We're storing our end value inside of our object, initially. It's not updating when the screen or the window resizes. We need to update that value so that we can update a few other values so it can give us an accurate fraction value. How do we do this? Well, this piece of code here. I'm going to copy and paste it. Instead of listening for a mousemove event, I'm going to listen for a resize event. Then instead of calling the handleMouseMove function, I'm going to call the handleResize function. So var handleResize and this is going to store a function. Inside of this function we're going to update our code input.mouseX.end equals, and it's going to be exactly the same as our initial value. There we go. Because our end value is updated, we also need to update our range value because it makes use of the end value. That should handle that. Let's see if it works. To clear our console, go from left to right. It almost gets to one. 0.998, it's almost one. We're going to work with this. If we resize our browser 0-99, things are definitely working. What we need to do now is we need to check that if our start value is at 100 and some other value, this actually also works. Let's start with our start value and then we'll get to our end value after that. What I'm going to do is, inside of our HTML, I'm going create a div with a class of block. I'm using a thing called Emmet which works in CodePen, Sublime Text and Visual Studio Code. Once you've got this abbreviation, you just press "Tab" and it expands it into some code for you. I've got an entire class in this if you want to check it out. Inside our CSS, where Emmet also works, I can go.block. I'll give this a background color and then go for a color that CodePen has. Let's go for this green color. Let's copy it to the clipboard, let's paste it. Thank you very much. I'm going to set a width of 100 pixels, and then going to set a height of 100 viewer height. Now we have this great little green bar. That's going to be 100 pixels. When we clear this, we'll know that when we get to 100 pixels, which is about there, it should be zero, which it looks like it is. Now we need to set our end to the innerWidth minus 200. Don't forget that we can also just copy this and paste it down below where we update our end value. Pretty important. Let's just copy and paste this block piece of code, let's call it block2. Inside of our CSS, we'll do pretty much the same thing for block2. We'll give it a width of 200 pixels this time, a height of 100 viewer height. We'll say position absolute, and we'll say right, give it a value of zero and a top value of zero too. To mean it's on the right-hand side. If we go to here, it should be zero. If we go to here, it should be one, which it is. If we go over one, it's going to be a value over one. If we go below zero, it's going to be a value below zero. There we go. This is exactly what we've wanted from this video. I'm going to show you two more things. The first thing is that if we don't want our values to go below zero and above one, what we can do here is we can say. If input.mouseX.fraction is bigger than one, then we'll just cap it at one. If our value is smaller than zero, we'll also just cap it at zero. Like so. Then we'll log out our fraction value after we've nailed those two things down. When we go from left to right, it's zero, zero, zero, zero, zero, zero. Then it starts working, gets to one, and then it just stays at one. That's a real easy way to make sure that our values range from 0-1. But those negative values and values higher than one are going to be really important in a later video. Now, the next thing is that we have our y-value to work out. What I'm going to do here is, I'm going to say pause the video and you try and work out your y-values. Have some fun, do some experimentation. I'm going to get onto my y-value in just a few seconds. Let's do our y-value. I'm going to change my start to zero again and my end to innerWidth. I'm going to go down here and do the same thing. Then I'm going to take out my two blocks because I don't really want them. I'm going to go to my HTML and take out those two blocks too. Now, let's go for our y-values. I just get to copy and paste a bunch of different stuff here. Instead of going for window.innerWidth, I'm going to go for window.innerHeight. Then I'm going to set up my mouseY range, my mouseY end, and my mouseY start. When I say handle the mousemove, I'm going to copy and paste this. We'll just copy and paste the mouseY into all these different places. It's all pretty much the same calculation, the same algorithm, we're just changing values. Instead of the event of clientX, I'm going to go for the clientY. We don't have to use this if we don't want to. I'm just going to comment them out. I'm going to press "Command" or "Control, " and "Slash" I'll just comment those out. We can go for logging the fraction X and the fraction Y, and we'll change this to mouseY. Then when we handle our resize, we'll just copy and paste this again, and then copy and paste our mouseY and change our innerWidth to innerHeight. This should technically work, so let's double-check that it does. We're going to go all the way at the top left, should be pretty close to 0,0. Then we go all the way to the right which should be pretty close to one for the x-value, and then let's check that our y works. I'm going to go all the way to the top. There we go, zero all the way to the bottom, which almost gives us one. But because of some reasons with this browser, it doesn't quite give us a value of one. There we go, we have fraction values for both our X and Y mouse position. This means that we can plug in some output values in the next video. Fantastic.
6. Connecting Mouse Movement To An Output: In this video, we'll connect our input fraction values we calculated in the previous video with some output values. Which means we get to start making things move based on our mouse position, which is super cool. Our output setup will look fairly similar to our input setup. There will be a start and end value as well as a range. To work out the current output value, we'll take the fraction value from our input and multiply it by the output range before adding it to the stock value. Or we could take that value and subtract it from the end value depending on what you want to do with it. Now, that's the theory let's get into some code. We're going to have some fun now and make some googley eyes move around when our mouse moves around. It's going to be great. Inside of my HTML, I'm going to create two eyes. So let's go for the eye and the inside pupil, like so and then inside of my CSS, I'll go for.eye. I'll set a background color of white and then a width of say, 200 pixels, a height of 200 pixels, a border-radius of 50 percent because we want it to be round. Yes. Then a pause A for absolute, and then we'll say a left of 50 percent. Well, thanks. Let's save that. Left of 50 percent and they we'll say a margin left of say, minus 100 pixels, just that's right in the middle and then we can say the same for the top of 50 percent and a margin top of minus 100 pixels also is there right in the middle. We'll then put.pupil in here, and we'll say VGC is black, we'll say width of 50 pixels, a height of 50 pixels, border-radius of 50 percent, a top value of 50 percent. We can pretty much just copy all of this and instead of a 100 pixels, we would just say 25 pixels. Doesn't look right. Now, doesn't look too right. Does it? Because we haven't put a position absolute. There we go. We have an eyeball, we have a pupil, we have an eye. So now I want another eye. Let's go for another eye. Perhaps we'll call this one eye 1 and this one eye 2. Great. Eye 1 will have, let's say, a margin left of minus 200 pixels.eye 2. I don't have three eyes. Eye 2, a margin-left, perhaps you can say 0. We can get this a little bit more room. So let's add 25 pixels to that and 25 pixels to that. There we go. We have some eyes. Now, as I move my mouse from left to right, I want the eyeballs of the pupils to follow the mouse, or maybe to look the other direction to where the mouse is going. Same with my y position. We've done our HTML and CSS. Now let's get into some JavaScripts. Let's make these panels a little bit bigger. Over here, we're going to go and create our output setup. This will look really familiar. We'll go for an x and a y setup, and x and y because it's not really mouse x and mouse y, it's actually the x exposition or a translate x position and the translate y position. Let's go for a start value, and I'll say minus 100 pixels, except without the px and the end, of say, 100, the current will be 0 and then a range, we could just put our range in here of 200, but we'll dynamically create that after we've created the object. I'll just work with the x position for now, and I'll get you to do the y position later on before I finish up and show you exactly how I would do the y position. So what's after this is our output.x.range and this is our output.x.end minus output.x.start. Fantastic. I'm just going to cut and paste the input values where the input coders and the output where the output coders. That makes a little bit more sense. We can also start just counting coder bits just so that we know what's going on. Fantastic. Then down here, we probably don't need this anymore unless you're going to make use of an input range where the start is not 0 and the end is not the window in a width. So we can just chop that and then we can do some more commenting here. So we can do mouse x, we can say mouse y, or we can just call that mouse x input to mouse y input. Then we've got some console logging happening here, which I'll just comment out for now. Now we've got our inputs happening. We've set up our outputs. Now, how do we actually convert or connect our inputs to our outputs? Output, let's spell that correctly, output.x.current equals, and we've got a fraction value that we can work with. So we're going to say our fraction value multiplied by our output.x.range, which is going to be one value in itself. So you don't have to do this, but sometimes it's a bit easier to say, okay, that is a value that is going to work out first, and then we're going to say output.x.start plus that value. Now let's log this out. Let's see what happens. All ready. If we clear this first, you're all the way from the left, which is minus 100, all the way to the right, which is almost plus 100. Pretty cool. So this is working, our output values are coming through. Now we just need to connect it to the HTML. But how the heck do we do this? Everything up until now has been simple coding. Well, a bit of mathematics, but no HTML stuff. How do we actually connect the HTML? At the top of my document. This is where I'm going to set up my HTML. So HTML setup. Inside of our HTML, we've got some classes, we've got eye and pupil. I want to move and make changes on the pupil. So let's try to get the HTML elements for these pupil classes. Someone say var pupils HTML Collection equals document.get elements by class name and you see how we're using camel case here and then I want to get pupil/not pupils, pupil. Let's say console.log, pupils HTML collection. You may have seen that quick flash, says log skipped. We'll actually have to check out what that is using Chrome's Developer Console. We can just log that here again. You see? Log skipped. So let's go to Developer and JavaScript console. This logs HTML Collection, which is div of pupil and div of pupil. You can see that it's actually selecting whether these HTML elements, as I hover over them, we can also right-click and say reveal an elements panel, and there we go. We've got these two eyes, which is fantastic. So let's close that. This won't actually help us too much. We need to convert this pupils HTML collection into an array. There's a few ways you can do that, but one of the simplest is var pupils. Array equals array.from, and we just paste in our pupils HTMLCollection into there. If you're wanting to make production ready code, just double-check that this piece of code works in all the browsers that you want your code to work in. Now we've got our pupils Array, let's just double-check this, also a log skipped. Again, log skipped. Let's go and check out what this brings back. Again, it's going to give us our two pupils, but instead of an HTML collection, it's not going to be an array, which means we can work with it. Let's close that up, let's copy this pupils Array, and let's go into our upward section over here. We've worked out our output x, now let's go and apply output to HTML. We copy our pupils Array, and then we uses array rad function called forEach. Now our forEach function takes a function argument. We can say function and inside of here, we're going to put an anonymous function. There we go, and we run code for every single pupil that is inside our array. Inside of this function, we get possible information. The first piece of information is the actual element. You could write element, I'm going to write pupil, because I want to know that I'm working with one pupil, and then you also get past which Luca says. The first pupil, is going to get a zero value when we log i, the next one is going to get a value of one when we log i. This is really, really cool because it means that you can change your code, you can change some logic based on which i it is. It's a bit confusing when I'm saying i. We could use something like k here. Let's say pupil.style.transform, and this is actually going to change the HTML, equals. They want to say translate x. I'm going to use translate x for now. I'm going to say translate x, and I'm going to say 75 pixels. There we go. Let's see if this actually works. Right now, it's not doing anything because we haven't had our mouse move just yet. Let's clear these console, and perhaps we can just clear the logs for now. You see now how our pupils had been coded to be 75 pixels. If we right-click and we say Inspect, you can see that it has a translate of 75 pixels applied. That's fantastic. Let's close this again, we can scroll to the top, and we can just take out this console log, and then we scroll back down to apply output to HTML piece of code. Instead of making this a static value, let's make this a dynamic value. We can say plus plus, and we can now put an output.x.current value right here. What this is doing is, this is concatenating three different values. This string, this number value with this string, and it's putting them all into one string value. It's called string concatenation. An amazing little descriptive word there. It's applying them to the pupil.style.transform value. Let's see if this works. There we go. It's quite fun. Let's just clear our console and just close that. That's really, really cool. It's fun. It is overlapping a little bit, so we could change our input or output values a little bit. If we scroll up here, we change our output values to minus 70 and perhaps our end to 70. There we go. Never quite reaches it, or what we could do is inside our CSS, we could change our i, we could just say overflow to hidden. That means that when we get to the edge, it doesn't overlap, it just goes behind. So your choice what to do here. Let's just hide that again. What is next? Let me show you a few really cool things. At the moment, our pupils follow the mouse. How do we get it to not follow the mouse, but be inverse? As I move my mouse from left to right, the pupils move from right to left. Is that possible? Well, check this out. Our output.x.current equals the output.x.start at the moments. What happens if we start off at the end, and we say minus this value? That means as we go from the right-hand side to the left-hand side, it's not doing the inverse of what our mouse is doing. Now what I want you to do is pause this video and try get the y-values working for the pupils. I'm going to show you how I would do the y-values for the pupils. Let's get going. I'll put sections here, let's just copy and paste this. Minus 100 to 100, it should be about the same values. You can change these if you want to. Perhaps we can, let's maybe change it to 125, like so. Then we'll just calculate our range for our y. There we go. We've got a mouse x input, and mouse y input, output x. Let's get our output y, like so, and we can start at the end again. It changes to y, mouse y fraction, which is really important. You can actually experiment with mouse x with your y, that's a little bit funny. I'll leave it up to you. Then over here where we apply to the HTML, instead of using translate x, I'm going to use translate, which means that I need to put in another value over here. We can say 50 pixels and we move our mouse around. This will always stay at that same position. That's not quite what we want, we want this to be dynamic, so instead of 50 pixels, we want to use a more string concatenation here. We'll put in single quotes, plus, plus, and then between the pluses will use our output y.current. Let's see what happens here. This is going exactly where our mouse isn't going, and you see that we can actually hide our eyeballs, which isn't ideal. I'm going to change my values here to maybe 75, and I'll change these to 75 and 75 too. There we go. Pretty cool. If we wanted our y value to follow our mouse position rather than be inverse, we could start at the start position, and then add this piece of the calculation. You see as I move my mouse up, it follows my mouse. As I go from left to right, the eyes do the opposite. You can change the code really easily and simply update the HTML. For stretch exercise with this, what I want you to do is, I want you to try for each pupil, make a move in a different direction. As I move my mouse from the top of the screen to the bottom of the screen, I want one eye to follow my mouse, and I want the other eye to not follow my mouse. I want it to be inverse. The same thing for the x. As I move my mouse from left to right, I want one eye to follow the mouse, and I want the other eye to do the inverse. Pause the video here, and see if you can do that. Let's try this out. I want my pupils to do the opposite things. What's great is I have this k value or i value, whatever you want to call it. I'm going to say if, and I'll say k equals, equals, equals zero, which will be the first i, do something, else, do something else. Let's just copy and paste this in here, copy and paste this in here, and let's take this out, which looks like that. This should still work exactly the same, we've got the same piece of code in it. Now I've got my current values here. What I'm going to do is, I'm going to change or add a different value. I'm going to copy and paste this output x, and I'm going to say dot opposite. I'm going to say start plus this value over here, and I'm going to do exactly the same for my y value. I'm going to say the opposite is the end, minus, and start plus. Now, you could call this whatever you wanted. You could call it inverse, you could even just change this to start, and this to end, and this to plus, and this to minus, whatever you want. I've now got two output values that I can work with. I've got the current and I've got the opposite. Let's see what happens here, if I update this to opposite and opposite, and this one to current and current, what happens? If I go all the way to the middle, he's normal, and if I go all the way to the left, he goes a little bit like weird squinty, if I go all the way to the right, super squinty. There we go, you can start having some fun, all encoded. The HTML is just being updated by your code, really cool. In the next video, we're going to take this to the next level. We've learned how to move things around with JavaScript. It's been really fun. But at the moment, there's no much depth. There's no much parallax. We're going to introduce parallax and depth in the next video. I'm looking forward to it.
7. Creating The Parallax Effect: In this video, we're going to create an illusion of depth. There are various ways of doing this but one way I quite like is to give each parallax elements at depth value between zero and one. Yes, we're talking about values between zero and one again but, why? Because it's easy to connect to our output values. Zero means very close and one means very far away. As an element gets further and further away, it will move less and less quickly. How we do this in code is, for each element we start with the x and y outputs that we worked out in the last video then we subtract a value that is made up by multiplying the current x or y outputs by the element's depth. If the depth of an element 0.5 then the x outputs of the elements will be half the current x output. If an element's depth is zero, the x outputs of that element will be the full x output and if the depth of an element is one then the x output for that element will be zero. The other thing we need to be aware of is where our elements appear on screen. In HTML, unless you specify elements z-index, it will appear beneath elements that come after it and on top of elements that come before it. If our first element has a depth of 0.1 and our second element has a depth of 0.8 in HTML the second element would appear on top of the first. But according to the elements depths, we want the first element to appear on top because it has a lower depth value. Unless you want to manually set z-indexes or put all the elements that are further away at the top of the document then we need to adjust the z-index values on each elements with code. We can do this by setting a zIndexRange. We then work out elements zIndex by subtracting the zIndex Range multiplied by the depth from the zIndexRange. The zndIexRange should correlate with or be higher than the amount of decimal places you intend to use in your depth values. If you are using single decimal places then a zIndexRange can be 10. If you're using two decimal places then use a zIndexRange of 100 and so on. A zIndexRange of 1,000 or 10,000 is a pretty safe bet. As you can see, it's all to do with depth. Now, let's get into the code. We've got quite a bit to cover. While on googly eyes example was pretty fun to play with and to create is not really going to help us in creating a parallax experience. I'm going to do some re-modelling here. First up, I'm going to remove my eyes from the HTML and create some parallax item elements so we can create maybe three of these. Then in my CSS, instead of eye1 and eye2, instead of my pupil, I'm going to change my.eye2 maybe let's just copy and paste this to parallax item. Background color, we can change this to black. The background color is black. The width and height 200. Border-radius we can take this out, okay? The position is absolute left and top margin-left, margin-top. That's all good. It's looking great. It is in the center of the page. The overflow: hidden, we can take that out. What we'll do is for each of those elements will set a separate background color. Then at the top here, instead of pupilsHTMLCollection, we can say items HTMLCollection and we can copy and paste that. Instead of looking for closing of pupil, we're again going to be looking for parallax-item. We can copy and paste that. Then instead of pupilsArray I'm going to go for items Array. We then got our inputs and our outputs which are all pretty good. I'm going to change these from 75 to 100 just so that there's a little bit more movement, perhaps we can even say 150. Let's just copy and paste these. Our outputs are handled. We then got all mouseX and mouseY inputs being worked out. We've got our output x. I don't need a current and an opposite being worked out all the time. I'm just going to go for current. I'm going to stick with the end minus this value here. Apply output to HTML, that's great so we're going to go with our current values. Let's just take this and overwrite this because there's going be no more eyes. Instead of our pupilsArray here we're going to go for itemsArray. Instead of referencing this element with pupi we can go item and then item.style.transform and then we translate it. It looks like it's working fantastic. Lets put some styling into these blocks. I want to say background-color. What color do I want? Well, this one's going to be black, so that's great. Let's copy and paste these style attributes. Let's open up our assets panel in color pen. I'm just going to copy one of these and paste it over here. Then let's go for a blue and paste it over here. Thank you very much. Now we have all of our squares moving at exactly the same speed. What's happening here is that if I come into this out, you'll see the pinky one and if I come into this one out, you'll see the black one. If I come into them both and again, just take it from me that they're all moving at exactly the same speed. What we're going to do here is we're going to start introducing our depth. For this item 1 I want a depth of say 0.1. In JavaScript we can use data-depth and when I say depth, you can put what you want here. It's up to you. Let's go for 0.1 and let's copy and paste this. Let's just make this a bit bigger. This can be 0.3 and 0.6. That means that this one should be our closest square. This one is in the middle and this one should be the furthest one away. Here we can see that that's not the case, but we haven't done any coding to make it so. This just highlight on html and CSS and let's go down to our items array for each loop. In here we can start playing around with the depth. To actually get the depth into JavaScript, this is what we're going to do. We're going to say var depth. We install this depth inside a variable called depth. We'll say item.dataset.depth. When I say depth here, if you named your data-depth, something like data-distance then you'll say dataset.distance, but we've got depth here. Let's see if this is actually coming through console.log. We'll say k for the item then we'll say depth and depth. When we move our mouse around, the first item has a depth of 0.1, the second has a depth of 0.3 and the third has a depth of 0.6. The items are coming through. The thing is that these are text values. I want them to be number values. How do we get that to happen in JavaScript? Well, we can use this thing called parse float. Then we select that and then we put it in braces. What parse float does is it converts something into a number and specifically a number with decimal places. We know that we have decimal places so this works really well. The other thing is that we need to put comma 10. If you don't put this is not a massive trans match, but it's best practice. The reason why I put comma 10 here is because we're saying we want this to be a decimal system. It could convert a number or a piece of string to something that counts by 15s for example. This is really good practice. Let's keep that in. Now when we move around and we'll see that these are all numbers now, they're orange, they don't have quotes around them. Now how do we actually apply this to each of our squares? Let's set up an item output. This is going to look fairly similar to our output up above here except we wouldn't have a start end and current value we'll just have an x or a y value. We don't need each of these. Down here, we're going to have our x value. What does our x value going to be? Well, it's going to start at our output x.current. It's going to be that as a starter and we'll say minus the output x.current multiplied by the depth. We can put braces around these just to make sure that we know that it's being calculated first but it does actually calculated first because of the multiplication sign. We've got all our exposition. Now I say itemoutput.x. Let's see if this works. The y is still part of the general or the global y position but our x is determined by our depth which is pretty cool. Now let's put the y position in here. We can just copy and paste this y:output.y, output.y and itemOutput.y. There we go. Now you can see that it's moving inversely to our mouse position and it's based on depth. Let's clear this and close. But there's one small problem still. In our HTML you'll see that our depth, this one is at 0.1 which means it should be at the front, right? because it is closer to us. Even though this looks nice, it's not really true. The closer something is, the quicker it should be appear to be moving. How do we change this? Well, in our JavaScript we can now start changing the z-index or the z-index, depending which part of the world you're from. Let's add a new value here, z-index. What we're going to do is we're going to say 10,000 is going to be out on z-index range. We'll create a new variable in our output shortly but we start with 10,000. It's just a really safe number to work with. We're going to say 10,000 minus 10,000 multiplied by our depth, okay? Now, we can just put these in braces to so that you know that that's being worked out first. If our depth is one, then our z-index is going to be zero. If our depth is zero, it means our z-index or zIndex is going to be 10,000. Then we add another line for our item and we say item.style.zindex equals and we just plot this number into there. That doesn't work. Let's open up our console, logs trimmed. There's no error messages, things aren't working. What's going on here? We have to go to our a Chrome, Developer, JavaScript Console and it says ReferenceError: z Index is not defined since happening all over the show. We can come down here and say zIndex. It's not itemOutput.zIndex is just zIndex. There we go. That should fix things for us, fantastic. Now our black box is on top of blue box is at the bottom. Things look really lifelike now, pretty cool. You may notice something a little bit strange now. These items are all actually the same width and height but as we've moved them backwards further and further away, they don't appear to be further and further away. What you could do is you could manually scale them or change the width and height the further and further away they get or you could do it with code. You could do a dynamically. That's what we're going to be getting into in the next video.
8. Making It More Realistic: We've made some parallax magic happen and it looks awesome. But if we're trying to get things looking and behaving like they do in real life. There will always be more things we can do. In this video, we're going to address two of them. We'll also do some code optimization and I replace the boxes with some nice-looking leaves because leaves are cool. The first thing we need to address is scale. If there are two items that are the same width and height, and one of them is further away. It should appear smaller in scale and it should appear smaller according to how far away it is. Its scale should be relative to its depth. You can hand-code each element's scale, or you could do it with code and of course, we're going to it with code. We could calculate the scale really easily by starting with one and subtracting the elements depth. But perhaps we don't want our items to be so small. Let's set a start and end scale, which will lead us to creating a scale range. Then to calculate an element scale, we start with the start scale and then add the depth multiplied by the scale-range. Does looks pretty familiar, doesn't it? The next thing we need to address is blurriness. Items will appear more and more blurry the further away they get. But we don't necessarily want them to get blurry until a certain depth. Otherwise, everything except elements and zero depth will be blurry. One way we can calculate blurriness is by deciding on a starting depth value, which will be where the blurriness will kick in and the other is a blur range value, which would be how blurry and element can get. The starting depth value needs to be a value between zero and one so that it correlates with the depth values and the blur range value is what we'll connect each item's depth to. Much like our Z index range are elements blur value is then calculated by subtracting the starting depth value from the elements depth and then multiplying that with our blur range, you may end up with some negative blur values. But at the moment it means that those elements will appear non-blurry, which is exactly what we want. Now let's implement scale and blur in our code and while we're doing it, let's optimize our code a little bit. Let's turn our blocks into some cool-looking leaves first. We'll open up our HTML panel, let's give it a bit more space. I'm going to take out the style attributes, boom, boom and boom. Then inside of my parallax item, I'm going to add an image and the source is going to be? If I open up my assets panel inside of CodePen, there's a bunch of images. You could go to photos that they're not ideal. With CodePen pro, it allows you to upload your own assets. I've uploaded a bunch of my own parallax assets. You can use these assets if you want. You can also use the assets available in the class and I'll show you how to upload your own assets and copy the URL if you don't have CodePen pro. We've copied that. Let's paste it into our source and there we go. It's coming through. Let's just copy and paste these into our div items and then asset number 2 and asset number 4. There we go and I'm using asset number 4 instead of asset number 3 because asset number 3 is a really big splotch and doesn't looked so cool. Then inside our CSS, I'll go dot parallax, item and I'll address the image within parallax item. I'll say width or perhaps max width is 100 percent and max height is also 100 percent. Let's see what that does. Yeah, that looks pretty good. Now how do I get it into the middle? Perhaps we can use some flex, df for display flex I'll say justify-content, center and align-items center. There we go. We can take off our background color. We can change the width and the height to 300 pixels and there we go. We now have three leaves on top of each other. What I want to do now is I just want to rotate the leaves a little bit. Let's open up our HTML and do some inline styling here. First one, let's go for a style attributes and let's change the transform rotate to about 30 degrees, like so. Then we'll copy and paste this and we'll change this to negative 45 and this one to something like 110. Does that work at all? Nope, because we've spell transform wrong. How about that? There we go, and things are starting to work now. We have some interesting leaves happening at the moment. They're a little bit better than our blocks. We've got our HTML done, we've got our CSS done, now let's get on to some JavaScript optimization. The first thing I want to do is, I want to remove these values that we don't really know what they are and what happens if we change one, then we always have to change the other. Let's change this to output.zindex.range and we'll copy and paste this and then up here we'll just put in our zindex object and we'll put in a range key, and the range will be 10,000. That's the first optimization that I want to do. The reason that I do this is so that I don't have a bunch of these 10,000 numbers just all over the show. I know exactly what it is and I can update it in one place and it will update it throughout my code, which is really cool. The next thing I want to do is, I want to change how this handle mouse move function works instead of having all this code inside of here, which is getting really, really long, I want to split it up. The way I want to split it up is I want to create a variable which is called updateinputs and I want to store a function in here which runs this code. Let's take this code from here and put it into this function and then going to run updateInputs from within this function. It means that I know exactly what it's doing. But I don't really have to look at the code and scroll through it every single time. The only problem with this way of doing it is that event will not be present in this function. What I'm going to do before we call update events is I'm going to assign my mouse.x to event.clientx and my mouse.y to event.clienty. You may be thinking that well, where the heck is mastered x coming from? Well, we're going to create that. Let's go for var mouse and will create an object and its x will be zero and it's y it will be zero. Now, when we get the event, will say mouse.x equals the event.clientx. Then instead of assigning event.clientx to our mousex.current, we can say mouse.x and mouse.y. That means that we can run our update inputs without having to rely on an event property. Now let's do the same for our output. This creates a variable called updateOutputs and let's store a function inside of here. We can cut this and paste it. Instead of having two lines of comments, I can just say output x and y, and let's just do it like that. That looks a bunch neater. We then call the updateOutputs function straight after the updateInputs and then we want to put this into a function to. This one's a little bit different because we're creating an item output for every single element and then we're updating the HTML. What do we call this function? Perhaps you can say updateEachParallaxItem. How about that? Let's copy that, paste it. I'll say var equals function and then we can cut this and put it in here. Now our code looks a lot more readable. We just see that it's updating the inputs, it's updating the outputs and then updating each parallax item. This is also really cool because we can call each of these separately and outside of this handle mouse move function. That's great. We've cleaned up our code a little bit. Now, what's next? It's scale time. Where do we do our scale? Well we do our scale and our itemOutput. Let's add a new property to our itemOutput and our scale. What is this going to be? It's going to be something like our output.scale.start plus. We're going to put inside our brackets here, output dot scale dot range multiplied by the depth. We haven't set this up, so let's go and set it up. All of these, we can actually just hide them for now, which is really cool about CodePen. It's also available in the code editors. We can hide the mouse value and then let's go ahead and put our scale in here. I'm going to have a start value, and the start value I would recommend being one, because a scale of one means it's at the original size. We then have an end value, and the end value perhaps can be 0.2, but we'll update that in a moment. Then we're going to work out our range much like the rest of these calculations. Output dot scale dot range is output dot scale dot end minus output dot scale dot start. You may be thinking, "Hang on, we'll be starting with 0.2 and then subtracting one, which will give us a value of negative 0.8 as our range." That's perfectly okay. You could change it if you wanted to. There's no hard and fast way of doing things with code. This is just the way that I'm doing it. Let's scroll down. Our scale is now output scale dot start, which would be one. Then we're adding the output scale dot range, which is going to be a negative value, multiplied by the depth. If our depth is one, then our output dot scale dot range is going to be negative 0.8. We're basically going to be saying start plus negative 0.8, which will give us 0.2 of a scale, which is fantastic. If our scale or if our depth is at zero, the output dot scale dot range multiplied by zero will be nothing. Then we'll be left with a scale of one. The problem with scale is that scale and translate both are transform properties, so we'll have to add scale into this line of code here. So scale, let's try it out, 0.5. Let's move our mouse around here. There we go. They're really small, so let's make it dynamic. I'm going to go for item output dot scale. That looks pretty good, and if we scroll up here and we set out end scale to zero, things should get a lot smaller. Perhaps if we change our HTML, if we change the 0.6 to a depth of one, we should actually see it disappear. It's nowhere to be seen. That's because our end is zero, and it'll have a scale of zero. What do we do here? We change it back to 0.2 or 0.3, or if you want 0.3, and then there we go. It's not quite zero. I don't like items having a depth of one, it means that they don't move, so I prefer going for 0.9, then it moves slightly. We now have our scale sorted, that's done. What's next is the blurriness. Lets put in a blur value over here on our item output. What is the blur calculation output? Dot blur dot starting depth, which we haven't quite setup, and we're going to say our depth minus our output dot blur starting depth. We're going to put this inside a brace so it works that out first. Then we're going to say multiply by our output dot blur dot range. What this is doing is it's saying that we have a depth, this could be zero, so zero minus our starting depth, which would be 0.5 maybe, so you'd have a negative 0.5 multiplied by the blur range. It would give you a negative value, which is perfectly fine for an item with a depth of zero. Let's just put in this output value. Let's go for blur and let's set our starting depth, and let's say 0.5. Anything that's at 0.5 or above will start getting a blue value. We'll then set our range, and we'll say 20 for now. Let's implement this into the HTML. We'll go item dot style dot filter, which we haven't used yet. We actually need a string value for this, and we'll say blur, and lets just try five pixels right now, move our mouse a little bit. There we go, we have some blur values. Now let's make this dynamic. What's really important to note here is that you do need a pixel or some measurement value, so we'll just remove the five and put in item output dot blur, and when we move our mouse, there we go. You see an item that is further back is now blurred, and the items closer to us, they're not blurred. If we change the values of starting depth, let's maybe change that to 0.1, we'll see that my item, which is at 0.1, it's still not blurred, but the items at 0.3 and 0.9, they definitely are blurred. If we had to change our range to something like 40, you should see that the items further back get even more blurry. We've got our blur setup. The only thing that you may have noticed is that every single time I change my code, so I'm just going to put in a bit of random code here, you'll see that before I move my mouse, these things aren't blurred and the aren't scaled, which is problematic. It means that unless or until we move our mouse, things are not actually going to look as if they're blurred or scaled. Let's take this out and let's implement some code that will fix this. What's great is that we've actually done update inputs, update outputs, and update each parallax item. We can just copy and paste this code and go to the bottom of our code and paste it. Lets unindent it, and from the get-go, you'll see that now things are scaled, and things are blurred. They're are slightly offset, it doesn't really look like they're in the middle, so perhaps what we can do is adjust our mouse X and Y position. Let's go to our mouse X and Y, and we'll go for window dot inner width and window dot inner height. Perhaps we shouldn't do that. Perhaps we should say multiply it by 0.5. This means the X and Y will be in the middle of the window, as if it was about there, which looks great. If we do some code changes or someone comes and visits our little pen or our site, it means that before they've had a chance to move their mouse, things are going to look blurry, they're going to be scaled, which is fantastic. We've done a bit of code updating, we've implemented leaves into our parallax examples, and we've done some scaling and blurring. Super-duper. As promised, I actually need to show you how to upload your own assets. If you open a new tab, you can search for image hosting. There are a bunch of different ways that you can host images. Some of them do not work, but just try it out. What we're aiming for is we want to get an image URL that we can pop into CodePen. Let's go start uploading. We choose a parallax asset like this cool face, we say, "Okay, let's upload." Then we copy its link, you paste its link. This is not the image URL. Once the image loads, you right-click and you say "Copy Image Address", paste that again, and you'll see that it says dot PNG or dot JPEG, whatever you upload. You can then copy this URL, and then inside your HTML, you can paste that. There we go. You don't need CodePen to upload images or to put images into your projects. Now we have a cool face, and we don't need to use CodePen Pro. Or if you're not using CodePen at all and you're on your local computer, it's pretty easy just to reference images on the file system using relative URLs. Super easy. There are few things we could add and implement that would make it even more realistic, and perhaps even give it a bit of a wow factor. If you can think of any that you'd like to try implement, I'd suggest you try code it up yourself, have some fun, make some mistakes, and if you need some help or things aren't working like you expect it to, share your URL in the Comment section of the class, and I'll try to help you out.
9. Plan Like An Amateur: When you design and code various versions of the Parallax effect, there can be a lot of moving parts. This is not just the case for parallax, but also for other interaction design pieces. Planning becomes an essential part of the process and even more essential when you're working with a team. Trying to figure out everything ahead, like a professional for forehand is just not going to work, or if you're trying to make everything work magically while you're coding even never happened or it takes way longer than if you're just plan in the beginning. How do you plan? That's a great question. I plan in two ways, and I do both of them at multiple stages of a project. The first method is writing down what I want to happen. I start by writing fairly broadly and descriptively. My first piece of writing may look something like this. As the user moves their mouse, the items move. I then would go to something like this. As the user moves their mouse from left to right, the items move from right to left. Then I'll change it again, as the user moves their mouse from left to right, the items move inversely from right to left at a ratio. Then as the user moves their mouse from left to right, each item moves inversely from right to left at a speed relative to its distance away from the user, you can see how I'm adding more and more detail to my description here. Finally, it will end up like this. As the user moves the mouse horizontally, each item moves inversely at a speed relative to its distance away from the user. This may sound a little bit complex, and this is why I didn't start writing complex because this is a little bit mind boggling. This end description is my end goal. I start with this in mind and you can see how changed over time, the more I got out of my head, the more detailed I could then be, I ended up making it succinct and slightly more generic. My next step is to break down my goal into manageable chunks. When things have broken down, everything seems easier and relatively simple. These chunks are part of my action plan. What's important to understand is that I didn't create the whole action plan at once. My next bit of writing may end up looking something like this. Track mouse X using mouse move events. Compared mouse X to screen width to create a fraction. Connect that fraction to an elements X range. Do this for each elements and apply a depth. Then for each point, I might break it down even further. The track mouse X using mouse move events, I may make some notes like this. One, add event listener, two, create a name function, handle mouse move, maybe three, create a variable that stores event X inside of handle mouse move. There we go, you can see how I am writing this all. I don't have to do everything all at once. What ends up happening is that these lines can become comments in your JavaScript, which you can then follow really easily. There like your pointers in a maze, as you get better and better, you may find yourself skipping parts of the planning. That's perfectly okay. What's really important to remember is that at any point in time or any point in the process, you can make a plan. Just write out what you want to happen in point form, either on a Javascript comment, or on a piece of paper on a regular text documents. I have a massive pad on my table most of the time, so I can just quickly make notes, I can quickly plan. Breakdown what needs to happen in English or whatever language you speak best, and then write the code for it. The second type of planning I do is putting pen to paper or pencil to iPad. I draw things, I work things out, I draw the documents, I draw with a screen Canvas as I draw with a mouses, I draw elements. I draw everything I can and then I start putting fake values into places. My mouse X and my screen width, my output range, and then I start making calculations. I represent unknowns with Ys and Bs and Xs. I make the calculations legible and preferably in JavaScript or something that can be easily transferred into JavaScript. Then I try the same drawing with different values, I see what results I get and then try the interaction at different stages, when my mouse is all the way on the left, when my mouse is in the middle, when my mouse is all the way on the right. Then once you think you know what's going on, replace the made-up values with variable names. These planning sketches are golden, it's like you had these moments of brilliance, these lucid moments where you're just a genius, which you record. You put pen to paper, you do all your calculations, and then you use a later where you're not, feelings are brilliant. There's a very small chance you can remember all these calculations in your head as you're coding. I find it best to write it down and then transfer to code. What's great about planning is that it doesn't need to be perfect and you don't need to do it all at once. You can iterate on it quickly. You can show to people, you can improve on it and you can jump back into it whenever you get stuck. You can use a mixture of writing and drawing when ever you want.
10. Capturing Scroll Position: Now that we've created our first parallax experience, we can get into creating a scrolling parallax experience. This is really fun to create and most people are totally mesmerized by them. What do we want to achieve though? The first thing that I want to achieve is, I want to create a scrollY input fraction value that I can connect my output values to. The second thing I want to achieve is, I then want each of my elements to move in the opposite direction to the scroll direction, but proportional to their depth. The further away an element is, the quicker it will be moving this time, but in the opposite direction to the scroll direction. The only thing we need to watch out for before we jump into code is that the maximum we can scroll is actually the document height minus the windows height. Let's remember this when setting up our scrollY input end value. Let's jump into code. Let's start by making our documents, scrolling document. Let's jump into our HTML here. We can create some things called parallax-container. There we go. I'm just going to indent that code. Let's paste that and we can copy and paste parallax container like so. That's good. Then, we can give this one an alt class and this one an alt class, so we can change the background colors. Then in the CSS we can paste this and give it a height or a min heights of 100 VH, which is 100 viewer height. We can say.parallax-container.alt and we can give this a background color. What shall we choose? Let's go for assets. Let's choose a really light green maybe, perhaps a much darker green or we could even go for array like pink. Here we go. Let's paste this over here. Now as we scroll down, there'll be green and pink divs. Just shows us how much we scroll. We also got this scroll bar on the right-hand side. There we go. Now we've got a document that scrolls. We can also add all of these parallax items into second parallax container. This will mean that as we scroll down, where are they? I have no idea. That's because we haven't put a position relative onto our parallax container. As we scroll down, there we go. That looks really nice. The colors work really well together. We've just got one and two divs with our leaves in. Now we've got our mousemove working. I'm going to comment that out for now. Instead of listening for a mousemove, that's actually not going to work anymore. We're going to start working with an event listener that listens for a scroll event. How do we do this? Well, instead of listening for a mousemove on the window, we're going to say document.addEventListener and we're going to listen for a scroll event and we'll say handlescroll. Then for our handlescroll equals a function. All of this should look fairly familiar. Let's just log something to make sure that this is actually working. Scrolling. Let's open up our console. As we scroll, we're getting a bunch of scrolling happening. Now how do we know how much we're actually scrolling? That's a really good question. The way we're going to do that is we're going to work out var scrollAmt equals and we're going to go for document.documentElement.scrollTop. Let's see if this works. We're going to say scrollAmt and scrollAmt. We'll open up our console again. Let's clear that and as we scroll, here we go. Our scrollAmt is coming through. The latest one is zero. As we go all the way to the bottom, it's 951. This is our scroll amounts. Perhaps we can now figure out what our maximum scroll amount is. How do we do this? Well again, we're going to use this document.documentElement. We'll say scrollMax equals document.documentElement.scrollHeight. We'll compare it like so. There we go. Let's scroll this. The scroll max is 1268. This is not really working out, is it? But remember, the height of the document isn't going to be the same as the scroll amount because we've still got our window height to a countful. Let's do minus window.innerHeight. Let's scroll again, 951, 951. There we go. We have our constant value, we have our end value. Now we can take these values and creates an input from them. I'm going to just copy them for now. Let's just give ourselves a bit more space. We'll go up to our input values and we'll say scrollY and we'll create a new object here and we'll say start. Our start is going to be zero. We can change this to some value besides zero. But in this case, we want to track our entire document's scroll position. We then going to have an end value, which is going to be, our scroll max. Well, all of that. Now this is really, really long. What we can do here is say var and we can say, HTML equals document.documentElements. There we go. Then we can replace that and that. Our end value, it's going to be that. Then our scrollAmt, this is going to be our current. We can actually work that out a bit later. Current will be zero in the beginning. We also need our fraction and our range. We'll workout our fraction a little bit later, and we'll work out our range just beneath the input. Let's go for input.scrollY.range equals, and then we can just copy and paste this. ScrollY.end minus scrollY.start. Which will give us our range. Now what's really important about the range is it will change as soon as the scrollY's end value changes and the end value will change when the browser resizes. Let's update that value. If we go down to the resize, the mouseX, mouseY. Let's go and put.scrollY.end. What was our end value? Let's scroll up here. Copy and paste this. Scroll all the way down again. Our end value gets updated and then our range value also gets updated. Let's copy the scrollY range calculation and let's paste it over here. Now we're seeing handlescrollY. We've got the scrollAmt, which is now actually going to be our input.scrollY.current. This is going to be our html.scrollTop. Then our input.scrollY.fraction is going to be what? In this case it's going to be our current divided by the maximum, so input.scrollY.end. But remember our previous calculations, if you can just look a little bit higher over here, update inputs, is our input mouse fraction is our mouseX.current minus our mouseX.start divided by our input mouseX range. We're going to copy this format. Let's go down here, handle scroll and we're going to copy and paste this. This is just more accurate as soon as we start tracking our document from a nonzero position to a position that isn't the total height of our document we'll need this to calculate the real fraction. Our scrollY.fraction is going to be the scrollY.current minus the scrollY.start, which in this case is just zero and we're going to divide by the scrollY.range, which in this case is also going to be the scrollY end value. That's handling the scroll. But now you may be like, well, why is the other one inside of update inputs coming up with that in there. Of course, we can. Let's do that. Let's copy and paste, update inputs to our handleScroll. There we go. We'll just cut this, take all of this out, and we'll put this into our inputs. There we go. Our input is now coming through. How do we now connect it to an output? We're going to update our outputs. Right now I'm just going to comment out our outputs so that nothing will work at all. It's not working anyway. What we can do here is we can just update our Y position. Our output.Y.current is our output.Y.end minus our input. We can go scrollY.fraction, multiplied by our output.range. Let's see if this works. As we scroll, is anything happening at all? Are you noticing anything? No, I'm not noticing too much. Anything happening here? Well, what about update outputs? The Y.currents is working? Yeah, it should be working, but remember we actually have to call update outputs. Let's copy this or let's copy update outputs and update each parallax item. Let's put it after we call the update and put function inside our handleScroll event handler. We can also just cut this and perhaps put it just here so it's a little bit closer to our handleMouseMove event handler. There we go. Now, let's see what happens as we scroll. Things are happening. You can see that the parallax is certainly working. We've got some blur going, We've got some scale going, and it's all related to our scroll position. We have achieved what we set out to do in this video. We've connected an input to an output using our scroll position. It's looking really good. There is a couple of problems with this so far though, we're going to cover this in the next video. I'll see you there.
11. Unique Input Values For Each Element: Our parallax experience on the last video is looking pretty good. But if you look closely, something's not quite right. I'll show you. If I go all the way to the bottom of my document and I comment out these update inputs and update output functions, and I stop listening for the scroll events. You'll see that all of my leaves or all of my parallax items, they're centered in the middle of the page. Then, if I scroll down a bit, so are these ones. Now, when I come in back in my code over here and my code over here, you'll see that all of the parallax items are at the bottom of the page. Why is this? Well, there's going to be two reasons why this happens. The first reason is that when we scroll up to our output.y current calculation, you'll see that we start with the y.end. Basically we're saying, let's start with the y.end and then as the fraction value increases, so we'll get closer and closer to the start value. Instead we want to say it, let's start with the start value and as the fraction value increases, let's get closer and closer to the end value. This is looking a little bit better, and now if we scroll up a little bit more, we'll see that when we define our start value, we actually started at minus 150. We're going to start this at zero. Now, everything should start at exactly the right place. When we scroll down, we'll see that these items in this pink container, they don't start in their original place. That's all we want to achieve in this video. When we get to an item or when we scroll to an item, we want it to be in the original position. The reason for this is that, these items are moving based on the scroll fraction from all the way at the top to all the way at the bottom. What I want to say is, I only want the scroll fraction to be zero about here and one about here, rather than all the way at the bottom and all the way at the top. I don't want the outputs of each item to be based on the whole document scroll position. I want it to be based on when it's visible. The question that we need to ask is, at what scroll fraction should an element be at its original position? Because at the moment, they're only in their original position when the scroll fraction is at zero. So how do we work this out? The key lies in our update each parallax item function inside of the items array for each loop. Now for each item we're actually going to create its own input, so item input. What we could do is we could actually hard code every single input for every single item, this will take hours. We're going to use some code to work it out for us. Now, our item input, we're going to have yScroll, and inside our yScroll, we're going to have a start and we're going to have an end. We'll update these values in a second. The next thing we need is a range, so if we scroll up here, where do we actually work out the range? Well, it's output, here we go, the scrollY.range, so let's copy that and let's bring it down here. Instead of saying input.scrollY.range, we're going say the iteminput.scrollY.range and the iteminput.scrollY.end, minus the iteminput.scrollY.start. This is really important. This means that we can specify a start and an end for each item. Right now we can hard code a value. Instead of being zero we could say, at 450, this is where I want my zero fraction to be and my end fraction, I want it to be at 800. When I scrolled 800 pixels down the page, I want my fraction to be one, and when I've scrolled 450 pixels down the page, I want my fraction to be zero. Let's start logging out some values. What I'm going to do here is I'm going to go into my HTML and I'm going to comment out a whole bunch of these divs, just that we have one div to work with. That means we'll only get one set of logs coming through. So as I scroll, is this working? Doesn't really looked like it, perhaps it's not scrolling that well. We can just double-check that there's no errors. There are some errors, so we just click on this. We'll say, iteminput.scroll.end, that's because we spelled scrollY differently to yScroll. Let's just change yScroll to scrollY, there we go. As we scroll down, we'll see that our leaf is doing some slight movement. What we've got here is, we've got our scroll range. What else do we need to do now? We need to work out our fraction value. Where do we work out our fraction value? Well, we work it out over here. We've got our scrollY fraction, so let's copy and paste that, and we'll say iteminput.scrollY.fraction equals, and this is really important. We still going to base it off the global input.scrollY.current, which is based on the pages scroll, but we're going to say minus the iteminput.scrollY.start, and we're going divide it by the iteminput.scrollY.range. Super important. The next thing that we need to do is we need to figure out a new output. At the moment we're using the global outputs and we're doing some calculations here. Let's go to our outputs, and we'll see that outputY.current is calculated over here. So we'll just create a new variable here, and we'll say if our itemOutputYCurrent, because we've got an itemOutput already. The fact that we only need one value means that we don't have to use an object, and here we can say outputY.start, which is great because we're going to still use our outputY.start and end values, and then instead of the input scroll fraction, we're going to go for the item input scroll fraction. So we've got our itemOutputYCurrent, now we can apply it to our y value down here. The thing is that, our output.y.current, currently is a little bit inaccurate. If we scrolled down, and perhaps we can just comment these elements back in. As we scroll down, you can't really see it that well here, so let's increase our end value to something like 3,000. As we scroll down here, you'll see that the items that are further away are actually moving rather quickly. We don't really want them to move quickly or appear to be moving quickly. If we change this to 1,000, perhaps you can see it a little bit better. As I scroll down, I don't really want the items that are further away to appear like they're moving faster. Like we said in the previous video, I actually want the items that are further away to move quicker in the opposite direction which means as I scroll down and the document moves up, I want those items that are further back to move downwards at a quicker rate. Let's try this out. Down here where we working out our y position. Instead of starting with the y currents and minusing the y current multiplied by the depth, I'm just going to start with the y currents and multiply the depth. This means that the deeper it is, the quicker it's going to move. Let's try this out. As I scroll, anything happening? No. That's because we're still using our output y current. Let's use our item output y current, and this is going to be per item. There we go. We're going to start at a range of 450 and end at a range of 800. Now, as I move, you'll see that things are looking a little bit better, and because we're scrolling between 450 and 800, we don't need to use this massive value over here, so we can change this back to 300. As we scroll, there we go. Things are looking a little bit better. If we change this to 500, perhaps we can see a little bit more. As we scroll, you'll see that the top item is actually going with the page as it scrolls up. Then the items that are further away are actually moving downwards as we're scrolling downwards. The page is going up, we're scrolling down and the items that are further away are scrolling down, moving down at the same speed or quicker than items that are closer to us. It's a little bit complex. Now let's go back to our loop. What's happening here is that we're setting the start and the end. I'm just going to comment out these two sections again. We've just got one leaf or one parallax item. We can actually do some console logging here. I'm going to copy this. I'm then going to go to our input. I'm then going to log our current scroll. Let's go for scroll and then I'll copy this and paste this. Let's open up a Console and then we don't want the depth anymore. But what we do want is we want the fraction. Let's log this. There we go. As we scroll for this item, when we're over here, you'll see that the fraction is a negative 1.26. Weird? But check this out. As we scroll and you'll see that the scroll position is increasing, you'll see that the fraction value is really close now. When we get to a value of 450, there we go. The fraction is zero. When you get to a value of 800, you'll see that the fraction goes to one or just above one. This means that It's moving between the start and end value that we've specified in our output. As moving between zero and 500, between a range or a scroll range of 450 and 800. This is super, super cool. Now we don't want every single item to start at 450 and end at 800. We want to start where it's visible and end when it's not visible. How do we do this? Well, one of the best ways that we can do this is say, item.offsetParents.offsetTop. An offset parents is really important. In our CSS, you'll see that our position relative is declared. This means that this is an offset parent. It means that anything that has a position besides static is an offset parents. Inside our parallax container we have our parallax items. A parallax item, will say, "Who's my offset parents?", and the parallax container will say, "Me, I am." Then we'll work out the offset top, the distance from the parallax container to the top of the document, and that will be our top value which is pretty cool. The next thing is sitting on end. We'll take this and we'll make it our end but we're going to add the window.innerHeight, like so. We're going to say, we're going to start at the offsetParents.offsetTop. The distance between the offset parents and the top of the document and the end is going to be that distance between the top of the parents and the top of the document plus the window.innerHeight. Pretty cool. Check this out. As I scroll, I should get to about here, which is a fraction of zero, scroll position of 319. This is where our parallax item is going to be. Let's close this, and we'll do exactly the same here. Check that out. Pretty cool. If we just undo and undo, basically commenting in all of our parallax items. Now, it's going to start in the middle here. As we scroll down, you'll see that when we get to this position right here, hey, it's also going to be in the center exactly where we set it originally which is fantastic. If you don't want to use the offsetParents.offsetTop, that's okay. But what's really important is that you use something that doesn't change its position because if you're dynamically calculating the start and end values and you're basing it off of something that's changing its offsetTop, things can get really, really messy and confusing really quickly. This way, if we just have to copy and paste a bunch of this code and put it into our next parallax container and our next parallax container. We can change a bunch of these values. We can change this from asset one to perhaps 60 and 61 and 67. Let's go down here, I'll change this to 2-1 and to zero. We'll change this to 11-21-41. As we scroll down, let's see what happens. All right. They all appearing in exactly the right place as we get to the offset parent being at the top of the screen which is fantastic. That's really cool, and I'd encourage you to use that offsetParents.offsetTop to get things to be exactly where you set them originally. Of course you don't have to use scale and you don't have to use blur. They just make things look a little bit more realistic. That's basically all you need to know about scrolling parallax and using the parallax effect with a mouse move events. Well done. I'm going to show you a few more things before I actually code up an entire experience, that's not just examples. Sweet, I'll see you in the next video.
12. Using Mouse And Scroll Position: You may be wondering whether you can use the mouse position and the scroll position together to change the Parallax effect. The answer is, yes. In this video, I'm going to show you how. If we scroll all the way down to the bottom, we're going to uncomment our piece of code that we commented at. We're basically saying, "Let's listen for the mouse move event again". Luckily, we haven't removed any of our code. We just need to move up here. We can just comment this back in. But our y.current has been changed to make it work for the scroll position. What we're going to do is, we're going to go up here and we're going to put in a new value. Let's put in an object like so, and I'm just going to copy the start and end current from x, and the y we're going to call scrollY. Now we need to create and copy and paste a bunch of the values that used the y position throughout our code. Let's start off over here. We can say scrollY, and we'll just update that. Then got a bunch of inputs, which is great. Then our output over here, we can update input scrollY, output.scrollY range. Then we've got our output.scrollY start, output.scrollY range. I think that's about it. Fantastic. Let's just double check that this is moving. You can see this is responding to our mouse move on the x-axis and it's responding to our scroll on the y-axis. Now what I want to happen is, as I scroll up and down, and as I move my mouse up and down, I want the y-axis or the vertical axis to respond to both. How do we do this? The key lies in this piece of code right here. This piece of code that I've just highlighted, this is our scroll piece of code. The next thing that I want to add here is some code that we removed in the previous video. I'm going to say output.y.current, and perhaps you can just make sure that this is all braced off so that we know that these are separate. Output.y.current, I'm going to say minus, and brace this again, output.y.current multiplied by depth. We've got our scroll value over here, and then we've got our mouse value over here, and we're adding them together. Check that out. Now as I scroll, looks pretty good. Nice. Sometimes this parallax items encroach on the other parallax items areas. A really easy way to fix this is to go to your CSS, and we can say parallax container, we can just set this to overflow hidden. Just like that when we scroll, it just hides behind. There we go. That's how you use mouse position and scroll position in the same document. It's really cool, really fun to use both of them at the same time.
13. Other People's Code: Let's talk about using code that you did not write. This could be using a plugin, using some code you copied off the internet, or using something like jQuery. A lot of plugins and frameworks are simply amazing. They're made by super clever people and it makes our lives a lot easier. It's like outsourcing part of your coding to somebody else. There are plugins made for developers and plugins made for the general public. Plugins for developers make coding easier and more standardized. They also tend to focus on specific parts of the process and let you handle the rest. Plugins that are made for the general public or plugins that say, "We do it all!" and generally quite skeptical, and you may have to spend hours reading their documentation and guidelines to get anything working. The downside to most frameworks and plugins is that a lot of the time you won't need to use all it has to offer. This is the equivalence of buying a tool set and only using a hammer. Also, if the plugin you're using doesn't do exactly what you want, then you're stuck. You will have to start from scratch. All you have to do some hack-work which often ends up taking way more time than good planning and hand-written code. Then there's code written by other people. You can find this kind of code on medium, in blog posts, on Stack Overflow, wherever. Sometimes this code is fantastic, nothing wrong with it, it's amazing. Other times it's not great at all. The best kind of code for you is the code that you understand and you make sure that it works for your project and your browsers that you're trying to support.
14. Putting It All Together: I've shown you a bunch of stuff, many about inputs, outputs, and the parallax effect. Now it's your turn to create something. Don't pressurize yourself into creating a big website using everything you've learned in the class. Take parts of what I've shown you and make a small project or make a few small projects, or just work on it daily. When you're ready to share it with your mom, with the world, and with us, then send through a link of something you've made. It can be on CodePen or it could be hosted using Surge, GitHub Pages or even your own website. If you need help, remember to share a link to your code. In the rest of this video, I'm going to create a little project of my own using a few things that I've taught in the class. I've included this to show you that I'm not perfect. Development is hard. You'll see that I made mistakes and that I sometimes forget pretty important things. But I hope this shows you how real development happens and I hope this inspires you to create, to play, and to experiment without the pressure to be perfect. I'm going to have a quick look in my planning and what I've got is a container with a bunch of different leaves in it. All of these leaves are going to be parallax items. They're going to have different depths. They're going to be a bit blurry at times, but they're not going to be scaled. They're going to have maybe a random width and height, and every single leaf is going to be randomly generated by JavaScript because I do not feel like putting in, that many leaves inside of my HTML and I definitely do not feel like styling them. They're going to have a random rotation, a random blurriness or a random depth, and they all going to be parallax items. Then on top of this container, there's going to be a parallax plants with an e-mail inputs and a sign-up button and that's going to be it. Let's get cracking. What I've got is I've got a couple of color values that I really like. Let's just start off with this body. I want a dark body, so maybe let's go for black, bgc, can be black and also I'm going to set a margin to zeros. There's no margin around my body. Let's get an example, leaf going and its of a parallax container. Inside my parallax container I want a parallax item, and then inside here I could have an image, but I'm actually going to put the image on the background. Let's go for.leaf. Then it's going to have a random background image. But we'll do this all in CSS, parallax item and parallax container. Lets copy these into my CSS. Like so. This is going to have a width of 100 vh and then height of 100 vh, my width would be a 100 vw actually. So 100 vw, a 100 vh for my parallax container at position of relative. Then my parallax item will be at position absolute. Then for now we can have a width of 300 pixels, height of 300 pixels, and we can have a margin top of minus 150 pixels. No, I don't think we actually need that, we just need that. We've got our position, we've got our width, we've got our height. What do we need next? Position absolutes, perhaps you can just say, top of 50 percent and left of 50 percent. Top, left width, height. Let's go for our leaf and this can have a width of 100 percent and a height of 100 percent. It can have a background, and the background is going to be a URL. One of the assets is going to be one of these leaves. Let's just copy this one, paste it in there, and it'll say center no-repeats and then background size can be contain. Already I like that. Let's just double-check that this is actually what we want. Let's go for a background color of yellow. Yeah, that looks cool and then my parallax item, top 50 percent. There we go. That's cool. We're going to randomize the top and the left of every single item. They're all going to be about 300 pixels high and wide. We can change that to make them bigger and smaller. You can take this away. Now, let's get into some Javascript, but what I want to do here, well, I want to set up all of my leaves. What I'm going to do here is I'm going to randomly generate a bunch of different leaves and splotches, whatever. Let's go for a bunch of arguments. Let's do something. Let's go var i is equal to 0. Then I'm going to say, while i is smaller than, let's say 10 for now, then I'm going to say i plus plus, which means it increases in value. Perhaps you can just close this, this is not so much jarring as we're typing. Inside of here, what do I want to do? To write some comments. Well, first of all, I want to create a new elements, create new leaf for inside elements, then add element to container. Then after that, I want to say random width, height, depth. What else do I want, rotation, background image. Then adjust blur on depth. That looks pretty good. What I'm going to do here is quickly put an id onto this div and it's going to be parallax container. I also want to add the class names. Let's try this. What I want to do here is say var parallax container equals document dot get element by Id and this is going to be my parallax container. Create a new element with a parallax item class name. Let's go for document dot create elements, and i want to be a div and we're going say var item. Then what we're going to do is give that item a class name. We're going to do the same thing here, so we're going to create a leaf and say this is a leaf. Then we're going to add the leaf to the items, so item dot append child leaf then add element to contain. Parallax container dot add append child and we'll put in item. Let's see if that works now. I've got two here. I've got a bunch of leaves happening here, that is fantastic. The next thing I want to do is just double check that these are all actually positioned absolute. Looks like they should be. Let's just right click and inspect leaf. All the leaves are being added to the parallax container and there's just one parallax item. Saying create element, which is an item document dot create element div, the item class name is leaf. The item class name is parallax item, leaf dot class name is leaf item append child leaf and then parallax container pinch alt item. If we right click on this one now, we should see a bunch of parallax items all with leaves inside of them. That's great. The next thing I want to do is I want to get a random width, height, depth, ratio, background image, all that stuff. Let's go for item dot style dot width equals 300 height. Let's go for depth, rotation and background image, so height. Then we're going to go for depth then rotation, so this one will be depth. This will be a dot data set dot depth, then we're going to say rotation. This won't be there, it'll be transform and then the final one will be a background image, so background image and we'll get this background image over here. Then we need a random number, so I'll create var random number equals math dot random. Then our width is going to be, let's go for 600 multiplied by the random number, which will give us a value between zero and 600 and then plus 300. If it is zero, then it'll be 300 or maybe you can say plus 200, and maybe we can say this one's 500. Obviously, these are going to be worked out first, so let's just give them some braces, the depth is going to be a random number, and that's just going to be between zero and one. Then I'll transform. What do we want here? We want something between 0 and 360. Let's go to 360 multiplied by a random number and then our background image, we want one of these between 1 and 91. Let's try it out. For my bgImg image number, I want my random number multiplied by 90. Anyway, between 90, but I'm going to say, well, let's just see what that is actually. Let's just put in two for now, bgImg image number. Let's open up our console, so we're 64 point whatever. What we can do here is you can say math dot round and this will give us six. Fantastic. Why don't we just log this out? Console dot log bgImg number and this should give us a bunch of different bgImg numbers. That looks pretty good and changes to 91 I think, it should be okay. Then we can put our bgImg number into here and we could have done the same with this calculation here, maybe we should try that. Let's go and put this up here. Let's take this away and let's say rotate number and copy and paste that. We can do the same with all of these actually, but sometimes it's unnecessary. It doesn't look like I'm getting random plants, no it doesn't really. Does background image actually exist? Right click here and inspect parallax item, that's because we need to put it on our leaf. Let's say leaf dot background item, see if that changes anything, div dot style dot background image. Dotted depth, transform rotate. Perhaps we need to do some research about how to put a background image onto an item with JavaScript. Let's go for JavaScript background image. Background image. Because we didn't put a URL in. Let's try that. I'll say URL, and like some or like so. How about that? Don't understand what you're saying. All of this URL, one of these, let's just put that there. It looks like we have some random background images. Fantastic. Thanks so much W3 schools. Boom, what's next? Well, we need to work out our blurriness. Let's go for item.style.filter equals blur of 20 pixels. There's a whole bunch of blur happening there, and we've got our depth already. Where is our depth? Here's our depth. Maybe we can say var depth equals randomNum, and we can say, okay, what is I'll blur value? Var blur equals our depth. We need a start value here, so I'm going to say output.blur.start, and then multiply by the output.blur.range. Now, we obviously don't have these values, so let's set them up. It's going to say set up output and the var output equals, and our output is going to be blur, and we're going to have a start of 0.2 and the range of 20. How about that? Output blur start and range. What happens if we change this to five? Then what happens? If we have to say start at one, I'm expecting all of these to be non-blurry. That's not working. item.style.filter blur 20 pixels, that's because it's all just 20 pixels there. Let's change this to a blur value. There we go and we can put out blur appear with all the other variables. Let's change our start to 0.2 again and our range to 20. Hopefully, we'll see some of these being blurry and some of them not. Then maybe I can change my width to, I don't know, 50. Between zero and 500 and yeah, the minimum will be 50. Item.style.filter blur, you can put that up there. That looks pretty good so far. What else do we need to do? I've got a blur, I've got a randomly for spludge, I've got random width and heights, I've got random depth and blur. Now, I guess I need a random position. I don't think I've put that in actually. Let's go for item.style.top equals and we can say, where's this randomNum multiplied by, and we can say window.innerHeight. Cool, and then window.innerWidth for my left value, and then we're going to just add a pixels to that. Then we may need to round this. Not quite sure, but let's just do it anyway just so that we don't get any point values. Let's inspect this. Now, we have transformed filters to top left. A bunch of stuff happening. Well, that is fantastic. But maybe we can also just say Math.round minus 200 also, and that's just so that the item is go a little bit to the left and a little bit to the top. Otherwise, they always go to the right and the bottom of the page. Then we can also put a overflow hidden on our parallax container so that we don't have any scroll bars. We've got random positions now I think we need to make them move. Let's make them move. Let's set up our input and share. Perhaps we can say setup HTML. We're going to add the semicolons as well. Our input is going to be mouseX and mouseY. Then we're going to have, I'll start at zero and I always do that window.innerWidth, and then our current. We can just start at window.innerWidth multiplied by 0.5, and then we need a range which will work out afterwards. We can just copy and paste this. Then we say input.minusX.range equals input.mouseX.end minus. Let's just copy and paste that. Start. These things are freaking me out. We've got our input setup. Now, what's next is we need to do our event listeners. So perhaps we can just hide this for now, and we can say window.addEventListener, and we can say mousemove, handleMouseMove. Then we can also add a resize, resize handle. Resize and don't quite know why I spoke handle like that. But I did handleMouseMove. We can say handleResize. What needs to happen in our resize. We need to do our range. I'll end our range, that's good. Then I'll handleMouseMove. What happens in now handleMouseMove? We need to do input fraction and current, and then outputs current and then apply to HTML. Let's go for our updateInputs, which is a function, and we can just copy and paste this and say updateOutputs, like so, and then we can say updateParallaxItems. We can just copy and paste these, fantastic. What we first need to do in update-inputs is, currents and our fraction. Let's do that, update-inputs. What we are going to get is, get our events and we say mouse dot x equals event dot client X. We haven't set up our mouse yet, so we can't do that. Var mouse equals 0 or perhaps you can say, window dot inner-width multiplied by 0.5. We can copy that for our y-value and say inner-heights. If we just cut this and put it at the top, we can actually reference that, so it's a mouse dot x and mouse dot y. The next thing we need to do is copy and paste this, mouse dot y is our client Y. The next thing we need to do is, we're cutoff fraction values, so we go and actually this doesn't go here, this goes down here, and this goes down here, there we go. Then we can actually update our current values input mouse X dot current equals mouse dot x, and put dot mouse Y, the current goes mouse dot y. Then our fraction value, input dot mouse X dot fraction, and this equals current minus start divided by range. We put these inside of braces, and we change this to mouse Y. We've done our inputs, that's great. Now outputs. What are we going to do for our outputs? Well, we need to do are x and y. Let's go for output dot x. Do we have an x yet? No, we don't, so the scale for x, and we'll have a start of minus 150, and an end of 150, and then a current of zero. We'll copy and paste this, and change this to y and then we'll just copy and paste this, and changes to x, x, x and this to y, y, y, and this to output. Already. We've now got our x and y output. The next thing we need to do is actually carry on here and say, dot current equals, and our current value is going to be input dot mouse-X dot fraction multiplied by output dot x dot range. Pretty cool. We probably don't need to do this, but I'm going to do it anyway. It makes life a little bit easier, so y-current mouse-Y fraction, and output dot y-range. Now we have put our outputs. The next thing is, we need to apply to the HTML. What I've done up here is, I've set up the HTML, but I haven't added it to an array. Let's say, items-array equals a blank array. Then what I want to do is, var item when I create it, and I do the class-name, and I'll say items-array dot push, and I'll just add this item to that array. Then I can reference it later, so items-array, let's go down to here. Items-array dot forEach, and inside of this forEach provide a function item and k or item and i. Then what I can do is, I can create a var item-Output equals an object, and there'll be an x, there'll be a y. That's actually going to be it, just my x and y. Then I'm going to say item dot styles dot transform equals translate, and then we'll say 20 pixels, 20 pixels. Then I'm also going to have a depth, so var depth equals item dot set dot depth. I'm going to say parseFloat. We probably don't need to do this because we're actually generating that number up here. We could store that on the item itself but I think this is just a nice way to put it into HTML, and bring it back just to cement what you guys have learned during the class, so that's our depth. We're just going to put in that 10 value. We got our depth, we've got our item-Output. Let's make this dynamic. We'll start with our output dot x-current and then multiply it by our depth. Then things so, somebody looks a bit off. I think I might have to do with this value up here. I think I might actually have to start with output dot x dot start plus this value. That looks about right and then we'll do the same thing over here. Since this will be our y value, still put braces around here. Then our x would be our output-x dot current [inaudible] currently is, multiplied by the depth. Let's double-check. Now let's copy and paste this. Output-y dot current, it's pretty much the same thing. Then we can put this to dot x and then copy and paste all of that. Say item-Output dot y. Hopefully that should work. A whole bunch of stuff not happening, doesn't look like it's even recognizing that I am moving my mouse, so let's go to View, Developer Javascript Console, cannot set property transform of undefined. That's item dot styles. Styles definitely doesn't work, so let's go for item dot style. Save my pen, so things are working here. Can actually remove this, so we'll just comment this out. Looks like there's much rotation happening here. Let's check out our rotation. Our rotation I think isn't working, because we've set it to our item. When we went for this rotate, every time these images move over here, it means that overwrites that. Let's change this to our leaf. Perhaps we can just pour down the blur a little bit. Let's go to output blurred, lets make this 10, and change this to five. Then where I set up my HTML, I'll just maybe change this to 50, this is now going to be 50 leaves and splotches and whatever else. It doesn't really look like they're randomly positioned. It looks like they're just position from top left to top right. It's weird. If we go for top and left, innerHeight, innerWidth, yeah, that's just weird, so let's maybe log this, say i, dimensions, I will just go for top and left. So let's go for our Developer Javascript Console. The problem is that, what's happening is, as the items increase, so the top and the left values increase, giving it like this really even spread from top left to bottom right. So what I'm going to do here is, instead of relying on this random number over here, I'm just going to copy and paste that and using unique randomNum for the top left, the transformation, the width and the height. Actually I'm just going to use Math.random all over the show. So we'll say, rotateNumber. Let's put that down there too. So, randomNumber, do you exist anymore? Depth is still randoNumber. Or we can just change that and that should be it, no more random numbers. So we now have a bunch of leaves, which is pretty cool. They move a lot something doesn't seem right here. What is the matter? Well, I think it has something to do with the our current that we starting at the start, and then we're saying the mouseX. fraction, multiplied by the range starting at the range. So perhaps can say end - and end -, and see how that works. Then our x is our output x.current multiplied by the depth. That looks a lot better. Pretty of that. Let's change our blow values again. Start at 0.5, well say start at 0.35 and our range could be up to16, and the only thing we haven't done is our Z and X, So we need to do our Z. So we can work this out and say var zIndex equals our Z range. So we can say, output.z.range, which we haven't set up yet, minus our depth multiplied by output.z.range, let's go and do that. Ten thousand, that looks pretty good. So range range. Now let's set it item.style.zIndex equals zIndex. So do you see what happened there? Resizing things not really working that well. Let's update that. So on my resize and in range, let's go for input.mouseX.end equals window.innerWidth. MouseY is innerHeight. Then we can copy and paste not our output, but our input ranges down here. Let's see if that works any better. That's looking pretty good. It is a bit of a mess though. So maybe I could select my images a little bit better, or perhaps we can just reduce the blur again. Some of it here from 0.2 and let's say 10. Yes, it is quite random as to what pops up, and I bet you if I took all the blur off, it would be a lot more performant. So if we go and find the blur. So style.blur or style.filter, this one here. Just comment this out. That feels a lot better. I wonder if I can change this to a percentage, the top and left rather than being actual pixels. So let's change this to a percent. So Math.random multiplied by 100, minus, let's say 10, and this means that it will work no matter what the window height and width is and if it gets resized. Let's change the amounts of elements that we have to like 100 or something. Maybe we can even say minus a little bit more here, so minus 20 percent. Yeah that's looking pretty good. I'd like to see how many leaves I can actually put in here. Maybe let's go for 150. It's like a flipping Jungle here, yeah that's really cool. Maybe we can just lessen that score 130. There's lots of movement happening here. What I need to do now, I need to put in the rest of my HTML. Let's go for parallaxContainer, and on top of this, I'm going to put in my form-container, actually I spell container right. Inside here I'll have a form, and inside my form, I'm going to have an input with a type of text. Don't really need a name id right now. Then an input type of submit. We say, Sign Up and can give as a placeholder value of, Email address. Outside our form we can have an h1 saying, Parallax Plants Newsletter and h2 says, Please sign up. Now we can just style this. Let's go for our form-container, and we'll say width is 100 percent. We'll say height is 100 percent. Or maybe we'll just say 100vw and 100vh. Then we'll say position absolute and top zero, left zero. We can also then set at display flex and say justify-content, and we'll say center and align- items also, center. Then I will say, flex direction row can change that to a column. Then in my body I can say, font-family. I would like to be Open Sans I think. Open Sans great. Then my h1, let's just give it a color of white. We can say text-shadow 0, 0, 10 px, rgba 0, 0, 0.5. Perhaps we can change this to 4px and this to 20px and we can make this even darker 0.8, yeah that's great. I can say font-size of 50 px, maybe 40 px, and then our h2 can pretty much be the same thing. Except it will be 20px. Can change the margin to 0. The margin to 0 too. Then our form, same margin-top of 20 px. Then our input and say type = text, and our input type=submit, and here we can do the same thing as our form-container. We can also just set the display type to flex inside of our form. Center center but we can go for row here. Yeah, like so, say border, none, and say outline, none. Say box-sizing, border-box can say padding is 10px, and that looks pretty good. Maybe 10px, 20px or maybe we can say 10px, 12px like so. Or maybe we can even just give this a height of, say 40px. Our submit can have a height of 40px. We can also say bg or we can say border of none, outline, none, cursor pointer. My background-color, scroll down to get some nice colors here, I want the Pink. Let's put that in and then give this a padding of what do we say here 10, 12. Maybe you can give us a bit more. Fantastic and then font-size can be 16px. Same thing here, and our color can be black and font-weight can be bold. Our color here can also be black. That looks pretty good. What I would like to do is, I would like to see if I can add a drop shadow on the leaves without making it super slow. Let's go filter and drop-shadow. This might have to be inside of quotes, but let's just double-check and we'll say 0, 0, 0, 0.5. Did that do anything at all? Don't think so. That do anything at all? I don't think so either. Filter and drop-shadow, drop-shadow like that. No I don't think so. What about CSS filter drop-shadow, drop-shadow oh no comments. How about that? Working at all? This one, it is working but it is super is low. Let's take that out quick before my computer breaks. We're back over there. I guess with the blur and the drop-shadow, things aren't so performant. Then we have our Parallax Plants Newsletter, sign-up. As you move your mouse all of these plants move. There are some weird plages in our characters here and there. But it's pretty cool. All of this is just really easy to change and setup. We can change this to something like 300 to make it even more responsive. It looks pretty fun. That's my Parallax Plants Newsletter. Have fun creating yours. If you want to change the view. You can go to, I think Full Page. Still has this little bar, perhaps you can go to Live View. Now my images are massive, that's why it's taking so long to load. But this is pretty cool. There's quite a bit of space at the top storm. Perhaps you can change this. Let's go to Editor View, and let's scroll down until we get to our itemsArray. I think it's about here. Let's go for 40 percent, yeah let's try that 40 percent. Let's refresh this. Maybe will look a lot better if I didn't have a bunch of my plages, like these big things here. Anyway I like it. It's a lot of fun. Everything is Parallaxing really nicely. It's a really nice way to have a newsletter sign-up page. Cool.
15. What's Next?: That's it for this class. Thank you for taking it. I hope you've had fun. I hope you've learned a lot. I hope you want to do some more coding. The thing I want to leave you with is that this is only the beginning. Interaction design is super fun and in the web world, it's certainly the funner side of JavaScript. There's a lot more to learn and there is certainly a lot better, quicker, and more elegant ways of writing code than how I've coded in this class. My aim has been to make everything as simple and as easy to understand as possible. If you have any questions or want to discuss anything, please do so in the community area or reach out to me on social media. If you've enjoyed the class, please give it a review and share it so that other students can find it and benefit from it, too. I've also got plenty more classes in the pipe-line. If you like the way I teach, follow me on Skillshare and on social media and check out taptapkaboom dot com. Bye for now and I'll see you soon.