# How to Use a Web API

This tutorial explains how to use the [MediaDevices API ](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices)to capture pictures using the device camera in a sample application.

## Electron TODO app

### Creating the app

First of all, let's create the application with a Monaca template. From the Monaca dashboard, go to **Create New Project → Sample Applications**. Then choose **Electron TODO App** from the template list, fill in the `Project Name` and `Description` and click **Create Project**.

<div align="center"><img src="/files/-MgF8hIbQP7ceOylGCkN" alt=""></div>

### Application features

This sample application allows users to create and manage a to do list. The user can add pictures by uploading an existing picture or taking a picture. The list is saved in the local storage.

{% hint style="info" %}
This tutorial focuses on explaining how we use the MediaCapture API to take pictures using the built-in camera.
{% endhint %}

Once you open the application, it displays the items saved in the local storage.

![Application dashboard](/files/-MgIkA0pcLHykwguITrh)

To create a new item, click the **+ new** button on the top right corner of the screen. A new modal dialog will open. You can input a description to the text field and upload an existing picture with the :frame\_photo: button or take a new picture by clicking the :camera: button.

![Add a new item](/files/-MgIkIY-GFZAOzfga75n)

Once the :camera: button is clicked, another modal dialog with the camera view opens. If you press `capture`, it will capture a photo and save it.

![ Taking a picture using the laptop camera](/files/-MgIkQBWPZANQEDMpQDO)

## HTML explanation

### Camera modal

The following code snippet is the camera modal. This modal opens when the `camera` button is clicked. It has 3 buttons - `rotate`, `capture` , and `cancel`. The `rotate` button is only visible if the device supports flipping between the `front` and `rear` cameras. The `video-container` element is used to stream pictures from the built-in camera.

```markup
<div class="modal fade" id="camera-modal" tabindex="-1" data-backdrop="static" role="dialog" aria-labelledby="camera-modal-label" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="camera-header-modal"></div>
            <div class="camera-modal-body modal-body text-center">
                <video id="video-container" class="camera-preview" autoplay></video>
            </div>
            <a id="cordova-camera-cancel" class="btn enabled camera-close-btn" data-dismiss="modal"><i class="fa fa-times"></i> cancel</a>
            <a id="rotate-camera" class="btn enabled camera-rotate-btn"><i class="fa fa-sync"></i> Rotate</a>
            <a id="camera-capture" class="btn enabled camera-capture-btn" data-dismiss="modal"><i class="fa fa-camera"></i> Capture</a>
        </div>
    </div>
</div>
```

## JavaScript explanation

### Global variable declaration

Let's go quickly through some of the most important variables used in the camera feature:

* `isFrontCamera` is used to toggle between front and rear camera.
* `FRONT_CAMERA` is used to store the front camera value of the mediaDevices API’s [facingModeEnum.](https://w3c.github.io/mediacapture-main/#dom-videofacingmodeenum)
* `REAR_CAMERA` is used to store the rear camera value of the mediaDevices API’s facingModeEnum.

```javascript
let isFrontCamera;
const FRONT_CAMERA = 'user';
const REAR_CAMERA = 'environment';
const videoContainer = document.getElementById('video-container');
const btnOpenCameraModal = document.getElementById('open-camera-modal');
const btnRotateCamera = document.getElementById('rotate-camera');
...
```

### Checking if the mediaDevices API is supported

The following code snippet is to check whether the mediaDevices API is supported and to display the `rotate` button if the device is Android and use the `rear` camera as default.

```javascript
function initialize() {
  // Check if getUserMedia is supported on the device
  if (!hasMediaDevicesApi()) {
    btnOpenCameraModal.hidden = true;
  }
  if (isAndroidOS()) {
    // use rear camera for android
    btnRotateCamera.hidden = false;
    isFrontCamera = false;
  } else {
    // use front camera for browser/electron
    btnRotateCamera.hidden = true;
    isFrontCamera = true;
  }
  ...
}

function hasMediaDevicesApi() {
  return !!(navigator.mediaDevices &&
    navigator.mediaDevices.getUserMedia);
}
```

### Turning the camera on/off

We will use the function `getUserMedia()` to ask the user for the permission to use the media input that forms the `MediaStream`. The stream can contain video (such as camera, video recording device, screen sharing service, etc), audio, or other media. For more details, please refer to the [official document](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices). The syntax is as following:

```javascript
var promise = navigator.mediaDevices.getUserMedia(constraints);
```

The function returns a [promise ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)and accepts a [MediaStreamConstraints ](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints)object as a parameter.

In the following code snippet, we specify the width and height of the `video` element to be exactly `250` pixels and set the camera facing mode based on the provided argument. Once the camera device is connected, the [Media Stream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream) object is returned and assigned to the `video` element.

```javascript
function turnOnCamera(frontCamera) {
  const facingModeOption = frontCamera ? FRONT_CAMERA : REAR_CAMERA;
  const constraints = {
    video: {
      width: {
        exact: 250
      },
      height: {
        exact: 250
      },
      facingMode: facingModeOption
    }
  };
  // Access to the camera and turn it own
  navigator.mediaDevices.getUserMedia(constraints)
    .then(handleSuccess)
    .catch(handleError);

  function handleSuccess(stream) {
    videoContainer.srcObject = stream;
  }

  function handleError(error) {
    alert('Could not get user media API' + JSON.stringify(error));
  }
}
```

To turn off the camera, we need to stop all the sources associated with the video stream.

```javascript
function turnOfCamera() {
  if (videoContainer && videoContainer.srcObject) {
    videoContainer.srcObject.getTracks().forEach(function(track) {
      track.stop();
    });
    videoContainer.srcObject = null;
  }
}
```

The function below flips the camera between the front and rear view.

```javascript
function rotateCamera(e) {
  isFrontCamera = !isFrontCamera;
  turnOfCamera();
  turnOnCamera(isFrontCamera);
}
```

### Capturing a photo

To capture a photo of the video stream, we first create a `canvas` element whose width and height are the same as the `video` element. Then, we stop the stream and convert the last capture of it to image format.

```javascript
function takePicture(e) {
  const canvas = document.createElement('canvas');
  // Saving current image
  canvas.width = videoContainer.videoWidth;
  canvas.height = videoContainer.videoHeight;
  canvas.getContext('2d').drawImage(videoContainer, 0, 0);
  // If the video source Object is set, stop all tracks
  if (videoContainer.srcObject) {
    videoContainer.srcObject.getTracks().forEach(function(track) {
      track.stop();
      try {
        // Other browsers will fall back to image/png
        todoItemImage.src = canvas.toDataURL('image/webp');
      } catch (error) {
        alert('Could not get the picture.' + JSON.stringify(error));
      }
    });
  }
}
```

See Also:

* [Building for Electron](/products_guide/monaca_ide/build/electron.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://en.docs.monaca.io/tutorials/cordova_electron/use_web_api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
