How to Control Camera Zoom with JavaScript
Using the getUserMedia
API, we can open cameras on the web with JavaScript. Starting from Chrome 87, it is also possible to control the camera’s pan
, tilt
, and zoom
, giving more possibilities for making a camera web app.
In this article, we are going to talk about how to control camera zoom on the web. We will create a demo directly using getUserMedia
and another demo using Dynamsoft Camera Enhancer.
The zoom control feature is only available on Android’s Chrome or browsers with a Chrome kernel. Dynamsoft Camera Enhancer enables zoom on browsers that do not have this feature using a simulated method.
Demo video:
This article is Part 1 in a 2-Part Series.
Control Camera Zoom in a Web App
Let’s do this in steps.
Open the Camera with getUserMedia
-
Create a new HTML file with the following template:
<!DOCTYPE html> <html> <head> <title>Camera Zoom Demo</title> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" /> <style> video { max-width: 100%; } </style> </head> <body> <h2>Camera Zoom Demo</h2> <label> Camera: <select id="select-camera"></select> </label> <label> Resolution: <select id="select-resolution"> <option value="640x480">640x480</option> <option value="1280x720">1280x720</option> <option value="1920x1080" selected>1920x1080</option> <option value="3840x2160">3840x2160</option> </select> </label> <button onclick="startCamera();">Start Camera</button> <br/> <video id="video" muted autoplay="autoplay" playsinline="playsinline" webkit-playsinline></video> <script type="text/javascript"> </script> </body> </html>
-
Request camera permission.
async function requestCameraPermission() { try { const constraints = {video: true, audio: false}; const stream = await navigator.mediaDevices.getUserMedia(constraints); closeStream(stream); } catch (error) { console.log(error); throw error; } } function closeStream(stream){ if (stream) { const tracks = stream.getTracks(); for (let i=0;i<tracks.length;i++) { const track = tracks[i]; track.stop(); // stop the opened tracks } } }
-
List cameras.
let cameras = [] async function listCameras(){ let cameraSelect = document.getElementById("select-camera"); let allDevices = await navigator.mediaDevices.enumerateDevices(); for (let i = 0; i < allDevices.length; i++){ let device = allDevices[i]; if (device.kind == 'videoinput'){ cameras.push(device); cameraSelect.appendChild(new Option(device.label,device.deviceId)); } } }
-
Start the selected camera with the desired resolution.
async function startCamera(){ let selectedCamera = cameras[document.getElementById("select-camera").selectedIndex]; closeStream(document.getElementById("video").srcObject); let selectedResolution = document.getElementById("select-resolution").selectedOptions[0].value; let width = parseInt(selectedResolution.split("x")[0]); let height = parseInt(selectedResolution.split("x")[1]); const videoConstraints = { video: {width:width, height:height, deviceId: selectedCamera.deviceId}, audio: false }; const cameraStream = await navigator.mediaDevices.getUserMedia(videoConstraints); document.getElementById("video").srcObject = cameraStream; }
Enable Camera Zoom
-
First, check whether the browser supports the zoom feature.
function checkBrowserCapabilities(){ if (navigator.mediaDevices.getSupportedConstraints().zoom) { console.log("Browser supports zoom"); }else{ alert("The browser does not support zoom."); } }
-
Check whether the selected camera supports zoom. If it is supported, load the range of zoom.
function checkCameraCapabilities(){ const video = document.querySelector('video'); const videoTracks = video.srcObject.getVideoTracks(); track = videoTracks[0]; let capabilities = track.getCapabilities(); console.log(capabilities); if ('zoom' in capabilities) { let min = capabilities["zoom"]["min"]; let max = capabilities["zoom"]["max"]; document.getElementById("zoomInput").setAttribute("min",min); document.getElementById("zoomInput").setAttribute("max",max); document.getElementById("zoomInput").value = 1; }else{ alert("This camera does not support zoom"); } }
An input is added to set the zoom of the camera.
<label> Zoom Factor: <input type="number" min="0" max="2" id="zoomInput" value="0" onchange="setZoom();"> </label>
-
Set the zoom if the factor is updated.
async function setZoom(){ let expectedZoom = document.getElementById("zoomInput").value; const constraints = {advanced: [{zoom: expectedZoom}]}; await track.applyConstraints(constraints); }
Using Dynamsoft Camera Enhancer
Dynamsoft Camera Enhancer is a library which makes it easier to control the camera and has features to enhance the camera. It is based on getUserMedia internally.
Here are the equivalent functions using Dynamsoft Camera Enhancer v4:
-
List the cameras.
let cameras = await cameraEnhancer.getAllCameras();
-
Open the selected camera with the desired resolution.
let selectedCamera = cameras[document.getElementById("select-camera").selectedIndex]; let selectedResolution = document.getElementById("select-resolution").selectedOptions[0].value; let width = parseInt(selectedResolution.split("x")[0]); let height = parseInt(selectedResolution.split("x")[1]); await cameraEnhancer.selectCamera(selectedCamera); await cameraEnhancer.setResolution({width:width, height:height}); await cameraEnhancer.open();
-
Get zoom range.
let zoomRange = cameraEnhancer.getAutoZoomRange();
-
Set zoom.
let expectedZoom = document.getElementById("zoomInput").value; cameraEnhancer.setZoom({factor: parseFloat(expectedZoom)});
An advantage of using Dynamsoft Camera Enhancer is that its zoom function supports all browsers. If the browser does not support zoom natively, it will simulate the zoom behavior using CSS and WebGL.
Source Code
Get the source code of the demos to have a try: