DEV Community

Daniel Orner
Daniel Orner

Posted on

Building an Unsplash Slide Show on NeoCities

Unsplash is a great website that offers free images in a variety of formats and subjects. When we first went into lockdown in 2020, my home setup was two screens - my laptop, for actual work, and an external screen which is where my video calls took place, so I could still reference my work screen at the same time.

However, while a call wasn't taking place, my top screen just kind of sat there, blank. I wanted something to look at during thinking breaks. Basically I wanted a screen saver, but you can't get those going on just one screen.

Way back in the day, I had a number of personal pages on GeoCities. This revolutionary site allowed you to write your own HTML and have it hosted for free! Turns out, there's a modern version of this, called NeoCities. It allows you to create simple sites with static files that are hosted for free.

I used this post to make use of the source.unsplash.com endpoint to show a random, full-page image on my browser which I made full-screen on the external monitor. (I use Firefox for my browsing, so I just stuck Chrome up there for the slide show). I also made use of finicky so that all Google Meet links went to Chrome, while all other links stayed with Firefox.

Problem! A couple of weeks ago, Unsplash removed the source.unsplash.com endpoint. Instead, you need to use their API directly. Thankfully, the API is still free for low levels of usage, so I was able to modify the site to work with it.

The Design

Once you sign up, you'll get an API key. For these purposes, I didn't care too much about exposing it in a static site since I don't have any payment info on Unsplash and I'm not using it for anything else.

The overall design is as follows:

  • We want a "target" image div which will hold the image.
  • We will fetch 30 images (the max we can) from the API in the collection we're interested in.
  • We will loop through those images and show a new one once per minute.
  • Once we've exhausted the ones we have, we'll fetch more. This means we should in general only be making 2 API requests per hour.
  • If I don't like the image showing, I want an easy way to skip to the next one. I want to add a "refresh" button that will do that for me.

I'm going to keep this super simple. The only dependency I have is jQuery which I'm using for animations. You could easily do this with CSS animations, but I'm not as used to those.

The Implementation

First, here's the HTML:

<head> <style> * { box-sizing: border-box; } body { margin: 0; background-color: black;} .trigger { position: fixed; top: 2rem; right: 2rem;} a { font-size: 2rem; color: white; transition: color 200ms ease; } a:hover { color: rgba(white, 0.7) } #target {background-size: cover; background-position: center; background-repeat: no-repeat; height: 100%; width: 100%; } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/material-design-iconic-font/2.2.0/css/material-design-iconic-font.min.css"></link> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <body> <div class="trigger"> <a style="cursor: pointer;" id="refresh"><i class="zmdi zmdi-refresh-alt"></i></a> </div> <div id="target"></div> </body> 
Enter fullscreen mode Exit fullscreen mode

Now for the JavaScript.

// control the auto refresh rate -> 1000 = 1 second window.refreshRate = 60000; // you can change the collections ID to switch these out. Or you can use any other query from the API if you want truly random images window.url = "https://api.unsplash.com/photos/random?w=1600&h=900&collections=879001&count=30&client_id=YOUR_API_KEY&orientation=landscape" // use this to cache our data window.jsonData = null; // fetch the data, put it into the JSON blob, and pre-load the images from the data async function fetchData() { const response = await fetch(window.url); window.jsonData = await response.json(); window.jsonData.forEach((image) => { const img = new Image(); img.url = image.urls.full; }); } // display the next image async function nextImage() { const image = window.jsonData?.pop() if (image) { // we have more in the array const imageURL = image.urls.full $('#target').fadeOut(function() { $('#target').css({'background-image' : `url(${imageURL})` }).fadeIn(1500) }); } else { // we've exhausted the array, go get more await fetchData(); await nextImage(); } } window.intervalTimer = setInterval(nextImage, refreshRate); setTimeout(nextImage, 0); $('#refresh').click(async function() { clearInterval(window.intervalTimer); await nextImage(); window.intervalTimer = setInterval(nextImage, refreshRate); }); // Hide the images on load $('#target').hide(); 
Enter fullscreen mode Exit fullscreen mode

Et voila! Hope someone out there finds this helpful!

Top comments (0)