Skip to content

Instantly share code, notes, and snippets.

@kjintroverted
Last active October 16, 2019 18:23
Show Gist options
  • Save kjintroverted/d67c7f12f68288f6ccf07cbd06fa66a8 to your computer and use it in GitHub Desktop.
Save kjintroverted/d67c7f12f68288f6ccf07cbd06fa66a8 to your computer and use it in GitHub Desktop.
A simple React component that creates a tiled background of recent posts from Instagram.
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
const IGBackground = ({ username, quality, filterOpts = [] }) => {
const [imageResources, setImages] = useState(null);
const [imageDims, setImageDims] = useState(0);
// CALCULATE HOW WIDE THE TILES SHOULD BE
function getImageDims() {
if (!imageResources || !imageResources.length) setImageDims(0);
else setImageDims(
Math.sqrt((window.innerHeight * window.innerWidth) / imageResources.length)
);
}
useEffect(() => { // LOADS POSTS WHEN USERNAME UPDATES
async function getMedia() {
if (!username) return;
const resp = await fetch(`https://www.instagram.com/${ username }/?__a=1`);
const { graphql } = await resp.json();
setImages(
graphql.user
.edge_owner_to_timeline_media.edges
.map(({ node }) => node.thumbnail_resources)
)
}
getMedia();
}, [username]);
// UPDATES TILE DIMENSIONS WHEN IG IMAGES LOAD
useEffect(getImageDims, [imageResources]);
// UPDATES TILE DIMENSIONS WHEN WINDOW RESIZES
window.addEventListener("resize", getImageDims)
// PARENT TILE FOR IMAGES
const Tile = styled.div`
width: ${imageDims }px;
height: ${imageDims }px;
flex-grow: 1;
`
// CREATES A FILTER OVER TOP
const Filter = styled.div`
position: fixed;
width: 100vw;
height: 100vh;
background-color: ${filterOpts }; /* USED IF ONE COLOR PASSED */
background-image: linear-gradient(${filterOpts.join() }); /* USED IF GRADIENT OPTS PASSED */
opacity: .7;
`
return (
<Container>
{ imageResources &&
imageResources.map(res => (
<Tile key={ res[0].src }>
<Post src={ res[quality || 1].src } alt="recent post" />
</Tile>
))
}
<Filter />
</Container>
)
}
export default IGBackground;
IGBackground.propTypes = {
username: PropTypes.string.isRequired,
quality: PropTypes.number,
filterOpts: PropTypes.arrayOf(PropTypes.string)
}
const Container = styled.div`
position: fixed;
width: 100vw;
height: 100vh;
display: flex;
flex-wrap: wrap;
`
const Post = styled.img`
height: 100%;
width: 100%;
object-fit: cover;
`
import React from 'react';
import styled from 'styled-components';
import './App.css';
import IGBackground from './components/IGBackground';
import Splash from './components/Splash';
function App() {
return (
<Main>
<IGBackground
username="ferrytalecreative"
filterOpts={ ["to bottom right", "teal", "blue", "purple"] }
/>
<Fence>
<Splash />
<Spacer />
</Fence>
</Main>
);
}
export default App;
const Main = styled.div`
display: flex;
justify-content: center;
`
const Fence = styled.div`
position: fixed;
height: 100vh;
width: 100%;
max-width: 1000px;
display: flex;
align-items: center;
`
const Spacer = styled.div`
flex: 1;
`
@kjintroverted
Copy link
Author

The above options renders like this:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment