Picture-in-Picture with JavaScript and Angular 10

In this quick example, we'll learn how to use the Picture-in-Picture mode in JavaScript. Next, we'll see how to an example of using this new web API with Angular 10.
Picture-in-Picture (PiP) is a new feature in modern browsers that enables users to watch videos in a floating window that stays always on top of other windows.
How to Check if your Browser Supports Picture-in-Picture
You can simply use the document.pictureInPictureEnabled
boolean to check if Picture-in-Picture is supported and enabled in your web browser.
if ('pictureInPictureEnabled' in document) {
if(document.pictureInPictureEnabled){
console.log('Picture-in-Picture Web API is enabled');
}
}
else{
console.log('Picture-in-Picture Web API is not supported');
}
For Picture-in-Picture support we check if pictureInPictureEnabled
property exists in the document object then we verify that the web API is enabled if equals true.
Implementing Picture-in-Picture video in JavaScript
Now after checking that Picture-in-Picture is supported and enabled in your web browser, let's see how to implement this feature in a simple example with vanilla JavaScript.
Create an HTML file and add the following code:
<video id="videoElement" controls="true" src="<URL TO VIDEO>"> </video>
<button id="btn"> Enable Picture in Picture </button>
Next, add a <script>
tag with the following code:
<html>
<head>
<title>Picture-in-Picture Example</title>
</head>
<body>
<video id="videoElement" controls="true" src="<URL TO VIDEO>"> </video>
<button id="btn"> Enable Picture in Picture </button>
<script>
const videoElement = document.getElementById('videoElement');
let startButton = document.getElementById('btn');
startButton.addEventListener('click', startPiPMode);
async function startPiPMode(event) {
startButton.disabled = true;
try {
if (videoElement !== document.pictureInPictureElement) {
await videoElement.requestPictureInPicture();
startButton.textContent = "Exit Picture In Picture";
}
else {
await document.exitPictureInPicture();
startButton.textContent = "Enable Picture In Picture";
}
} catch (error) {
console.log(error);
} finally {
startButton.disabled = false;
}
}
</script>
</body>
</html>
First, we add a click handling function to the button in which we add the code for checking if we already have a video playing with Picture in Picture enabled by simply comparing the video DOM element to document.pictureInPictureElement
. If no video is playing, we then we call requestPictureInPicture()
on the video element to enable Picture in Picture, which will return a promise.
We use Async/Await syntax to avoid dealing with the then()
callback
If the promise is resolved or the function is returned in case of async/await , the video element is moved to the right corner of your screen with your video playing.
Finally, we toggle the button to exit Picture in Picture mode using the document.exitPictureInPicture()
method.
Implementing Picture-in-Picture video in TypeScript and Angular 10
Let's now see how to implement Picture-in-Picture with TypeScript and Angular 10.
As a prerequisite, you need to have Node.js and Angular CLI v10 installed on your local development machine.
Creating an Angular 10 Project
First, create an Angular 10 project using the following command:
$ ng new Angular10PictureInPictureExample
$ cd Angular10PictureInPictureExample
The CLI will ask you a couple of questions — If Would you like to add Angular routing? Type y for Yes and Which stylesheet format would you like to use? Choose CSS.
Next, open the src/app/app.component.html
file and update it as follows:
<h1>
Picture-in-Picture with Angular 10 Example
</h1>
<video #videoElement controls="true" src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"> </video>
Next, open the src/app/app.component.ts
file and start by importing ViewChild
, and ElementRef
:
import { Component, ViewChild, ElementRef } from '@angular/core';
Next, define the following interface:
interface VideoElement extends HTMLVideoElement {
requestPictureInPicture(): any;
}
So we can access the requestPictureInPicture()
without getting the undefined method error since we are using TypeScript.
Next, query for the video element via its template variable using ViewChild
as follows:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
@ViewChild("videoElement") videoElement: ElementRef;
Next, call the addEventListener()
to listen for the play
event on the video DOM element (accessed from the .nativeElement
property) and then call the requestPictureInPicture()
method to enter the Picture-in-Picture mode as follows:
ngAfterViewInit(){
const video: VideoElement = this.videoElement.nativeElement;
video.addEventListener('play', async (e) => {
await video.requestPictureInPicture();
})
}
This is the full component's code:
import { Component, ViewChild, ElementRef } from '@angular/core';
interface VideoElement extends HTMLVideoElement{
requestPictureInPicture(): any;
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
@ViewChild("videoElement") videoElement: ElementRef;
ngAfterViewInit(){
const video: VideoElement = this.videoElement.nativeElement;
video.addEventListener('play', async (e) => {
await video.requestPictureInPicture();
})
}
}
This is the live example in Stackblitz
Conclusion
In this example, we've seen what Picture-in-Picture is and how to use it with both vanilla JavaScript and within a TypeScript Angular 10 app.
- Author: Ahmed Bouchefra Follow @ahmedbouchefra
-
Date:
Related posts
Build an Angular 14 CRUD Example & Tutorial Angular 9 Components: Input and Output Angular 13 selectors Picture-in-Picture with JavaScript and Angular 10 Jasmine Unit Testing for Angular 12 Angular 9 Tutorial By Example: REST CRUD APIs & HTTP GET Requests with HttpClient Angular 10/9 Elements Tutorial by Example: Building Web Components Angular 10/9 Router Tutorial: Learn Routing & Navigation by Example Angular 10/9 Router CanActivate Guards and UrlTree Parsed Routes Angular 10/9 JWT Authentication Tutorial with Example Style Angular 10/9 Components with CSS and ngStyle/ngClass Directives Upload Images In TypeScript/Node & Angular 9/Ionic 5: Working with Imports, Decorators, Async/Await and FormData Angular 9/Ionic 5 Chat App: Unsubscribe from RxJS Subjects, OnDestroy/OnInit and ChangeDetectorRef Adding UI Guards, Auto-Scrolling, Auth State, Typing Indicators and File Attachments with FileReader to your Angular 9/Ionic 5 Chat App Private Chat Rooms in Angular 9/Ionic 5: Working with TypeScript Strings, Arrays, Promises, and RxJS Behavior/Replay Subjects Building a Chat App with TypeScript/Node.js, Ionic 5/Angular 9 & PubNub/Chatkit Chat Read Cursors with Angular 9/Ionic 5 Chat App: Working with TypeScript Variables/Methods & Textarea Keydown/Focusin Events Add JWT REST API Authentication to Your Node.js/TypeScript Backend with TypeORM and SQLite3 Database Building Chat App Frontend UI with JWT Auth Using Ionic 5/Angular 9 Install Angular 10 CLI with NPM and Create a New Example App with Routing Styling An Angular 10 Example App with Bootstrap 4 Navbar, Jumbotron, Tables, Forms and Cards Integrate Bootstrap 4/jQuery with Angular 10 and Styling the UI With Navbar and Table CSS Classes Angular 10/9 Tutorial and Example: Build your First Angular App Angular 9/8 ngIf Tutorial & Example Angular 10 New Features Create New Angular 9 Workspace and Application: Using Build and Serve Angular 10 Release Date: Angular 10 Will Focus on Ivy Artifacts and Libraries Support HTML5 Download Attribute with TypeScript and Angular 9 Angular 9.1+ Local Direction Query API: getLocaleDirection Example Angular 9.1 displayBlock CLI Component Generator Option by Example Angular 15 Basics Tutorial by Example Angular 9/8 ngFor Directive: Render Arrays with ngFor by Example Responsive Image Breakpoints Example with CDK's BreakpointObserver in Angular 9/8 Angular 9/8 DOM Queries: ViewChild and ViewChildren Example The Angular 9/8 Router: Route Parameters with Snapshot and ParamMap by Example Angular 9/8 Nested Routing and Child Routes by Example Angular 9 Examples: 2 Ways To Display A Component (Selector & Router) Angular 9/8 Tutorial: Http POST to Node/Express.js Example Angular 9/8 Feature and Root Modules by Example Angular 9/8 with PHP: Consuming a RESTful CRUD API with HttpClient and Forms Angular 9/8 with PHP and MySQL Database: REST CRUD Example & Tutorial Unit Testing Angular 9/8 Apps Tutorial with Jasmine & Karma by Example Angular 9 Web Components: Custom Elements & Shadow DOM Angular 9 Renderer2 with Directives Tutorial by Example Build Progressive Web Apps (PWA) with Angular 9/8 Tutorial and Example Angular 9 Internationalization/Localization with ngx-translate Tutorial and Example Create Angular 9 Calendar with ngx-bootstrap datepicker Example and Tutorial Multiple File Upload with Angular 9 FormData and PHP by Example Angular 9/8 Reactive Forms with Validation Tutorial by Example Angular 9/8 Template Forms Tutorial: Example Authentication Form (ngModel/ngForm/ngSubmit) Angular 9/8 JAMStack By Example Angular HttpClient v9/8 — Building a Service for Sending API Calls and Fetching Data Styling An Angular 9/8/7 Example App with Bootstrap 4 Navbar, Jumbotron, Tables, Forms and CardsHands-on Angular eBook
Subscribe to our Angular newsletter and get our hands-on Angular book for free!
