Transitions have solidified themselves as an important part of web applications, as they have been used in different ways to capture users' attention. They, however, have also been known to be a little tricky to implement. This problem has been mitigated by the release of UI libraries over the years.
This article will walk us through embedding a video player and handling video overlay transitions similar to what we see on Netflix, using Nuxt.js.
What we will be building
Akin to smart TV's Netflix, we want our video to start playing automatically after three seconds when our video player mounts. After five seconds, we want our overlay to fade out, only to fade back in when the video ends.
Check out the Codesandbox to get started quickly.
GitHub URL:https://github.com/Iheanacho-ai/nuxtjs-netflix-animation
Prerequisities
To get the most out of this article it is important that we have the following:
- A basic understanding of CSS, JavaScript and Vue.js
- Node and it’s package manager,
npm
. Run the commandnode -v
&&npm -v
to verify we have them installed, or install them from here. It is recommended that we have the latest version. - Alternatively, we can use another package manager, Yarn.
- Understanding Nuxt.js would help us follow through with this tutorial quicker, but it is not entirely required.
- A Cloudinary account, if you don’t have one, you can create one here.
Setting up our Nuxtjs app
Nuxt.js is an open-source vue.js frontend development framework that allows us to create universal web applications without stress, render statically Vue.js applications without having a server, and enables functionalities like server-side rendering, static site generating, etc. in our project.
To create a nuxt.js app, we go to our terminal and run the command below.
NOTE: If you are on windows and using Git Bash you might have issues with the arrows, so it is advisable that you use the Powershell terminal instead
1npm init nuxt-app <project-name>23 #or45 npx create-nuxt-app <project-name>67 #or89 yarn create nuxt-app <project-name>
Running this command will trigger a set of question prompts. In the picture below, this is the setup I used.
After that, we run these commands
1cd <project name>23 npm run dev45 #or67 yarn dev
This would change the directory to our project and run it on the browser, to see our app go to http://localhost:3000/
Installing dependencies
In this section of the tutorial, we will install the dependencies required for this project. These dependencies are Cloudinary for the video player and Vue2-animate for handling the transitions.
Cloudinary
Cloudinary is a cloud-based service that provides an end-to-end image and video management solution, including uploads, storage, manipulations, optimizations, and delivery.
It also allows developers to embed video players in their app that handles video events effectively.
To enable our nuxt app to use these Cloudinary features, we will add the video player assets in the head
section of our nuxt.config.js
file.
1// nuxt.config.js23 export default {4 head: {5 ...6 link: [7 ...8 { rel: 'stylesheet', href: 'https://unpkg.com/cloudinary-video-player@1.5.9/dist/cld-video-player.min.css' }9 ],10 script: [11 { src: 'https://unpkg.com/cloudinary-core@latest/cloudinary-core-shrinkwrap.min.js' },12 { src: 'https://unpkg.com/cloudinary-video-player@1.5.9/dist/cld-video-player.min.js' },13 ],14 },1516 };
Next up, we create a .env
at the root of our project.
1touch .env
After creating our .env
file, we go to our Dashboard, in the Account Details section we can see our cloud name, we copy paste it in our .env
file.
1CLOUD_NAME = <Cloudinary-cloud-name>
Vue2-animate
Vue2-animate is a great UI library created for the Vue.js framework. It helps developers create high-performance and stunning animations with just a few lines of code.
To install vue2-animate
in our project, we run this command.
1npm install --save vue2-animate23 #or45 yarn add vue2-animate
Creating our Video Player
In our index.vue
file, we embed the Cloudinary video player in our project using the HTML5 native video
element.
We then give the element an id
of video-player
and a class
of cld-video-player
.
1<template>2 <div>3 <video4 id= "video-player"5 class="cld-video-player"6 >7 </video>8 </div>9 </template>
In our mounted
lifecycle hook, we create a Cloudinary instance. Doing this in our mounted lifecycle hook allows the instance to be created once the app mounts.
1// pages/index.vue23 <script>45 export default {6 data(){7 return{8 cld: null,9 player: null,10 video: "production_ID_4456999_gr6iy4"11 }12 },13 mounted(){14 this.cld= cloudinary.Cloudinary.new({15 cloud_name: process.env.CLOUD_NAME,16 secure: true17 })18 this.player = this.cld.videoPlayer(19 'video-player'20 );21 this.player.source(this.video);22 }2324 }252627 </script>
In the data
object, we define three variables:
- The
cld
variable holds the Cloudinary instance we will create. - The
player
variable holds the new Cloudinary video player we will instantiate on mount. We do this by passing the idvideo-player
(id of our video element) to theVideoPlayer
method. - The
video
variable holds theid
of the video we are looking to play stored on cloudinary.
In our mounted lifecycle hook, we create a Cloudinary instance from the Cloudinary object by providing the cloud name we stored in our .env
file and secure: true
, as arguments.
We then instantiate the Cloudinary video player using the videoPlayer method and passing either the video player id or the video player itself, as as argument.
After we create our player, we sourced the video we are looking to play.
Next, in the style section of our index.vue
file, we add a bit of styling to our video player, with a width of 500px and a height of 300px.
1<style scoped>2 div{3 margin: 0;4 padding: 0;5 }6 .cld-video-player{7 width: 500px;8 height: 300px;9 }10 </style>
With that we have embedded a Cloudinary video player in our project.
Creating our overlay
In the template
section of our index.vue
file, we create our video overlay with the HTML native div
element.
1<div class = 'overlay' >2 <h2 class= 'overlay-header'>bonne vitesse</h2>3 <p>4 You look down on where you came from sometimes5 But you'll have this place to call home, always.6 </p>7 <button>Play</button>8 </div>
Our overlay is incomplete without the styling
1.overlay{2 box-sizing: border-box;3 font-family: 'Nunito', sans-serif;4 width: 250px;5 height: 300px;6 padding: 10px;7 background-color: rgba(0, 0, 0, 0.35);8 color: #fff;9 position: absolute;10 top: 7px;11 left: 7px;12 bottom: 7px;13 }14 .overlay-header{15 text-align: center;16 }17 button{18 width: 90%;19 height: 30px;20 margin: 0 auto;21 }
We give our overlay a width of 250px (half of our video player) and a height of 300px. Our overlay has an absolute position to sit on our video player.
Selectively rendering the overlay and playing the video.
To selectively render our overlay, we must first create an overlay
variable in the data
object. This will be used to control our overlay.
1export default {2 data(){3 return{4 cld: null,5 player: null,6 video: "production_ID_4456999_gr6iy4",78 // overlay variable9 overlay: true,10 }11 },12 mounted(){13 this.cld= cloudinary.Cloudinary.new({14 cloud_name: process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,15 secure: true16 })17 this.player = this.cld.videoPlayer(18 'video-player'19 );20 this.player.source(this.video);21 }
Next, we add a setTimeout
function to remove the overlay after five seconds in our mounted lifecycle hook. Then we use Cloudinary's ended
video player event to set the overlay to true when the video ends.
1this.player.on('ended', ()=> {2 this.overlay = true3 })45 setTimeout(() => {6 this.overlay = false7 }, 5000)8 }
We then selectively render the overlay depending on the value of the overlay.
1<template>2 <div>3 <video4 id= "video-player"5 class="cld-video-player"6 >7 </video>89 <div class = 'overlay' v-if = 'overlay'>10 <h2 class= 'overlay-header'>bonne vitesse</h2>11 <p>12 You look down on where you came from sometimes13 But you'll have this place to call home, always.14 </p>15 <button> Play</button>16 </div>1718 </div>19 </template>
Selectively playing our video.
We want our video to play automatically after three seconds, but we also want the play button on the overlay to play the video.
To achieve this, we use a setTimeout
function to play the video after three seconds on the mounted lifecycle hook. We add a function on the method object called playMedia
, which also plays the media.
1<script>23 export default {4 data(){5 return{6 cld: null,7 player: null,8 video: "production_ID_4456999_gr6iy4",9 overlay: true,10 }11 },12 methods: {13 playMedia(){14 this.player.play()15 }16 },1718 mounted(){19 this.cld= cloudinary.Cloudinary.new({20 cloud_name: process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,21 secure: true22 })23 this.player = this.cld.videoPlayer(24 'video-player'25 );2627 this.player.source(this.video);2829 this.player.on('ended', ()=> {30 this.overlay = true31 })3233 // plays the media3435 setTimeout(() => {36 this.player.play()37 }, 3000)3839 setTimeout(() => {40 this.overlay = false41 }, 5000)42 }4344 }454647 </script>
Next, we then pass the playMedia
method into an onClick
event listener on our button.
1<button @click= "playMedia()">Play</button>
Animating our Overlay
To use the vue2-animate
library in our project we have to require it, we do this in the script
section of our index.vue
file.
1require('vue2-animate/dist/vue2-animate.min.css')
The vue2-animate
allows us to use the transition
component to animate our element. This transition
component has a name prop that takes in the kind of animation we want our element to have, in this case, fade.
We then specify the duration for the animation using the style
prop.
1<transition name="fade">2 <div class = 'overlay' v-if = 'overlay' style="animation-duration: 1s">3 <h2 class= 'overlay-header'>bonne vitesse</h2>4 <p>5 You look down on where you came from sometimes6 But you'll have this place to call home, always.7 </p>8 <button @click= "playMedia()">Play</button>9 </div>10 </transition>
With these we have completed the Netflix-styled Video Overlay animation. Here is what it should look like:
Conclusion
In this article we discussed what Cloudinary is, why we would use it, and how to embed its video player in our project. We also discussed the vue2-animate
library and used it to animate in and out, our overlay depending on what player event was triggered.
Resources
You may find the following resources useful