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>
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();
Et voila! Hope someone out there finds this helpful!
Top comments (0)