Created
April 8, 2020 06:16
-
-
Save parzibyte/4d4e613be77b404a4d7b2cc00b44e238 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Tomar una fotografía y guardarla en un archivo v3 | |
@date 2018-10-22 | |
@author parzibyte | |
@web parzibyte.me/blog | |
*/ | |
const tieneSoporteUserMedia = () => | |
!!(navigator.getUserMedia || (navigator.mozGetUserMedia || navigator.mediaDevices.getUserMedia) || navigator.webkitGetUserMedia || navigator.msGetUserMedia) | |
const _getUserMedia = (...arguments) => | |
(navigator.getUserMedia || (navigator.mozGetUserMedia || navigator.mediaDevices.getUserMedia) || navigator.webkitGetUserMedia || navigator.msGetUserMedia).apply(navigator, arguments); | |
// Declaramos elementos del DOM | |
const $video = document.querySelector("#video"), | |
$canvas = document.querySelector("#canvas"), | |
$estado = document.querySelector("#estado"), | |
$boton = document.querySelector("#boton"), | |
$listaDeDispositivos = document.querySelector("#listaDeDispositivos"); | |
const limpiarSelect = () => { | |
for (let x = $listaDeDispositivos.options.length - 1; x >= 0; x--) | |
$listaDeDispositivos.remove(x); | |
}; | |
const obtenerDispositivos = () => navigator | |
.mediaDevices | |
.enumerateDevices(); | |
// La función que es llamada después de que ya se dieron los permisos | |
// Lo que hace es llenar el select con los dispositivos obtenidos | |
const llenarSelectConDispositivosDisponibles = () => { | |
limpiarSelect(); | |
obtenerDispositivos() | |
.then(dispositivos => { | |
const dispositivosDeVideo = []; | |
dispositivos.forEach(dispositivo => { | |
const tipo = dispositivo.kind; | |
if (tipo === "videoinput") { | |
dispositivosDeVideo.push(dispositivo); | |
} | |
}); | |
// Vemos si encontramos algún dispositivo, y en caso de que si, entonces llamamos a la función | |
if (dispositivosDeVideo.length > 0) { | |
// Llenar el select | |
dispositivosDeVideo.forEach(dispositivo => { | |
const option = document.createElement('option'); | |
option.value = dispositivo.deviceId; | |
option.text = dispositivo.label; | |
$listaDeDispositivos.appendChild(option); | |
}); | |
} | |
}); | |
} | |
(function() { | |
// Comenzamos viendo si tiene soporte, si no, nos detenemos | |
if (!tieneSoporteUserMedia()) { | |
alert("Lo siento. Tu navegador no soporta esta característica"); | |
$estado.innerHTML = "Parece que tu navegador no soporta esta característica. Intenta actualizarlo."; | |
return; | |
} | |
//Aquí guardaremos el stream globalmente | |
let stream; | |
// Comenzamos pidiendo los dispositivos | |
obtenerDispositivos() | |
.then(dispositivos => { | |
// Vamos a filtrarlos y guardar aquí los de vídeo | |
const dispositivosDeVideo = []; | |
// Recorrer y filtrar | |
dispositivos.forEach(function(dispositivo) { | |
const tipo = dispositivo.kind; | |
if (tipo === "videoinput") { | |
dispositivosDeVideo.push(dispositivo); | |
} | |
}); | |
// Vemos si encontramos algún dispositivo, y en caso de que si, entonces llamamos a la función | |
// y le pasamos el id de dispositivo | |
if (dispositivosDeVideo.length > 0) { | |
// Mostrar stream con el ID del primer dispositivo, luego el usuario puede cambiar | |
mostrarStream(dispositivosDeVideo[0].deviceId); | |
} | |
}); | |
const mostrarStream = idDeDispositivo => { | |
_getUserMedia({ | |
video: { | |
// Justo aquí indicamos cuál dispositivo usar | |
deviceId: idDeDispositivo, | |
} | |
}, | |
(streamObtenido) => { | |
// Aquí ya tenemos permisos, ahora sí llenamos el select, | |
// pues si no, no nos daría el nombre de los dispositivos | |
llenarSelectConDispositivosDisponibles(); | |
// Escuchar cuando seleccionen otra opción y entonces llamar a esta función | |
$listaDeDispositivos.onchange = () => { | |
// Detener el stream | |
if (stream) { | |
stream.getTracks().forEach(function(track) { | |
track.stop(); | |
}); | |
} | |
// Mostrar el nuevo stream con el dispositivo seleccionado | |
mostrarStream($listaDeDispositivos.value); | |
} | |
// Simple asignación | |
stream = streamObtenido; | |
// Mandamos el stream de la cámara al elemento de vídeo | |
$video.srcObject = stream; | |
$video.play(); | |
//Escuchar el click del botón para tomar la foto | |
//Escuchar el click del botón para tomar la foto | |
$boton.addEventListener("click", function() { | |
//Pausar reproducción | |
$video.pause(); | |
//Obtener contexto del canvas y dibujar sobre él | |
let contexto = $canvas.getContext("2d"); | |
$canvas.width = $video.videoWidth; | |
$canvas.height = $video.videoHeight; | |
contexto.drawImage($video, 0, 0, $canvas.width, $canvas.height); | |
let foto = $canvas.toDataURL(); //Esta es la foto, en base 64 | |
$estado.innerHTML = "Enviando foto. Por favor, espera..."; | |
fetch("./guardar_foto.php", { | |
method: "POST", | |
body: encodeURIComponent(foto), | |
headers: { | |
"Content-type": "application/x-www-form-urlencoded", | |
} | |
}) | |
.then(resultado => { | |
// A los datos los decodificamos como texto plano | |
return resultado.text() | |
}) | |
.then(idFoto => { | |
// idFoto trae el id de la foto | |
console.log("La foto fue enviada correctamente"); | |
$estado.innerHTML = `Foto guardada con éxito. Puedes verla <a target='_blank' href='./ver.php?id=${idFoto}'> aquí</a>`; | |
}) | |
//Reanudar reproducción | |
$video.play(); | |
}); | |
}, (error) => { | |
console.log("Permiso denegado o error: ", error); | |
$estado.innerHTML = "No se puede acceder a la cámara, o no diste permiso."; | |
}); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment