2025-01-16 03:27:33 +01:00
|
|
|
<!--- this is the main file --->
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<header>
|
|
|
|
|
<link href="bootstrap-5.0.2-dist/css/bootstrap.min.css" rel="stylesheet" ></link>
|
|
|
|
|
<script src="bootstrap-5.0.2-dist/js/bootstrap.bundle.min.js" ></script>
|
2025-01-23 14:18:10 +01:00
|
|
|
<meta charset="utf-8">
|
2025-01-16 03:27:33 +01:00
|
|
|
<style>
|
2025-01-17 03:44:56 +01:00
|
|
|
#output{
|
|
|
|
|
position: relative;
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
#video_container{
|
|
|
|
|
position: relative;
|
|
|
|
|
}
|
2025-01-16 03:27:33 +01:00
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
#video {
|
|
|
|
|
position:absolute;
|
|
|
|
|
z-index: 9;
|
2025-01-23 14:28:58 +01:00
|
|
|
width: 90%;
|
2025-01-17 03:44:56 +01:00
|
|
|
}
|
2025-01-16 03:27:33 +01:00
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
#canvas-draw{
|
|
|
|
|
position:absolute;
|
|
|
|
|
z-index:10;
|
2025-01-23 14:28:58 +01:00
|
|
|
width: 90%;
|
2025-01-17 03:44:56 +01:00
|
|
|
}
|
2025-01-16 03:27:33 +01:00
|
|
|
|
2025-01-23 14:28:58 +01:00
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
#photo {
|
|
|
|
|
position:absolute;
|
|
|
|
|
z-index:5;
|
|
|
|
|
width: 100%;
|
2025-01-16 03:27:33 +01:00
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#canvas-temp{
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#control-elements {
|
|
|
|
|
height:30em;
|
|
|
|
|
}
|
2025-01-16 03:27:33 +01:00
|
|
|
</style>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<body>
|
2025-02-25 18:12:30 +01:00
|
|
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
|
|
|
|
<div class="container-fluid">
|
|
|
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
|
|
|
|
|
<span class="navbar-toggler-icon"></span>
|
|
|
|
|
</button>
|
|
|
|
|
<a class="navbar-brand" href="#">Open Microscopy App</a>
|
|
|
|
|
<div class="collapse navbar-collapse" id="navbarTogglerDemo03">
|
|
|
|
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
|
|
|
|
<li class="nav-item dropdown">
|
|
|
|
|
<a class="nav-link dropdown-toggle" href="#" id="navbarScrollingDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
|
|
|
Settings
|
|
|
|
|
</a>
|
|
|
|
|
<ul class="dropdown-menu" aria-labelledby="navbarScrollingDropdown">
|
|
|
|
|
<li><a class="dropdown-item" href="/setup_microscope.html">Setup Camera</a></li>
|
|
|
|
|
<li><a class="dropdown-item" href="/sample_prep_protocol.html">Setup Preparation Protocol</a></li>
|
|
|
|
|
<li><hr class="dropdown-divider"></li>
|
|
|
|
|
<li><a class="dropdown-item" href="#">Defaults</a></li>
|
|
|
|
|
</ul>
|
|
|
|
|
</li>
|
|
|
|
|
<li class="nav-item">
|
|
|
|
|
<a class="nav-link active" aria-current="page" href="/sample_intake.html">add sample</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li class="nav-item dropdown">
|
|
|
|
|
<a class="nav-link dropdown-toggle" href="#" id="navbarScrollingDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
|
|
|
Observe
|
|
|
|
|
</a>
|
|
|
|
|
<ul class="dropdown-menu" aria-labelledby="navbarScrollingDropdown">
|
|
|
|
|
<li><a class="dropdown-item" href="/observe_nema.html">Nematodes</a></li>
|
|
|
|
|
<li><a class="dropdown-item" href="/observe_main.html">Filamentous and Protozoa</a></li>
|
|
|
|
|
<li><a class="dropdown-item" href="/observe_bact.html">Bacteria</a></li>
|
|
|
|
|
</ul>
|
|
|
|
|
</li>
|
|
|
|
|
<li class="nav-item">
|
|
|
|
|
<a class="nav-link" href="/create_report.html">generate report</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</nav>
|
2025-01-16 03:27:33 +01:00
|
|
|
<div class = "container">
|
2025-02-25 18:12:30 +01:00
|
|
|
<h1> Setup Microscope & Camera </h1>
|
2025-01-16 03:27:33 +01:00
|
|
|
<canvas id="canvas-temp"></canvas>
|
|
|
|
|
|
|
|
|
|
<!-- the output div is used to display the video, the photo and the canvas where you can draw in (and measure) your organisms. -->
|
|
|
|
|
<div id="output" class="row">
|
|
|
|
|
<div id = "video_container" class="col-8">
|
|
|
|
|
<canvas id="canvas-draw"></canvas>
|
|
|
|
|
<img id="photo" alt="The screen capture will appear in this box."></img>
|
|
|
|
|
<video autoplay="true" id="video"></video>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-4 ">
|
2025-01-23 14:32:23 +01:00
|
|
|
|
|
|
|
|
<label class = "form-label" for="camera_chooser">
|
|
|
|
|
Select a Camera
|
|
|
|
|
</label>
|
|
|
|
|
<select class="form-select" aria-label="Default select example" name="camera_chooser" id = "camera_chooser">
|
|
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
<div id="control_elements" class="row align-items-end">
|
|
|
|
|
<div class="col" name="length" >
|
|
|
|
|
<label class = "form-label" for="real_length">
|
|
|
|
|
Please enter the length of the object in um:
|
2025-01-16 03:27:33 +01:00
|
|
|
</label>
|
2025-01-17 03:44:56 +01:00
|
|
|
<input class="form-control" id = "real_length" type="text"
|
|
|
|
|
name="real_length" value=0>
|
2025-01-16 03:27:33 +01:00
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<br>
|
2025-01-17 03:44:56 +01:00
|
|
|
<form class="needs-validation" id = "microscope_setup">
|
2025-01-16 03:27:33 +01:00
|
|
|
<div class="row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<label class = "form-label" for="name">
|
|
|
|
|
Name of Setup
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<input class="form-control" type="text" name="name" id = "name"
|
|
|
|
|
placeholder="e.g. camera">
|
|
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-01-23 14:33:03 +01:00
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
<div class="row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<label class = "form-label" for="FoV_Width">
|
|
|
|
|
Width of Field of View (Camera) [um]
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<input class="form-control" type="number" id="FoV_width"
|
|
|
|
|
name="FoV_Width">
|
|
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<label class = "form-label" for="FoV_Height">
|
|
|
|
|
Height of Field of View (Camera) [um]
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<input class="form-control" type="number"
|
|
|
|
|
id="FoV_height" name="FoV_Height">
|
|
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<label class = "form-label" for="Slip_Height">
|
|
|
|
|
Height of Coverslip [mm]
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<input class="form-control" type="number"
|
2025-01-23 14:19:06 +01:00
|
|
|
id="Slip_height" step="0.1" name="Slip_Height">
|
2025-01-16 03:27:33 +01:00
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<label class = "form-label" for="Slip_Width">
|
|
|
|
|
Width of Coverslip [mm]
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<input class="form-control" type="number"
|
2025-01-23 14:19:06 +01:00
|
|
|
id="Slip_width" step="0.1" name="Slip_Width">
|
2025-01-16 03:27:33 +01:00
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-01-23 14:32:23 +01:00
|
|
|
<div class="row">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<label class = "form-check-label" for="default">
|
|
|
|
|
This should be the default Camera setup
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<input class="form-check-input" type="checkbox" id = "Default" name="default">
|
|
|
|
|
</input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-01-17 03:44:56 +01:00
|
|
|
<button class="btn btn-primary float-end" type="submit">submit</button>
|
2025-01-16 03:27:33 +01:00
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
|
|
|
|
var db;
|
|
|
|
|
let openRequest = indexedDB.open("my_db");
|
|
|
|
|
|
|
|
|
|
openRequest.onerror = function() {
|
|
|
|
|
console.error("Error", openRequest.error);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
openRequest.onsuccess = function() {
|
|
|
|
|
db = openRequest.result;
|
|
|
|
|
// continue working with database using db object
|
|
|
|
|
};
|
2025-01-17 03:44:56 +01:00
|
|
|
|
|
|
|
|
const form = document.getElementById("microscope_setup");
|
|
|
|
|
form.addEventListener("submit", add);
|
|
|
|
|
|
|
|
|
|
function add(event){
|
2025-01-23 14:32:23 +01:00
|
|
|
event.preventDefault();
|
|
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
let microscope_setup = {
|
|
|
|
|
"name" : document.getElementById("name").value,
|
|
|
|
|
"FoV_Height" : document.getElementById("FoV_height").value,
|
|
|
|
|
"FoV_Width" : document.getElementById("FoV_width").value,
|
|
|
|
|
"Slip_Height" : document.getElementById("Slip_height").value,
|
2025-01-23 14:32:23 +01:00
|
|
|
"Slip_Width" : document.getElementById("Slip_width").value,
|
|
|
|
|
"video_prefs" : video_prefs,
|
2025-01-16 03:27:33 +01:00
|
|
|
}
|
2025-01-23 14:32:23 +01:00
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
let transaction = db.transaction(["microscope_setup"], "readwrite");
|
|
|
|
|
let objectStore = transaction.objectStore("microscope_setup");
|
|
|
|
|
let add_request = objectStore.add(microscope_setup); // (3)
|
2025-01-23 14:32:23 +01:00
|
|
|
add_request.onsuccess = (event) => {
|
2025-01-16 03:27:33 +01:00
|
|
|
console.log("All done!");
|
2025-01-23 14:32:23 +01:00
|
|
|
let id_of_setup = event.target.result;
|
|
|
|
|
if (document.getElementById("Default").checked){
|
|
|
|
|
let my_default = {"id" : 0, "microscope_setup" : id_of_setup};
|
|
|
|
|
let next_transaction = db.transaction(["defaults"], "readwrite");
|
|
|
|
|
let next_objectStore = next_transaction.objectStore("defaults");
|
|
|
|
|
let add_next_request = next_objectStore.put(my_default);
|
|
|
|
|
transaction.oncomplete = (event) => {
|
|
|
|
|
console.log("All done!");
|
|
|
|
|
};
|
|
|
|
|
transaction.onerror = (event) => {
|
|
|
|
|
console.log("something went wrong");
|
|
|
|
|
// Don't forget to handle errors!
|
|
|
|
|
};
|
|
|
|
|
}
|
2025-01-16 03:27:33 +01:00
|
|
|
};
|
2025-01-23 14:32:23 +01:00
|
|
|
add_request.onerror = (event) => {
|
2025-01-16 03:27:33 +01:00
|
|
|
console.log("something went wrong");
|
|
|
|
|
// Don't forget to handle errors!
|
|
|
|
|
};
|
2025-01-23 14:32:23 +01:00
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
}
|
2025-01-23 14:32:23 +01:00
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
var video = document.querySelector("#video");
|
|
|
|
|
var out = document.querySelector("#output");
|
2025-01-23 14:32:23 +01:00
|
|
|
var camera_chooser = document.querySelector("#camera_chooser")
|
2025-01-16 03:27:33 +01:00
|
|
|
// init video switching get IDs of video inputs
|
2025-01-23 14:32:23 +01:00
|
|
|
let video_prefs={ video: {width: { ideal: 99999} , height: { ideal: 99999 }}, audio: false };
|
|
|
|
|
let streaming = false;
|
|
|
|
|
let index = 1;
|
2025-01-16 03:27:33 +01:00
|
|
|
navigator.mediaDevices
|
|
|
|
|
.enumerateDevices()
|
|
|
|
|
.then((devices) => {
|
|
|
|
|
devices.forEach((device) => {
|
|
|
|
|
if (device.kind=="videoinput"){
|
2025-01-23 14:32:23 +01:00
|
|
|
let cameraID = document.createElement("option");
|
|
|
|
|
let text = document.createTextNode("camera " + index);
|
|
|
|
|
if (index == 1){
|
|
|
|
|
video_prefs.video.deviceId = device.deviceId;
|
|
|
|
|
cameraID.defaultSelected = true;
|
|
|
|
|
}
|
|
|
|
|
++index;
|
|
|
|
|
cameraID.value = device.deviceId;
|
|
|
|
|
cameraID.appendChild(text);
|
|
|
|
|
camera_chooser.appendChild(cameraID);
|
|
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
console.error(`${err.name}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-23 14:32:23 +01:00
|
|
|
camera_chooser.addEventListener("change", change_cam);
|
|
|
|
|
function change_cam(){
|
|
|
|
|
video_prefs.video.deviceId = this.value;
|
|
|
|
|
startup();
|
2025-01-16 03:27:33 +01:00
|
|
|
};
|
|
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
var real_dimensions = document.querySelector("#real_dimensions");
|
|
|
|
|
var fov_width = document.querySelector("#FoV_width");
|
|
|
|
|
var fov_height = document.querySelector("#FoV_height");
|
|
|
|
|
var real_length = document.querySelector("#real_length");
|
2025-01-16 03:27:33 +01:00
|
|
|
|
|
|
|
|
// init drawing
|
|
|
|
|
var canvas_draw = document.querySelector("#canvas-draw");
|
|
|
|
|
var ctx = canvas_draw.getContext('2d');
|
|
|
|
|
var pos = { x: 0, y: 0 };
|
|
|
|
|
var start_pos = { x: 0, y: 0 };
|
|
|
|
|
// store lines for measurement
|
|
|
|
|
var lines = [];
|
|
|
|
|
var line = [];
|
|
|
|
|
|
|
|
|
|
// calculate length of line - helper function
|
|
|
|
|
function get_length(line){
|
|
|
|
|
var dist = 0.0;
|
|
|
|
|
if (line){
|
|
|
|
|
for (let j = 0; j < line.length-1; ++j) {
|
|
|
|
|
dist += Math.sqrt((line[j].x - line[j+1].x) ** 2 + (line[j].y - line[j+1].y) ** 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//return distance in units
|
|
|
|
|
return dist/canvas_draw.width
|
|
|
|
|
}
|
|
|
|
|
// events to set the position of the drawing cursor
|
|
|
|
|
canvas_draw.addEventListener('mousedown', setPosition);
|
|
|
|
|
canvas_draw.addEventListener('mouseenter', setPosition);
|
|
|
|
|
|
|
|
|
|
// set new position from mouse event
|
|
|
|
|
// scale canvas coords
|
|
|
|
|
function setPosition(e) {
|
|
|
|
|
var rect = canvas_draw.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
scaleX = canvas_draw.width / rect.width, // relationship bitmap vs. element for x
|
|
|
|
|
scaleY = canvas_draw.height / rect.height;
|
|
|
|
|
pos.x = (e.clientX - rect.x) * scaleX;
|
|
|
|
|
pos.y = (e.clientY - rect.y) * scaleY;
|
|
|
|
|
console.log(pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// the draw function to draw onto canvas
|
|
|
|
|
canvas_draw.addEventListener('mousemove', draw);
|
|
|
|
|
|
|
|
|
|
function draw(e) {
|
|
|
|
|
// mouse left button must be pressed and video must be hidden / a photo must have been taken.
|
|
|
|
|
if (e.buttons !== 1 && line.length !== 0) {
|
|
|
|
|
// push the line to lines array
|
|
|
|
|
console.log('Yay');
|
2025-01-17 03:44:56 +01:00
|
|
|
line.push({x: pos.x, y: pos.y});
|
|
|
|
|
let measured_length = get_length(line);
|
2025-01-23 14:33:03 +01:00
|
|
|
fov_height.value = ((real_length.value/(measured_length * canvas_draw.width))* canvas_draw.height).toFixed(0);
|
|
|
|
|
fov_width.value = ((real_length.value/(measured_length * canvas_draw.width))* canvas_draw.width).toFixed(0);
|
2025-01-16 03:27:33 +01:00
|
|
|
|
2025-01-17 03:44:56 +01:00
|
|
|
line = [];
|
|
|
|
|
return;
|
2025-01-16 03:27:33 +01:00
|
|
|
}
|
|
|
|
|
// draw on canvas.
|
|
|
|
|
if (e.buttons == 1){
|
|
|
|
|
|
|
|
|
|
canvas_draw.getContext('2d').clearRect(0, 0, canvas_draw.width, canvas_draw.height);
|
|
|
|
|
if (lines.length == 1){
|
|
|
|
|
draw_path(lines[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.beginPath(); // begin
|
2025-01-17 03:44:56 +01:00
|
|
|
ctx.lineWidth = 5;
|
2025-01-16 03:27:33 +01:00
|
|
|
ctx.lineCap = 'round';
|
|
|
|
|
ctx.strokeStyle = 'black';
|
|
|
|
|
// update line
|
|
|
|
|
// first time push the first position
|
|
|
|
|
if (line.length == 0){
|
|
|
|
|
start_pos = {x:pos.x, y:pos.y};
|
|
|
|
|
line.push(start_pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.moveTo(start_pos.x, start_pos.y); // from
|
|
|
|
|
setPosition(e);
|
2025-01-17 03:44:56 +01:00
|
|
|
ctx.lineTo(pos.x, pos.y); // to
|
|
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
ctx.stroke(); // draw it!
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 14:32:23 +01:00
|
|
|
startup();
|
|
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
|
|
|
|
|
function startup() {
|
|
|
|
|
output = document.getElementById("output");
|
|
|
|
|
video = document.getElementById("video");
|
|
|
|
|
canvas = document.getElementById("canvas-temp");
|
|
|
|
|
photo = document.getElementById("photo");
|
|
|
|
|
startButton = document.getElementById("start-button");
|
|
|
|
|
|
|
|
|
|
navigator.mediaDevices
|
2025-01-23 14:32:23 +01:00
|
|
|
.getUserMedia(video_prefs)
|
2025-01-16 03:27:33 +01:00
|
|
|
.then((stream) => {
|
|
|
|
|
video.srcObject = stream;
|
|
|
|
|
video.play();
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
console.error(`An error occurred: ${err}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
video.addEventListener(
|
|
|
|
|
"canplay",
|
|
|
|
|
(ev) => {
|
|
|
|
|
if (!streaming) {
|
2025-01-17 03:44:56 +01:00
|
|
|
video_aspect = video.videoWidth / video.videoHeight;
|
2025-01-16 03:27:33 +01:00
|
|
|
|
|
|
|
|
video.style.aspectRatio = video_aspect;
|
|
|
|
|
|
|
|
|
|
photo.style.aspectRatio = video_aspect;
|
|
|
|
|
|
|
|
|
|
canvas.style.aspectRatio = video_aspect;
|
|
|
|
|
|
|
|
|
|
canvas_draw.style.aspectRatio = video_aspect;
|
2025-01-17 03:44:56 +01:00
|
|
|
canvas_draw.height = canvas_draw.height*5;
|
|
|
|
|
canvas_draw.width = canvas_draw.height*video_aspect;
|
2025-01-16 03:27:33 +01:00
|
|
|
|
|
|
|
|
streaming = true;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
startButton.addEventListener(
|
|
|
|
|
"click",
|
|
|
|
|
(ev) => {
|
|
|
|
|
takePicture();
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
clearPhoto();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fill the photo with an indication that none has been
|
|
|
|
|
// captured.
|
|
|
|
|
|
|
|
|
|
function clearPhoto() {
|
|
|
|
|
const context = canvas.getContext("2d");
|
|
|
|
|
|
|
|
|
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
|
|
|
|
|
|
const data = canvas.toDataURL("image/png");
|
|
|
|
|
photo.setAttribute("src", data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Capture a photo by fetching the current contents of the video
|
|
|
|
|
// and drawing it into a canvas, then converting that to a PNG
|
|
|
|
|
// format data URL. By drawing it on an offscreen canvas and then
|
|
|
|
|
// drawing that to the screen, we can change its size and/or apply
|
|
|
|
|
// other changes before drawing it.
|
|
|
|
|
|
|
|
|
|
function takePicture() {
|
|
|
|
|
canvas_draw.getContext('2d').clearRect(0, 0, canvas_draw.width, canvas_draw.height);
|
|
|
|
|
const context = canvas.getContext("2d");
|
|
|
|
|
if (video.videoWidth && video.videoHeight) {
|
|
|
|
|
canvas.width = video.videoWidth;
|
|
|
|
|
canvas.height = video.videoHeight;
|
|
|
|
|
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
|
|
|
|
video.style.zIndex = 1;
|
|
|
|
|
photo.style.zIndex = 5;
|
|
|
|
|
canvas.style.zIndex= 10;
|
|
|
|
|
|
|
|
|
|
const data = canvas.toDataURL("image/png");
|
|
|
|
|
photo.setAttribute("src", data);
|
|
|
|
|
} else {
|
|
|
|
|
clearPhoto();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 14:32:23 +01:00
|
|
|
|
2025-01-16 03:27:33 +01:00
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
</html>
|