Hi folks,
I’m trying to get the rear camera of the phone with usermedia and display the live video in a canvas. this works if I start the project with ionic serve on the pc and also on the mobile phones google chrome within an Ionic app obviously. But if I run a “ionic cordova run android” I can’t see the video. How is that possible? shouln’t the app and the browser be the same?
In the app on the phone I just see a default HTML video tag with no video rendering…
My end goal: is to be able to have an app which can display the camera output in a canvas and then use the library: https://github.com/cozmo/jsQR to scan a QR code and get the coordinates of the endpoints of the QR code to be able to draw a live line on the qr code…
My HTML code:
<ion-header>
<meta charset="utf-8">
<title>jsQR Demo</title>
<link href="https://fonts.googleapis.com/css?family=Ropa+Sans" rel="stylesheet">
</ion-header>
<ion-content>
<h1 style="text-align: center">Jack's QR with User Media Test</h1>
<div #videoContainer></div>
<div #canvasContainer></div>
</ion-content>
My TS File:
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import jsQR from 'jsqr';
import { Platform } from '@ionic/angular';
import { AndroidPermissions } from '@ionic-native/android-permissions/ngx';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements AfterViewInit {
@ViewChild('videoContainer') videoContainer;
public video;
@ViewChild('canvasContainer') canvasContainer;
@ViewChild('canvasInHTML') canvasInHTML;
public canvas;
public canvasContext;
constructor(private platform: Platform, private androidPermissions: AndroidPermissions) {
this.video = document.createElement('video');
this.video.width = 640;
this.video.height = 480;
this.video.setAttribute('autoplay', '');
this.video.setAttribute('playsinline', '');
this.video.setAttribute('facingMode', 'environment');
this.canvas = document.createElement('canvas');
this.canvas.width = 640;
this.canvas.height = 480;
this.canvasContext = this.canvas.getContext('2d');
if (this.platform.is('cordova')) {
this.platform.ready().then(() => {
this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.CAMERA).then(
result => console.log('Has permission?', result.hasPermission),
err => this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.CAMERA)
);
this.androidPermissions.requestPermissions([this.androidPermissions.PERMISSION.CAMERA]).then(() => {});
});
}
}
ngAfterViewInit() {
this.videoContainer.nativeElement.appendChild(this.video);
this.canvasContainer.nativeElement.appendChild(this.canvas);
this.initWebRTC();
}
initWebRTC() {
const constraints = {
video: true,
audio: false,
facingMode: 'environment'
};
const handleSuccess = (stream: MediaStream) => {
this.video.srcObject = stream;
this.video.setAttribute('playsinline', '');
this.video.play();
// this.canvasContext.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
this.draw();
// requestAnimationFrame(this.tick);
};
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess);
}
drawLine(begin, end, color) {
this.canvasContext.beginPath();
this.canvasContext.moveTo(begin.x, begin.y);
this.canvasContext.lineTo(end.x, end.y);
this.canvasContext.lineWidth = 4;
this.canvasContext.strokeStyle = color;
this.canvasContext.stroke();
}
draw() {
// if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
this.canvas.height = this.video.videoHeight;
this.canvas.width = this.video.videoWidth;
console.log('I found a QR!');
this.canvasContext.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
const imageData = this.canvasContext.getImageData(0, 0, this.canvas.width, this.canvas.height);
const code = jsQR(imageData.data, imageData.width, imageData.height, { inversionAttempts: 'dontInvert' });
if (code) {
this.drawLine(code.location.topLeftCorner, code.location.topRightCorner, '#FF3B58');
this.drawLine(code.location.topRightCorner, code.location.bottomRightCorner, '#FF3B58');
this.drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, '#FF3B58');
this.drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, '#FF3B58');
}
// }
// requestAnimationFrame(this.tick);
}
}
My component file:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { HomePage } from './home.page';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild([
{
path: '',
component: HomePage
}
])
],
declarations: [HomePage]
})
export class HomePageModule {}
My end goal is to have an app in ionic that does the same like this demo of the jsQR library:
https://cozmo.github.io/jsQR/