DEV Community

quantotius
quantotius

Posted on

Building a Klondike Solitaire Game: Adding a Simple Image Preloader with Vanilla JavaScript

Creating a smooth user experience is a key priority in web development, especially when your site relies on large visuals. While working on my new shiny Klondike Solitaire game, I needed to ensure that the card images loaded in a way that felt natural and didn’t leave users staring at a blank screen. So, I decided to add a simple image preloader that could also show users how much of the image had loaded, using nothing but vanilla JavaScript, HTML, and CSS. Here’s how I did it.


Step 1: Basic Setup

First things first, I created a simple file structure to keep things tidy. Here’s what it looked like:

klondike-preloader/
├── index.html
├── styles.css
└── script.js
Enter fullscreen mode Exit fullscreen mode

This way, I had separate files for the HTML structure, the styling, and the JavaScript logic.

Step 2: Building the HTML Structure

In the HTML file, I set up a button to start the image loading process, a progress bar to show how far along the loading was, and a spot to display the image once it was ready.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Klondike Solitaire Image Preloader</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <button id="load-button">Load Solitaire Image</button>
    <div id="progress-bar">
        <div id="progress"></div>
    </div>
    <div id="image-container">
        <img id="image" alt="Klondike Solitaire Card" />
    </div>
    <script src="script.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 3: Styling the Progress Bar and Layout

With the structure in place, I moved on to styling. I wanted the progress bar to stay hidden until the image actually started loading.

styles.css

#progress-bar {
    width: 100%;
    background: lightgray;
    margin-bottom: 10px;
    height: 20px;
    display: none; /* Hidden at first */
}

#progress {
    width: 0%;
    height: 100%;
    background: green;
}

#image-container {
    display: none; /* Also hidden initially */
}

#load-button {
    margin-bottom: 10px;
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Adding JavaScript for Image Loading

Now for the JavaScript! Here’s what I did:

  1. Triggered Image Loading: Clicking the button starts loading the image.
  2. Updated the Progress Bar: Showed the bar and adjusted its width as the image loaded.
  3. Fallback for When Content Length Isn't Available: Used a default size to calculate progress in case the server didn’t provide the total size.

script.js

const progressBar = document.getElementById('progress');
const imageContainer = document.getElementById('image-container');
const imageElement = document.getElementById('image');
const loadButton = document.getElementById('load-button');

// Default fallback size in bytes
const DEFAULT_SIZE_BYTES = 500 * 1024; // 500 KB

function loadImage(url) {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';

    let totalSize = DEFAULT_SIZE_BYTES;

    document.getElementById('progress-bar').style.display = 'block';

    xhr.onprogress = (event) => {
        if (event.lengthComputable) {
            totalSize = event.total;
        }
        const percentComplete = (event.loaded / totalSize) * 100;
        progressBar.style.width = percentComplete + '%';
    };

    xhr.onload = () => {
        if (xhr.status === 200) {
            const blob = xhr.response;
            const objectUrl = URL.createObjectURL(blob);
            imageElement.src = objectUrl;
            imageContainer.style.display = 'block';
            progressBar.parentNode.style.display = 'none';
        }
    };

    xhr.onerror = () => {
        console.error('Image loading failed.');
    };

    xhr.send();
}

loadButton.addEventListener('click', () => {
    loadImage('https://example.com/your-image.jpg');
});
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Used XMLHttpRequest to Fetch the Image: Tracked progress with onprogress and handled the image as a blob.
  • Fallback for Default Size: Ensured the progress bar worked even if the server didn’t send the file size.
  • Cleaned Up After Loading: Hid the progress bar and showed the loaded image.

Step 5: Testing

After coding, I tested it with different image sizes and adjusted the default size to make sure it provided a realistic loading experience. You can try the code on codepen: https://codepen.io/quantotius/pen/KKOXxqP


Conclusion

And there you have it! A basic, yet effective way to preload images and improve the user experience using vanilla JavaScript. Perfect for a game like Klondike Solitaire where visual feedback is a must. Try it out, and if you get stuck, feel free to ask for help!

Top comments (0)