DEMOs

导航页

使用FF36+ compatibility table

    .getusermedia {
      .video {
        width: 90vw;
        height: 67.5vw;
        max-width: torem(600px);
        max-height: torem(450px);
        margin: 0 auto;
      }
    
      .btn {
        display: block;
        font-size: torem(14px);
        line-height: 1.5;
        padding: 0 torem(10px);
        margin-bottom: torem(10px);
      }
    
      .pip--disabled {
        display: none;
      }
    }
    
    /**
     * 摄像头操作
     */
    function getUserMedia(video) {
      if (!navigator.mediaDevices) {
        alert('Error! Use FF36+'); // eslint-disable-line no-alert
        return;
      }
    
      const detail = document.querySelector('.detail');
    
      // media devices信息
      const frag = document.createDocumentFragment();
    
      navigator.mediaDevices.enumerateDevices().then((devices) => {
        devices.forEach((device) => {
          const li = document.createElement('li');
          const info = `${device.kind}: ${device.label} id = ${device.deviceId}`;
          const text = document.createTextNode(info);
    
          li.appendChild(text);
          frag.appendChild(li);
        });
    
        detail.innerHTML = '';
        detail.appendChild(frag);
      }).catch((err) => {
        detail.innerHTML = `<li>${err.name}: ${err.message}</li>`;
      });
    
      // use
      navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
        // Older browsers may not have srcObject
        if ('srcObject' in video) {
          // MediaStream不需要创建Object URL,可直接传入video.srcObject属性
          video.srcObject = stream;
        } else {
          // Avoid using this in new browsers, as it is going away.
          const imgURL = window.URL.createObjectURL(stream);
    
          video.src = imgURL;
          video.onloadedmetadata = () => {
            window.URL.revokeObjectURL(imgURL);
          };
        }
      }).catch((err) => {
        detail.innerHTML = `<li>${err.name}: ${err.message}</li>`;
      });
    
      // snap
      document.querySelector('.snap').onclick = (e) => {
        const canvas = document.querySelector('.canvas');
        const ctx = canvas.getContext('2d');
    
        ctx.drawImage(video, 0, 0, 320, 240);
    
        e.preventDefault();
      };
    }
    
    /**
     * Picture-in-Picture
     */
    function readyPip(video) {
      const control = document.querySelector('.pip');
    
      if (!('pictureInPictureEnabled' in document)) {
        control.classList.add('pip--disabled');
        return;
      }
    
      control.onclick = async () => {
        console.log(document.pictureInPictureElement);
    
        try {
          if (video !== document.pictureInPictureElement) {
            await video.requestPictureInPicture();
          } else {
            await document.exitPictureInPicture();
          }
        } catch (err) {
          alert(err.message);
        }
      };
    
      control.textContent = '进入Picture-in-Picture';
    
      // info
      let pipWindow = null;
    
      const log = (e) => {
        console.log(`> Window size ${e.target.width}x${e.target.height}`);
      };
    
      video.addEventListener('enterpictureinpicture', (e) => {
        pipWindow = e.pictureInPictureWindow;
        log({ target: pipWindow });
    
        pipWindow.addEventListener('resize', log);
    
        control.textContent = '退出Picture-in-Picture';
      });
    
      video.addEventListener('leavepictureinpicture', () => {
        control.textContent = '进入Picture-in-Picture';
        pipWindow.removeEventListener('resize', log);
      });
    }
    
    window.onload = () => {
      const video = document.querySelector('.video');
    
      getUserMedia(video);
    
      readyPip(video);
    };