Skip to content

Instantly share code, notes, and snippets.

@sploders101
Created December 19, 2019 20:26
Show Gist options
  • Save sploders101/6ef7a9497d15c31968639d420e7c7adb to your computer and use it in GitHub Desktop.
Save sploders101/6ef7a9497d15c31968639d420e7c7adb to your computer and use it in GitHub Desktop.
Barcode scanner input component [vue] [vuetify] [instascan]
<template>
<div>
<v-text-field
v-model="syncVal"
>
<template slot="append">
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-btn
v-on="on"
@click="dialogOpen = true"
icon
x-small
>
<v-icon small>mdi-barcode-scan</v-icon>
</v-btn>
</template>
Scan QR Code
</v-tooltip>
</template>
</v-text-field>
<v-dialog
v-model="dialogOpen"
eager
>
<v-card>
<v-card-title>Barcode Scanner</v-card-title>
<v-card-text>
<v-select
v-model="camera"
:items="cameras"
/>
<center>
<video
ref="cameraPreview"
/>
</center>
</v-card-text>
</v-card>
</v-dialog>
</div>
</template>
<script lang="ts">
import {
Component,
Vue,
Prop,
Model,
Ref,
Watch,
} from "vue-property-decorator";
// Use `npm install https://github.com/schmich/instascan.git`. Currently, the npm-published version breaks on newer browsers.
import * as instascan from "instascan";
@Component({})
export default class extends Vue {
@Prop() readonly value!: string;
@Ref() readonly cameraPreview!: HTMLVideoElement;
get syncVal() { return this.value; }
set syncVal(newVal: string) { this.$emit("input", newVal); }
dialogOpen = false;
cameras: Array<{ text: string; value: instascan.Camera }> = [];
camera: instascan.Camera | null = null;
scanner: instascan.Scanner | null = null;
@Watch("dialogOpen")
async scan() {
if(this.scanner && this.camera) {
if(this.dialogOpen) {
const scannedEvent = new Promise<string>((res) => this.scanner!.once("scan", (content) => res(content)));
await this.scanner.start(this.camera);
const scanResult = await scannedEvent;
this.syncVal = scanResult;
this.dialogOpen = false;
} else {
await this.scanner.stop();
}
}
}
@Watch("camera")
async switchCamera() {
if(this.dialogOpen && this.scanner && this.camera) {
await this.scanner.stop();
await this.scanner.start(this.camera);
}
}
async mounted() {
this.cameras = (await instascan.Camera.getCameras())
.map((val) => ({
text: val.name || "Unknown Camera",
value: val,
}));
this.camera = this.cameras[0].value || null;
if(this.camera) {
this.scanner = new instascan.Scanner({
continuous: true,
video: this.cameraPreview,
mirror: false,
captureImage: false,
backgroundScan: false,
});
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment