Capture and Upload Dynamic Page Thumbnails with Vue.js and html2canvas

James Kingsley
4 min readJun 16, 2023

--

Introduction

In web applications, especially content management systems, users often create pages with custom titles and themes. A visually engaging thumbnail can make these pages more appealing and help in better content representation. However, users might not always have a thumbnail ready or might need some time to create one. To streamline this process and enhance the user experience, we can automatically generate thumbnails based on the content they create.

In this tutorial, we will dive into how to capture a screenshot of a page’s title, apply one of the selected themes to the title and div, and upload the screenshot as a thumbnail using Vue.js and html2canvas.

Prerequisites

  • Basic knowledge of JavaScript and Vue.js
  • Node.js and npm installed
  • A text editor (such as Visual Studio Code)
  • A working backend that can handle file uploads (not covered in this article)

Setting Up The Project

Begin by setting up a new Vue.js project if you don’t have one already

vue create thumbnail-capture
cd thumbnail-capture

After creating your project, you need to install the required packages:

npm install html2canvas axios

Building the Thumbnail Capture Component

Now, let’s create a component to capture and upload the thumbnails.

Create a new file named ThumbnailCapture.vue in your components directory and add the following code:

Template Section

<template>
<!-- button to capture screenshot -->
<div class="d-flex row gap-1">
<button class="btn btn-primary" @click="createThumbnail">
Create Thumbnail
</button>
<!-- BS5 image to display thumbnail -->
<img :src="thumbUrl" class="img-thumbnail" alt="thumb" />
<div class="mb-3">
<label for="formFile" class="form-label">Or, Upload your own</label>
<input
class="form-control"
type="file"
id="formThumbnail"
accept="image/*"
@change="handleFileUpload"
/>
</div>
</div>
</template>

Script Section

Next, let’s add the script section to our component.

<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import html2canvas from 'html2canvas';
import axios from 'axios';

const thumbUrl = ref(""); // initialize the thumbUrl to an empty string

const handleFileUpload = async (e) => {
const file = e.target.files[0];
const formData = new FormData();
formData.append('file', file);

try {
// Upload to server
await axios.post(`/api/courses/store-thumbnail`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});

//set thumbUrl to the uploaded file
thumbUrl.value = URL.createObjectURL(file);

//clear the input
e.target.value = null;
} catch (error) {
console.error("Error uploading file:", error);
}
};

const createThumbnail = async () => {
try {
// Code to capture styles of the elements we need
const titleStyle = window.getComputedStyle(document.querySelector('#page-title'));
const backgroundColor = window.getComputedStyle(document.body).backgroundColor;

// Create temporary div
const tmpDiv = document.createElement('div');
tmpDiv.style.cssText = `
width: 800px;
height: 600px;
font-family: ${titleStyle.fontFamily};
color: ${titleStyle.color};
background-color: ${backgroundColor};
border: 1px solid black;
`;

// Append to the body
document.body.appendChild(tmpDiv);

// Capture the screenshot
const options = {
allowTaint: true,
useCORS: true,
height: 600,
width: 800,
};
const canvas = await html2canvas(tmpDiv, options);

// Convert the canvas to a data URL
const imageDataUrl = canvas.toDataURL('image/jpeg', 0.95);

// Convert DataURL to Blob
const response = await fetch(imageDataUrl);
const blob = await response.blob();

// Create FormData
const formData = new FormData();
formData.append('file', blob, 'screenshot.jpg');

// Upload to server
await axios.post(`/api/courses/store-thumbnail`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});

// Update thumbUrl to show the captured image
thumbUrl.value = imageDataUrl;

// Remove the temporary div
document.body.removeChild(tmpDiv);
} catch (error) {
console.error("Error creating thumbnail:", error);
}
};
</script>

Wrapping Up

In this tutorial, we created a solution that automatically generates thumbnails for user-created pages. This is especially useful in scenarios where users have the flexibility to create pages with custom titles and select from various themes. By offering an auto-generated thumbnail based on their content and selected theme, we not only save users’ time but also ensure a consistent visual appeal throughout the application.

For those users who wish to use custom images, they have the option to upload their thumbnails. This solution thereby offers the best of both worlds by providing convenience without compromising customization.

Remember to handle errors effectively and check server responses to ensure the robustness of the application. Your users will surely appreciate this intuitive and streamlined feature. Happy coding! 🚀

About the Author

James Kingsley has spent the last 15 years creating software for the eLearning sector. He likes to alter software, websites, and apps to make them do things they weren’t designed to do. A number of eLearning development tools have been released by his company, GForce Learning. ReviewMyElearning: The most effective method for gathering feedback from SMEs, team members, clients, etc. He leverages his experience as a Co-Founder of GForce Learning to create solutions tailored for the Web, Mobile, and Desktop. We offer solutions for various additional industries in addition to eLearning. Node.js, Vue, Mongo, integrating APIs, xAPI, SCORM, and extending Off-the-Shelf Tools.

You can connect with him on LinkedIn.

--

--

James Kingsley

15 years in eLearning software, co-founded GForce Learning. Innovated tools like ReviewMyElearning. Excels at making software do the unexpected with JavaScript.