Creating a Video Thumbnail Previews in GatsbyJS

Chris Achinga

Video previews give users a quick snapshot of the video while still browsing the page. A thumbnail is an image preview of the actual video.

This post covers the processes of uploading video files to Cloudinary, displaying their thumbnails on web pages, and creating the preview on hover functionality.

Demo and source code

We completed this project in a CodeSandbox. Fork and run it to quickly get started.

The GitHub repository can be found here.

Prerequisites

  • A Cloudinary account — create a free account here
  • Knowledge of React.js and Gatsby.js
  • Node.js version 12+

Creating a Gatsby.Js application

We will be using Gatsby CLI to create our application, and we will install it using the following command:

npm install -g gatsby-cli

After the installation, we will use the command gatsby new to start a new Gatsby application.

On a terminal (or CMD for Windows), use:

gatsby new

The Gatsby installation process will prompt us to answer some questions:

After choosing the configurations, a new Gatsby site is created.

To test the new project, run the development server using:

npm run develop

The server runs on localhost port 8000: http://localhost:8000/

We will be styling our page using Bootstrap. To install it, we run the command:

npm install bootstrap

Inside the src folder, we will edit pages/index.js to contain the following:

1import React from 'react'
2 // Import from an installed package - Bootsrap
3 import 'bootstrap/dist/css/bootstrap.min.css'
4
5 const IndexPage = () => {
6 return (
7 <div>index</div>
8 )
9 }
10 export default IndexPage

Uploading media to Cloudinary

After signing in to your Cloudinary account, navigate to Media Library and upload a few videos.

The easiest way to upload media to Cloudinary is by using the Upload button at the top right of the web page.

Once the video is uploaded, click on the link icon on the top right of the video card to copy its URL.

Inside the page/index.js file, above the return keyword, create an array of the video links uploaded to cloudinary, like so:

1const video_urls = [
2 {
3 id: 1,
4 title: 'Video One',
5 video_url:
6 'https://res.cloudinary.com/chris101/video/upload/v1645684691/video_1.mp4',
7 },
8 {
9 id: 2,
10 title: 'Video Two',
11 video_url:
12 'https://res.cloudinary.com/chris101/video/upload/v1645684672/video_2.mp4',
13 },
14 {
15 id: 3,
16 title: 'Video Three',
17 video_url:
18 'https://res.cloudinary.com/chris101/video/upload/v1645684663/video_3.mp4',
19 },
20 ]

Creating a video player using native element

We will use native HTML elements to display the videos you uploaded to Cloudinary:

1<div className="card h-100">
2 <div className="card-body">
3 <h4 className="card-title">video title</h4>
4 <video width="320" height="240" controls>
5 <source
6 src="https://res.cloudinary.com/chris101/video/upload/v1645684663/video_3.mp4"
7 type="video/mp4"
8 />
9 </video>
10 </div>
11 </div>

Inside the IndexPage, we will loop through the arrays with the video URLs and display them:

1{video_urls.map((video) => (
2 <div key="{video.id}" className="col-lg-4 col-sm-6 mb-4">
3 <div className="card h-100">
4 <div className="card-body">
5 <h4 className="card-title">{video.title}</h4>
6 <video width="320" height="240" controls>
7 <source src="{video.video_url}" type="video/mp4" />
8 </video>
9 </div>
10 </div>
11 </div>
12 ))}

Upon reloading the page, we will have all the videos shown on the page. The video cards show video thumbnails at timestamp 0:00 by default.

Creating event handlers

To trigger a preview of the video when a user hovers over the thumbnails, we will create two event handlers:

  1. To start the preview when the mouse pointer is on the thumbnail
  2. To stop the preview once the mouse pointer moves away from the thumbnail

To achieve this, we will utilize onMouseEnter and onMouseLeave mouse events in React.js.

Inside the IndexPage component, we will create two functions to handle the mouse events: handleMouseEnter() and handleMouseLeave().

1// handle mouse enter
2 const handleMouseEnter = (e) => {}
3 // handle mouse leave
4 const handleMouseLeave = (e) => {}

To trigger the video preview, update the handleMouseEnter() function to:

1const handleMouseEnter = (e) => {
2 const vid = e.target
3 vid.muted = true
4 vid.play()
5 }

The handleMouseEnter() function starts by grabing the <video></video> element — e.target. It then mutes the video(vid.muted = true), and begins playing the video(vid.play()).

To stop the preview and return it to its previous state once the pointer leaves the video card, update the handleMouseLeave() function to:

1const handleMouseLeave = (e) => {
2 const vid = e.target
3 vid.muted = false
4 vid.currentTime = 0
5 vid.pause()
6 }

To trigger the two events, we update the <video> element with:

1<video
2 width="320"
3 height="240"
4 controls
5 onMouseEnter="{handleMouseEnter}"
6 onMouseLeave="{handleMouseLeave}"
7 >
8 <source src="{video.video_url}" type="video/mp4" />
9 </video>

The complete code to the IndexPage() component is:

1import React from 'react'
2// Import from an installed package - Bootsrap
3import 'bootstrap/dist/css/bootstrap.min.css'
4
5const IndexPage = () => {
6 // video urls
7 const video_urls = [
8 {
9 id: 1,
10 title: 'Video One',
11 video_url:
12 'https://res.cloudinary.com/chris101/video/upload/v1645684691/video_1.mp4',
13 },
14 {
15 id: 2,
16 title: 'Video Two',
17 video_url:
18 'https://res.cloudinary.com/chris101/video/upload/v1645684672/video_2.mp4',
19 },
20 {
21 id: 3,
22 title: 'Video Three',
23 video_url:
24 'https://res.cloudinary.com/chris101/video/upload/v1645684663/video_3.mp4',
25 },
26 ]
27
28 // handle mouse enter
29 const handleMouseEnter = (e) => {
30 const vid = e.target
31 vid.muted = true
32 vid.play()
33 }
34 // handle mouse leave
35 const handleMouseLeave = (e) => {
36 const vid = e.target
37 vid.muted = false
38 vid.currentTime = 0
39 vid.pause()
40 }
41
42 return (
43 <div className='container'>
44 <h1 className='text-center mt-4'>Video Show</h1>
45
46 {/* video player */}
47 <div className='container'>
48 <div className='row'>
49 {/* display videos */}
50 {video_urls.map((video) => (
51 <div key={video.id} className='col-lg-4 col-sm-6 mb-4'>
52 <div className='card h-100'>
53 <div className='card-body'>
54 <h4 className='card-title'>{video.title}</h4>
55 <video
56 width='320'
57 height='240'
58 controls
59 onMouseEnter={handleMouseEnter}
60 onMouseLeave={handleMouseLeave}
61 >
62 <source src={video.video_url} type='video/mp4' />
63 </video>
64 </div>
65 </div>
66 </div>
67 ))}
68 </div>
69 </div>
70 </div>
71 )
72}
73
74export default IndexPage

Once we run the server and hover over the video thumbnails, the preview plays, and it stops once the mouse pointer leaves the thumbnail. A live preview of the demo can be found here.

Conclusion

This post covered the processes of creating a Gatsby.js application, uploading media files to Cloudinary, and creating event handlers to enable a video preview upon thumbnail hover.

Resources

Chris Achinga

Technical Writer