instascan
instascan copied to clipboard
Instascan instance not displaying the video stream
in my application i have two instascan instances in two different vue.js components that lives in two different routes (pages) the code is identical but one route shows the video stream whereas the other page doesn't
in the DOM the first page have this
<video id="scanner" autoplay="autoplay" style="transform: scaleX(-1);" class="inactive" src=""></video>
whereas the second page seems that instascan is not able to mount the camera properly and i am getting this
<video id="QRscanner"></video>
I have tried to use different variable names in my components and different CSS ids but in vain
and what is strange tho is that the scanner is actually working and i am scanning the QR codes but the video stream is not showing
and it's not a CSS issue since i have checked and used background-color
for the video element and it's visible I also rose the z-index
to a big number but again nothing and i am sure it's something with instascan not able to mount properly but i can't figure out why since i am not getting any error
I have also tried to destroy the video element before leaving the rout and assign a null
value to the camera and instascan instance variable
beforeRouteLeave(to, from, next) {
EventBus.$emit('close');
this.camera = null;
this.cameras = null;
this.scanner = null;
const video = document.getElementById('scanner');
console.log(video.parentNode);
video.parentNode.removeChild(video);
next();
},
any help would be very much appreciated
Can you show your JS code
Ok here i go @mairh
<div v-show="scanning" class="QRScanner-lock" @click="scanning = false" >......</div>
<div v-show="scanning" class="QRScanner-container">
<el-select v-model="camera" placeholder="Choose a camera">
<el-option v-for="camera in cameras" :key="camera.id" :label="camera.name" :value="camera">
</el-option>
</el-select>
<video id="scanner"></video>
</div>
<el-button type="danger" style="margin: 20px;" @click="scanning = !scanning" class="button">
<icon name="qrcode" scale="2"></icon><span class="text">Scan my Barsaris</span>
</el-button>
the script part
export default {
data() {
return {
scanning: false,
scanner: null,
cameras: [],
camera: null,
};
},
beforeCreate() {
EventBus.$emit('loading-stop');
Instascan.Camera.getCameras().then((cameras) => {
this.cameras = cameras;
if (cameras.length > 0) {
this.camera = cameras[0];
this.$message({
message: `found ${cameras.length} cameras`,
type: 'success',
showClose: true,
});
} else {
this.$notify({
message: 'No camera found!',
type: 'error',
showClose: true,
});
}
}).catch((e) => {
this.$message({
message: 'an Internal error occured',
type: 'error',
showClose: true,
});
});
},
mounted() {
EventBus.$emit('loading-stop');
const that = this;
this.scanner = new Instascan.Scanner({
video: document.getElementById('scanner'),
});
this.scanner.addListener('scan', (result) => {
console.log(result);
});
},
watch: {
scanning() {
if (this.scanning === true) {
if (this.cameras.length > 0) {
this.scanner.start(this.camera);
} else {
Instascan.Camera.getCameras().then((cameras) => {
this.cameras = cameras;
if (cameras.length > 0) {
this.camera = cameras[0];
this.$message({
message: `found ${cameras.length} cameras`,
type: 'success',
showClose: true,
});
this.scanner.start(this.camera);
} else {
this.cameras = [];
this.camera = null;
this.$notify({
message: 'No camera found!',
type: 'error',
showClose: true,
});
}
}).catch((e) => {
this.$message({
message: 'Camera detection error',
type: 'error',
showClose: true,
});
});
}
} else {
this.scanner.stop(this.camera);
}
},
},
beforeRouteLeave(to, from, next) {
EventBus.$emit('close');
// TODO: if this code doesn't solve anything we need to omit it
this.camera = null;
this.cameras = null;
this.scanner = null;
const video = document.getElementById('scanner');
console.log(video.parentNode);
video.parentNode.removeChild(video);
next();
},
}
of course i have put only the part that is relevant to this question i omitted all the other code
notice that this works perfectly in the first component but doesn't on the second component where i renamed scanner
to scanner2
in the data part and renamed the video
tag id
also as i mentioned before even tho the video stream is not showing on the second component it's working perfectly and i am able to scan the QR code and i am not getting any errors
so the problem lies when the instscan instance mount on the video
tag i have tried wrapping the following snippet in a try and catch and it was clean without errors even tho the instance was not mounted properly in my opinion
this.scanner2 = new Instascan.Scanner({
video: document.getElementById('scanner'),
});
I will have a look in a while as soon as I get on my laptop.
@gimyboya Can you try to create 2 different Vue
initialization instances for your 2 separate version?
Something along the line
var app = new Vue({
el: '#instance-1',
data: {
scanner: null,
activeCameraId: null,
cameras: [],
scans: []
},
mounted: function () {
// Something
},
methods: {
// Something
}
});
and
var app = new Vue({
el: '#instance-2',
data: {
scanner: null,
activeCameraId: null,
cameras: [],
scans: []
},
mounted: function () {
// Something
},
methods: {
// Something
}
});
and wrap your html on 2 different routes like this
<div id="instance-1">
// Your html code
</div>
and
<div id="instance-2">
// Your html code
</div>
try with