loading...
Cover image for Get your first dev job by building these projects! #3: Instagram Feed with a Flashlight Effect

Get your first dev job by building these projects! #3: Instagram Feed with a Flashlight Effect

catmcgeecode profile image Cat McGee ・7 min read

Youtube | Twitter | Instagram

Hello geeks! Today we're going to be building something super awesome. I'm so excited about this. It's an Instagram feed of any person you want (as long as their profile as public, more about that later) with a flashlight effect on top of it. Our mouse will dictate where the flashlight is. So it'll be like you're stalking them. Which is what Instagram is for anyway! It's perfect!

Image

We'll be building this in HTML, CSS, and plain ol' Javascript.

Find the code here.

Watch the 2 minute 20 second tutorial here.

Step 1: Make your HTML, CSS, and Javascript files

Create your HTML file, your CSS file, and your Javascript file. Make sure to attach the CSS and the Javascript to the HTML! (I give this reminder in every tutorial because I always forget to do this.)

Your HTML should look a little like this.

<html>
    <head>
        <title>Instagram photos under a flashlight</title>
        <script type="text/javascript" src="actions.js"></script>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
    </body>
</html>

Step 2: Request the photos from Instagram

The public Instagram API is incredibly easy to use, and you can get photos from any page at all!! This includes profile pages and tags. Because the API is public, we don't need to create a developer account, but it also means that we have no authentication and can't access private accounts. We only need to add ?__a=1 at the end of the URL. I'll be using my Instagram profile link in this tutorial, but feel free to use any!

https://www.instagram.com/catmcgeecode/?__a=1

We're going to use async functions for this so that our code works asynchronously. Async functions allow the use of await which does exactly what it says on the tin - we'll wait for the promise to be fulfilled or rejected (i.e. we either get a valid response from Instagram or we're told we're not allowed) before we go onto the next task. Learn more about async functions here.

So let's use Javascript's fetch API, the easiest and best way to request data.

Go ahead and put this fetch statement in an async function.

async function getInstaPictures() {
    const response = await fetch("https://www.instagram.com/catmcgeecode/?__a=1");
}

We get a lot of data from this response, so we're going to want to read it as JSON. This will make it far easier to parse through and find the photos.

const jsonData = await response.json();

Let's console.log (or console.table()) the response and run it so we can see what we're expecting and know where to find the photos in the response. And don't forget to call the function!

async function getInstaPictures() {
    const response = await fetch("https://www.instagram.com/catmcgeecode/?__a=1");
        const jsonData = await response.json();
        console.log(jsonData)
}
getInstaPictures()

Now open the HTML file in your browser and have a look at the console (click Inspect to open developer tools, then click Console). You'll be able to see the response. It might look like nonsense, but spend some time looking through it and see what you can find.

If you look hard enough, you'll find that the image URLs can be found by navigating through like this:

jsonData → graphql → user → edge_owner_to_timeline_media → edges

Then, inside edges there are multiple nodes and each node contains one display_url which is what we need.

So we need to iterate through each node inside edges and grab the display URL.

const pictures = jsonData.graphql.user.edge_owner_to_timeline_media.edges; 
        for(i = 0; i < pictures.length ; i++) {
                // here we will show the images on the website
}

