點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Vue-web-cam 控制 Camera

Sam Xiao's Avatar 2020-08-22

HTML 5 已經內建支援 Camera,Vue-web-cam 將 HTML 5 API 封裝成更適合 Vue 使用,還可以選擇內建 Camera 或者 USB Camera,更支援 Mobile Browser。

Version

macOS Catalina 10.15.6
WebStorm 2020.2
Vue 2.6.11
Vue-web-cam 1.9.0

Install Package

$ yarn add vue-web-cam

使用 Yarn 安裝 vue-web-cam。

Vue-web-cam

<template>
  <div>
    <div>
      <web-cam ref="webcam" :device-id="deviceId" width="100%" @cameras="onCameras" @video-live="onVideoLive" @error="onError"/>
    </div>
    <div>
      <select v-model="deviceId">
        <option>-- Select Device --</option>
        <option v-for="device in devices" :key="device.deviceId" :value="device.deviceId">{{ device.label }}</option>
      </select>
      <button type="button" @click="onStart">Start Camera</button>
      <button type="button" @click="onStop">Stop Camera</button>
      <button type="button" @click="onCapture">Capture Photo</button>
    </div>
    <div>
      <img :src="img" class="img-responsive"/>
    </div>
  </div>
</template>

<script>
import { WebCam } from 'vue-web-cam'

let onCameras = function(cameras) {
  this.devices = cameras
  console.log('On Cameras Event', cameras)
  this.deviceId = this.devices[0]?.deviceId
}

let onVideoLive = function(stream) {
  console.log("On VideoLive Event", stream)
}

let onStart = function() {
  this.$refs.webcam.start()
}

let onStop = function() {
  this.$refs.webcam.stop()
}

let onCapture = function() {
  this.img = this.$refs.webcam.capture()
}

let onError = function(error) {
  console.log('On Error Event', error)
}

let beforeDestroy = function() {
  this.$refs.webcam.stop()
}

export default {
  name: 'App',
  components: {
    WebCam
  },
  data: () => ({
    img: null,
    deviceId: null,
    devices: []
  }),
  methods: {
    onCameras,
    onVideoLive,
    onStart,
    onStop,
    onCapture,
    onError
  },
  beforeDestroy
}
</script>

22 行

import { WebCam } from 'vue-web-cam'

Vue-web-cam 並不需要在 main.js 以 global 引用,只要在要用的 component 引用 即可。

60 行

components: {
  WebCam
},

宣告 WebCam component。

第 4 行

<web-cam ref="webcam" :device-id="deviceId" width="100%" @cameras="onCameras" @video-live="onVideoLive" @error="onError"/>

在 HTML template 使用 WebCam

  • ref 為必須,稍後要使用 ref 控制 Vue-web-cam
  • device-id property 為必須,所有控制必須要指定 device-id 才能運作
  • width=100% 時,表示由 container 決定寬度

Event 部分則非必須,可依照需求選用。

第 7 行

<select v-model="deviceId">
  <option>-- Select Device --</option>
  <option v-for="device in devices" :key="device.deviceId" :value="device.deviceId">{{ device.label }}</option>
</select>

若要提供 user 選擇 camera,亦可由 Vue-web-cam 提供 devices 顯示所有 camera,包含內建 camera 與 USB camera 都可抓到,並將 deviceId 綁定到 <select>,如此可立即將所選定 camera 綁定到 Vue-web-cam。

24 行

let onCameras = function(cameras) {
  this.devices = cameras
  console.log('On Cameras Event', cameras)
  this.deviceId = this.devices[0]?.deviceId
}

Vue-web-cam 首先觸發 cameras event,將傳回所有抓到的 camera,可綁定到 devices model 顯示所有 camera。

deviceId model 將綁定到 WebCam component 的 deviceId property,因此將 devices[0] 取得第一台 camera。

因為 user 可能根本沒有 camera,所以 devices[0]undefined,特別使用 ?. optional chaining operator 避免 runtime error。

46 行

let onError = function(error) {
  console.log('On Error Event', error)
}

若 user 沒有 camera 將觸發 error event。

30 行

let onVideoLive = function(stream) {
  console.log("On VideoLive Event", stream)
}

當 Vue-web-cam 開始顯示 stream 時,將觸發 videolive event,如取消顯示 loading 可寫在此。

38 行

let onStop = function() {
  this.$refs.webcam.stop()
}

可使用 this.$refs.webcam.stop() 停止 camera,可發現 camera 顯示燈不亮。

由於使用了 $refs.webcam 控制,因此 Vue-web-cam 一樣要使用 ref

34 行

let onStart = function() {
  this.$refs.webcam.start()
}

可使用 this.$refs.webcam.start() 將停止 camera 重新啟動,可發現 camera 顯示燈亮起。

42 行

let onCapture = function() {
  this.img = this.$refs.webcam.capture()
}

可使用 this.$refs.webcam.capture() 擷取 camera 影像,回傳為 Base64 String。

61 行

let beforeDestroy = function() {
  this.$refs.webcam.stop()
}

最後在 beforeDestroy hook 將 camera stop,可在切換到其它 route 前先行 stop camera。

Conclusion

  • 本範例是以 官方範例 改編而成,原範例使用了 watch,使了整個範例難度提高不少,事實上 watch 並非必須,本範例完全將 watch 移除,更能清楚展現如何使用 Vue-web-cam

Reference

VinceG, vue-web-cam