Kamera i mobilen
Kamera i mobilen
Section titled “Kamera i mobilen”
Exempelprogrammet från denna övning finns i kursrepot webapp-example/camera och i webapp-example/camera. Använd det gärna tillsammans med övningen för att se hur de olika delarna hänger ihop. En del kod utelämnas i exemplet för att det ska vara mer lättläst i artikeln.
Kamera i webbläsaren
Section titled “Kamera i webbläsaren”Låt oss ta en titt på Web API:t MediaDevices och se hur vi med hjälp av funktion getUserMedia kan ta en bild.
Vi börjar med att skapa en komponent CameraComponent i filen src/components/camera.js.
export default class CameraComponent extends HTMLElement { constructor() { super();
this.photoData = ""; }
connectedCallback() { this.innerHTML = ` <div class="camera"> <video id="video">Video stream not available.</video> <button id="startbutton">Take photo</button> <button id="sendbutton">Send photo</button> </div> <canvas id="canvas"></canvas> `;
this.startup(); }}Här skapar vi först instansvariabeln photoData. Den kommer innehålla själva fotot vi tar med kameran inbyggt i mobilen eller en webkamera sedan. Sedan initierar vi den HTML vi behöver för att först få upp en video som vi sedan kan ta en bild ifrån och lägga i canvas-elementet.
När sidan är laddat anropar vi sedan funktionen startup för att sätta upp kameran och initierar EventListeners på knapparna ovan. I funktionsanropet navigator.mediaDevices.getUserMedia får vi tillbaka en video-stream som vi sedan tilldelar till video-elementet och startar. När videon startar anropas eventet canplay som vi har skapat en EventListener för i startup. I den EventListener sätter vi även storleken på videon.
startup() { let streaming = false; const width = 320; // We will scale the photo width to this let height = 0; // This will be computed based on the input stream
let video = document.getElementById("video"); let canvas = document.getElementById("canvas"); let startbutton = document.getElementById("startbutton"); let sendbutton = document.getElementById("sendbutton");
navigator.mediaDevices .getUserMedia({ video: true, audio: false }) .then((stream) => { video.srcObject = stream; video.play(); }) .catch((err) => { console.error(`An error occurred: ${err}`); });
video.addEventListener( "canplay", () => { if (!streaming) { height = video.videoHeight / (video.videoWidth / width);
// Firefox currently has a bug where the height can't be read from // the video, so we will make assumptions if this happens.
if (isNaN(height)) { height = width / (4 / 3); }
video.setAttribute("width", width); video.setAttribute("height", height); canvas.setAttribute("width", width); canvas.setAttribute("height", height); streaming = true; } }, false );
startbutton.addEventListener( "click", (ev) => { ev.preventDefault(); this.takepicture(canvas, video, width, height); }, false );
sendbutton.addEventListener( "click", (ev) => { ev.preventDefault(); this.sendpicture(); }, false );
this.clearphoto(canvas);}De resterande funktionerna i klassen finns nedan. I takepicture ritar vi ut en frame från videon som en bild i canvas-elementet. Sedan tar vi data och skapar det som kallas en dataUrl. Det är en lång base64-encoded sträng som beskriver bilden pixel för pixel. Vi sparar denna data i vår instansvariabel. clearphoto rensar canvas-elementet och sätter det till en mellangrå färg. Den kan vi se från första början på sidan.
takepicture(canvas, video, width, height) { const context = canvas.getContext("2d");
if (width && height) { canvas.width = width; canvas.height = height; context.drawImage(video, 0, 0, width, height);
this.photoData = canvas.toDataURL("image/png"); } else { this.clearphoto(canvas); }}
clearphoto(canvas) { const context = canvas.getContext("2d");
context.fillStyle = "#AAA"; context.fillRect(0, 0, canvas.width, canvas.height);
this.photoData = canvas.toDataURL("image/png");}Foto API
Section titled “Foto API”För att vi ska kunna spara undan bilderna behöver vi en plats att spara undan de på. Vi väljer UploadCare då det är gratis (upp till 5,000 uploads / mo, 15 GB traffic / mo, 1 GB storage) och det finns ett trevligt uppladdnings-API. Vi börjar med att gå till webbplatsen för tjänsten och registrerar oss. Sedan när vi har kommit in i tjänsten kopierar vi Public key från denna sidan, se till att välja API keys ute till vänster.

Vi importerar sedan upload-client längst upp i filen components/camera.js med raden import { UploadClient } from "https://cdn.jsdelivr.net/npm/@uploadcare/upload-client@6.14.1/dist/esm/index.browser.mjs";.
De med skarpa ögen såg att vi hade lagt till en eventListener på sendbutton i startup(), den anropar funktionen sendpicture.
async sendpicture() { const blob = await (await fetch(this.photoData)).blob();
const client = new UploadClient({ publicKey: '[INSERT API-KEY]' });
const fileInfo = await client.uploadFile(blob); const cdnUrl = fileInfo.cdnUrl;
console.log(cdnUrl);}I ovanstående funktion tar vi först och gör om vår dataUrl till en blob. Sedan initierar vi en UploadClient med vår API-nyckel vi kopierade från UploadCare-webbplatsen tidigare. Sedan laddar vi upp filen (kan ta en stund) och får tillbaka en url till bilden.
Avslutningsvis
Section titled “Avslutningsvis”Vi har i denna artikel använt oss av Web API:t MediaDevices för att ta bilder med våra mobila enheter. Vi har även använt ett Foto-API för att spara undan bilderna.