Skip to content
Snippets Groups Projects
Commit 39176704 authored by Steinwender, Tamara's avatar Steinwender, Tamara
Browse files

Add QR Scanner features

parent b34e7fe2
No related branches found
No related tags found
No related merge requests found
Pipeline #13208 passed
......@@ -4,8 +4,9 @@ import DBPLitElement from 'dbp-common/dbp-lit-element';
import * as commonStyles from 'dbp-common/styles';
import {Icon, MiniSpinner} from 'dbp-common';
import {classMap} from 'lit-html/directives/class-map.js';
import QrScanner from 'qr-scanner';
import * as commonUtils from "dbp-common/utils";
import jsQR from "jsqr";
/**
* Notification web component
......@@ -14,6 +15,19 @@ export class QrCodeScanner extends DBPLitElement {
constructor() {
super();
this.lang = 'de';
this.videoRunning = false;
this.notSupported = false;
this.scanIsOk = true;
}
static get scopedElements() {
return {
'dbp-icon': Icon,
'dbp-mini-spinner': MiniSpinner,
};
}
/**
......@@ -22,6 +36,9 @@ export class QrCodeScanner extends DBPLitElement {
static get properties() {
return {
lang: { type: String },
videoRunning: { type: Boolean, attribute: false },
notSupported: { type: Boolean, attribute: false },
scanIsOk: { type: Boolean, attribute: true }
};
}
......@@ -31,10 +48,146 @@ export class QrCodeScanner extends DBPLitElement {
const that = this;
this.updateComplete.then(()=>{
QrScanner.WORKER_PATH = commonUtils.getAssetURL('dbp-qr-scanner', 'qr-scanner-worker.min.js');
const qrScanner = new QrScanner(this._('#reader'), result => console.log('decoded qr code:', result), undefined, undefined, 'user');
qrScanner.start();
// Check for support & cams
if (!!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia) && !(!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices)) {
console.log("Everything works");
this.notSupported = false;
} else {
this.notSupported = true;
console.log("not supportet");
}
let devices_map = new Map();
const that = this;
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
console.log(device.kind + ": " + device.label +
" id = " + device.deviceId);
if(device.kind === 'videoinput') {
// TODO Übersetzen
devices_map.set(device.deviceId, device.label || 'camera ' + (devices_map.size + 1));
}
});
if(devices_map.size < 1) {
that.notSupported = true;
}
for (let [id, label] of devices_map)
{
let opt = document.createElement("option");
opt.value= id;
opt.text = label;
that._('#videoSource').appendChild(opt);
}
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
that.notSupported = true;
});
});
}
qrCodeScannerInit() {
let video = document.createElement("video");
let canvasElement = this._("#canvas");
let canvas = canvasElement.getContext("2d");
let loadingMessage = this._("#loadingMessage");
let outputContainer = this._("#output");
let outputMessage = this._("#outputMessage");
let outputData = this._("#outputData");
let color = this.scanIsOk ? getComputedStyle(document.documentElement)
.getPropertyValue('--dbp-success-bg-color') : getComputedStyle(document.documentElement)
.getPropertyValue('--dbp-danger-bg-color');
function drawLine(begin, end, color) {
canvas.beginPath();
canvas.moveTo(begin.x, begin.y);
canvas.lineTo(end.x, end.y);
canvas.lineWidth = 4;
canvas.strokeStyle = color;
canvas.stroke();
}
const that = this;
// Use facingMode: environment to attemt to get the front camera on phones
navigator.mediaDevices.getUserMedia({ video: { deviceId: this._('#videoSource').val } }).then(function(stream) {
video.srcObject = stream;
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
video.play();
that.videoRunning = true;
requestAnimationFrame(tick);
const track = stream.getVideoTracks()[0];
track.applyConstraints(constraints)
.then(() => {
advanced : [{ zoom: 3 }]
// Do something with the track such as using the Image Capture API.
})
});
function tick() {
if (that.videoRunning === false) {
video.srcObject.getTracks().forEach(function(track) {
track.stop();
console.log("stop early");
loadingMessage.hidden = false;
canvasElement.hidden = true;
outputContainer.hidden = true;
});
loadingMessage.innerText = "🎥 Unable to access video stream (please make sure you have a webcam enabled)";
return;
}
loadingMessage.innerText = "⌛ Loading video..."
if (video.readyState === video.HAVE_ENOUGH_DATA) {
loadingMessage.hidden = true;
canvasElement.hidden = false;
outputContainer.hidden = false;
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
var code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: "dontInvert",
});
if (code) {
drawLine(code.location.topLeftCorner, code.location.topRightCorner, that.scanIsOk ? 'green' : 'red');
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, that.scanIsOk ? 'green' : 'red');
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, that.scanIsOk ? 'green' : 'red');
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, that.scanIsOk ? 'green' : 'red');
outputMessage.hidden = true;
outputData.parentElement.hidden = false;
outputData.innerText = code.data;
that.sendUrl(code.data);
} else {
outputMessage.hidden = false;
outputData.parentElement.hidden = true;
}
}
requestAnimationFrame(tick);
}
}
stopScanning() {
this.videoRunning = false;
}
sendUrl(url) {
const event = new CustomEvent("dbp-qr-code-scanner-url",
{ bubbles: true, composed: true , detail: url});
this.dispatchEvent(event);
}
static get styles() {
......@@ -42,21 +195,78 @@ export class QrCodeScanner extends DBPLitElement {
return css`
${commonStyles.getThemeCSS()}
${commonStyles.getGeneralCSS()}
body {
font-family: 'Ropa Sans', sans-serif;
color: #333;
max-width: 640px;
margin: 0 auto;
position: relative;
}
#loadingMessage {
text-align: center;
padding: 40px;
}
#canvas {
width: 100%;
}
#output {
margin-top: 20px;
background: #eee;
padding: 10px;
padding-bottom: 0;
}
#output div {
padding-bottom: 10px;
word-wrap: break-word;
}
#noQRFound {
text-align: center;
}
`;
}
//todo check for cam: QrScanner.hasCamera();
//start stop button
//doku
//demo
//quadrat
//check obs geht: function hasGetUserMedia() {
// // Note: Opera builds are unprefixed.
// return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
// navigator.mozGetUserMedia || navigator.msGetUserMedia);
// }
//
// if (hasGetUserMedia()) {
// // Good to go!
// } else {
// alert('getUserMedia() is not supported in your browser');
// }
render() {
return html`
<div class="columns">
<div class="column" id="qr">
<button class="start">start scanning</button>
<video id="reader"></video>
<div class="${classMap({hidden: this.notSupported})}">
<div id="loadingMessage">🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>
<button id="switch">On / Off</button>
<canvas id="canvas" hidden></canvas>
<select id="videoSource"></select>
<button class="start ${classMap({hidden: this.videoRunning})}" @click="${() => this.qrCodeScannerInit()}">start scanning</button>
<button class="stop ${classMap({hidden: !this.videoRunning})}" @click="${() => this.stopScanning()}">stop scanning</button>
<div id="output" hidden>
<div id="outputMessage">No QR code detected.</div>
<div hidden><b>Data:</b> <span id="outputData"></span></div>
</div>
</div>
<div class="${classMap({hidden: !this.notSupported})}">
Ihr device unterstützt keine video aufnahmen
</div>
</div>
</div>
`;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment