Skip to content

Commit 38dd178

Browse files
committed
19: add my JavaScript code
Signed-off-by: Soshi Katsuta <soshi.katsuta@gmail.com>
1 parent b250b26 commit 38dd178

File tree

3 files changed

+1963
-4
lines changed

3 files changed

+1963
-4
lines changed

19 - Webcam Fun/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<div class="photobooth">
1111
<div class="controls">
12-
<button onClick="takePhoto()">Take Photo</button>
12+
<button id="take_photo">Take Photo</button>
1313
<!-- <div class="rgb">
1414
<label for="rmin">Red Min:</label>
1515
<input type="range" min=0 max=255 name="rmin">

19 - Webcam Fun/scripts.js

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,91 @@
1-
const video = document.querySelector('.player');
2-
const canvas = document.querySelector('.photo');
1+
'use strict';
2+
3+
class Notifier {
4+
constructor() {
5+
this.handlers = [];
6+
}
7+
8+
addHandler(handler) {
9+
this.handlers.push(handler);
10+
}
11+
12+
notify() {
13+
this.handlers.forEach(handler => handler());
14+
}
15+
}
16+
17+
class Model {
18+
constructor(notifier) {
19+
this.notifier = notifier;
20+
this.snapshots = [];
21+
}
22+
23+
addHandler(handler) {
24+
this.notifier.addHandler(handler);
25+
}
26+
27+
notifyUpdate() {
28+
this.notifier.notify();
29+
}
30+
31+
addSnapshot(snapshot) {
32+
this.snapshots.push(snapshot);
33+
this.notifyUpdate();
34+
}
35+
}
36+
37+
class ViewModel {
38+
constructor(video, ctx, snap, strip) {
39+
this.video = video;
40+
this.ctx = ctx;
41+
this.snap = snap;
42+
this.strip = strip;
43+
this.model = new Model(new Notifier());
44+
45+
// get webcam video
46+
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
47+
.then(localMediaStream => {
48+
this.video.src = URL.createObjectURL(localMediaStream);
49+
this.video.play();
50+
})
51+
.catch(err => console.error(err));
52+
}
53+
54+
paintToCanvas() {
55+
// paint to canvas
56+
const { videoWidth: width, videoHeight: height } = this.video;
57+
canvas.width = width;
58+
canvas.height = height;
59+
60+
const delay = 16;
61+
return setInterval(() => this.ctx.drawImage(this.video, 0, 0, width, height), delay);
62+
}
63+
64+
takePhoto() {
65+
// sound snapshot
66+
this.snap.currentTime = 0;
67+
this.snap.play();
68+
69+
const data = canvas.toDataURL('image/jpeg');
70+
this.model.addSnapshot(data);
71+
72+
const link = document.createElement('a');
73+
link.href = data;
74+
link.setAttribute('download', 'snapshot');
75+
link.innerHTML = `<img src="${data}" alt="snapshot">`;
76+
this.strip.insertBefore(link, this.strip.firstChild);
77+
}
78+
}
79+
80+
81+
const canvas = document.querySelector('canvas.photo');
382
const ctx = canvas.getContext('2d');
83+
const video = document.querySelector('video.player');
84+
const snap = document.querySelector('audio.snap');
485
const strip = document.querySelector('.strip');
5-
const snap = document.querySelector('.snap');
86+
const vm = new ViewModel(video, ctx, snap, strip);
87+
88+
video.addEventListener('canplay', () => vm.paintToCanvas());
89+
90+
const takePhotoButton = document.querySelector('button#take_photo');
91+
takePhotoButton.addEventListener('click', () => vm.takePhoto());

0 commit comments

Comments
 (0)