Still with me? (Because if so, you've come a long way.)

Step 3: Display the pictures on the website

Each time we iterate through the data, we want to display the display URL as the source of an image in our HTML.

So we're going to use the Javascript to create an image element (document.createElement('img')), then get node.display_url for each iteration and set it as the source of our new image element, and then add the image element to the HTML.

for(i = 0; i < pictures.length ; i++) {
        let img = document.createElement('img');
        img.src = pictures[i].node.display_url;
        document.body.appendChild(img);
    }

That wasn't so hard was it?

Put all this together, open it up in a browser, and there you have it - all the photos from someone's Instagram page! If it's still not working for you, here's the source code for the Javascript.

Change the styling a little bit so that they look good. In the video, I just changed the width to 350px as shown below, but you can play around with some flex-box styling to make it look real good.

body img {
    width: 350px;
}

Step 4: Make the flashlight effect

In this step, we're going to make it look like there is a flashlight over the Instagram photos, but we're not going to make it move just yet. We're going to make everything black except one transparent circle. So let's head to our CSS!

To make everything black, we are going to make the root element (HTML) black. We're going to use a pseudo-element (learn more here) inside root and make this element cover the entire screen. The content attribute along with ::before helps us achieve this.

:root:before {
    cursor: none;
    content: '';
    width: 100%;
    height: 100%;
    position: fixed;
}

We've also set the cursor here as none for added effect.

Run your code. Nothing has happened.

The magic happens in this next part - radial-gradient. (PS: Me trying to say this in an Irish accent is really funny.)

Radial gradient allows us to create a shape that has a gradient, progressing out from its origin. This shape can be a circle! It's pretty cool. So the idea here is that our background will be a radial gradient, with the primary colour being black, and our shape (a circle) will be transparent. The gradient will give it a kind of blurred appearance, which is perfect for a flashlight!

Add this to your :root:before:

background: radial-gradient(
        circle 10vmax at var(--cursorX) var(--cursorY), 
        rgba(0,0,0,0),
        rgba(0,0,0,1)
    )

Phew. Let's go through this.

circle - we set the shape as a circle. Pretty self explanatory.

10vmax - vmax is all about relatively. 1vmax = 1% of the screen. So our flashlight will be the size of about 10% of the screen.

at var(--cursorX) var(--cursorY) - this is where things get groovy. This sets the x and y coordinates for where our circle is, but because it isn't the same (our flashlight moves with our mouse), we want to pass variables into it. We get these variables from Javascript later.

first rgba(0,0,0,0) - this is transparent (the final 0 is opacity) and is the colour of the inside of our image.

second rgba(0,0,0,1) - this is black, and it is the colour that our circle gradient will progress into (as in - the rest of the background!)

Cool. If you run this code, you'll just see completely black. Can you take a guess as to why? It's because we don't have our --cursorX and --cursorY variables set yet. Let's just set these in the CSS so that we can make sure it's working before we move onto Javascript.

Your CSS should look like this:

:root:before {
    --cursorX = 50vw;
    --cursorY = 50vh;
    cursor: none;
    content: '';
    width: 100%;
    height: 100%;
    position: fixed;
    background: radial-gradient( 
        circle 10vmax at var(--cursorX) var(--cursorY),
        rgba(0,0,0,0),
        rgba(0,0,0,1)
    ) 
}

Step 5: Make the flashlight move

Now it's time to set our --cursorX and --cursorY variables to be in the position of our mouse every time we move our mouse. This is SUPER easy with Javascript.

Open your Javascript file and create a function that will run when you move your mouse.

document.addEventListener('mousemove', update)

function update(e) {
}

Here, e stands for event which has lots of different handlers, including the position of our mouse coordinates!

Firstly, this function needs to read the X and Y coordinates of your mouse. This is super simple - you can just use e.clientX and e.clientY.

let x = e.clientX; 
let y = e.clientY; 

Then we need to send these to the CSS, by setting them as properties on the styling.

document.documentElement.style.setProperty('--cursorX', x + 'px'); 
document.documentElement.style.setProperty('--cursorY', y + 'px');

(It's the document element, because that's the root element, which in our case is the html element. I wish they had the same name too.)

All together now!

document.addEventListener('mousemove', update)

function update(e) {
    let x = e.clientX; 
    let y = e.clientY; 

    document.documentElement.style.setProperty('--cursorX', x + 'px'); 
    document.documentElement.style.setProperty('--cursorY', y + 'px');
}

That's it. Open it up in your browser and you've got yourself a fun new way to stalk someone on Instagram.

Now it's your turn!

I emphasize this on every one of these tutorials. To really make the most out of this, you've got to build something on top of it (and keep searching the internet to find out how!) I'm sure you have some creative ideas, but just in case you don't, here are some:

  • Make it work better on mobile (maybe do something cool with phone gestures...)
  • Change the size of the circle and the background colour
  • Get different data from instagram
  • Use the real instagram API and authenticate (you can use the Explore page or private accounts that you follow)
  • Let the user choose the Instagram account first

Good luck! Happy coding, and make sure to comment or DM me on Twitter when you make something cool!

Posted on by:

catmcgeecode profile

Cat McGee

@catmcgeecode

I like Javascript and Python and make tutorials so you can like them too.

Discussion

markdown guide