En este post te mostraré cómo leer códigos de barras en el navegador web ya sea de una computadora o dispositivo móvil, usando la cámara del teléfono o la cámara web; y el lenguaje nativo JavaScript.
Esto hace que podamos hacer nuestras aplicaciones web todavía más diversas y con más características; en un ejemplo simple se me ocurre escanear el código de barras para un sistema de ventas.
La librería que vamos a usar se llama QuaggaJS y es capaz de leer códigos de barras con formato EAN, CODE 128, CODE 39, EAN 8, UPC-A, UPC-C, I2of5, 2of5, CODE 93 y CODABAR.
Con esto, podremos leer códigos de barras en dispositivos móviles o computadoras en tiempo real.
Limitaciones y requisitos
Así como para tomar fotos de la cámara web usando JavaScript, necesitamos que el sitio tenga HTTPS o esté en localhost.
No hay manera simple de que funcione si no existen esas características. Incluso si estás en una red local y apuntas a tu servidor local, eso no es localhost. Es forzoso que la URL diga localhost o tenga HTTPS.
También se requiere un navegador decente y actualizado, olvídate de Safari o Internet Explorer; utiliza Firefox o Chrome (esto es mi recomendación, pero puedes probar en el navegador de tu preferencia y dejar un comentario).
Por cierto, no se puede leer (al momento de escribir este post) todo tipo de códigos de barras; es decir, se debe configurar antes cuál formato se debe escanear. Aunque leí por ahí que en las últimas versiones esto ya se está agregando.
Dicho todo esto, comencemos.
Primer ejemplo básico
Comencemos con un ejemplo sencillo. Incluimos el script de Quagga (si usas NPM o similares también es válido) y nuestro script en donde vamos a iniciar el lector:
<!-- Cargamos Quagga y luego nuestro script -->
<script src="https://unpkg.com/quagga@0.12.1/dist/quagga.min.js"></script>
<script src="script.js"></script>
Ahora en nuestro HTML definimos el contenedor que, como lo dije, va a mostrar la vista previa del lector. Por cierto también defino (para el ejemplo) un elemento en donde se colocará el código leído y por lo tanto el código completo queda así:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Leer código de barras con JavaScript by parzibyte</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p id="resultado">Aquí aparecerá el código</p>
<p>A continuación, el contenedor: </p>
<div id="contenedor"></div>
<!-- Cargamos Quagga y luego nuestro script -->
<script src="https://unpkg.com/quagga@0.12.1/dist/quagga.min.js"></script>
<script src="script.js"></script>
</body>
</html>
La parte importante viene a continuación. Iniciamos Quagga indicándole que lea el formato EAN (puede leer los que indiqué al inicio), con una resolución de 1920 x 1080 y que los resultados los coloque en el elemento del DOM que estamos pasándole (obtenido con querySelector):
document.addEventListener("DOMContentLoaded", () => {
const $resultados = document.querySelector("#resultado");
Quagga.init({
inputStream: {
constraints: {
width: 1920,
height: 1080,
},
name: "Live",
type: "LiveStream",
target: document.querySelector('#contenedor'), // Pasar el elemento del DOM
},
decoder: {
readers: ["ean_reader"]
}
}, function (err) {
if (err) {
console.log(err);
return
}
console.log("Iniciado correctamente");
Quagga.start();
});
Quagga.onDetected((data) => {
$resultados.textContent = data.codeResult.code;
// Imprimimos todo el data para que puedas depurar
console.log(data);
});
});
Iniciamos el lector pasándole el modo, y el contenedor en donde debe colocar los resultados. Si no hay problema al iniciarlo (línea 22) entonces comenzamos a leer lo de la cámara y a buscar códigos de barras con Quagga.start()
.
Proporcionamos el callback a onDetected
que se invocará cuando se haya leído un código de barras. El mismo estará en la propiedad codeResult.code
del resultado que nos pasa la función.
Justo en la función onDetected
ocurre la magia. En mi caso simplemente coloco el código en el párrafo, pero tú puedes colocarlo en un input y enviar un formulario, enviarlo usando AJAX, etcétera.
Para terminar este ejemplo veamos el estilo usado, que si bien no es primordial, es importante:
#contenedor video{
max-width: 100%;
width: 100%;
}
#contenedor{
max-width: 100%;
position:relative;
}
canvas{
max-width: 100%;
}
canvas.drawingBuffer{
position:absolute;
top:0;
left:0;
}
El código completo de este ejemplo lo encuentras en GitHub. La demostración la encuentras en este enlace.
Formatos soportados
Anteriormente listé los formatos soportados. Aquí los muestro pero como cadena aceptable para el lector, es decir, si quieres indicar que se lea en el formato, no debes colocar espacios ni mayúsculas, sino algo así:
- code_128_reader
- code_39_reader
- code_39_vin_reader
- ean_reader
- ean_extended_reader
- ean_8_reader
- upc_reader
- upc_e_reader
- codabar_reader
- i2of5_reader
- 2of5_reader
- code_93_reader
En mi ejemplo simplemente utilizo ean_reader
, tú puedes utilizar cualquiera de la lista.
Dibujando código leído
El autor de la librería ha proporcionado una manera bastante sencilla pero poderosa de mostrar en qué lugar del canvas se ha detectado el código, dándole una mejor vista al lector de código de barras de JavaScript e indicándole al usuario en dónde se ha detectado el mismo.
En este caso podemos mostrar algunas líneas en el canvas o drawing buffer para indicar en dónde se ha detectado el código; para ello podemos escuchar al evento Quagga.onProcessed
que se invocará cada que haya procesado la imagen, con ciertos puntos en donde se ha detectado.
No es necesario implementar nuestro propio método de dibujo, pues el autor ya lo ha hecho en sus ejemplos. Basta con agregar al script anterior lo siguiente:
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
No es necesario modificar más código, pues todo este dibujo se hace en el lienzo que el lector ya coloca sobre el contenedor indicado. Para dejarlo claro, el código completo del script es el siguiente:
document.addEventListener("DOMContentLoaded", () => {
const $resultados = document.querySelector("#resultado");
Quagga.init({
inputStream: {
constraints: {
width: 1920,
height: 1080,
},
name: "Live",
type: "LiveStream",
target: document.querySelector('#contenedor'), // Pasar el elemento del DOM
},
decoder: {
readers: ["ean_reader"]
}
}, function (err) {
if (err) {
console.log(err);
return
}
console.log("Iniciado correctamente");
Quagga.start();
});
Quagga.onDetected((data) => {
$resultados.textContent = data.codeResult.code;
// Imprimimos todo el data para que puedas depurar
console.log(data);
});
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
});
Ahora tenemos un dibujo en cada código detectado. Además, si se detecta uno válido o legible, se dibuja una línea roja:
El código del ejemplo está en mi repositorio de GitHub, y puedes probarlo aquí.
Tercer ejemplo: leer código de barras en ventana separada
Si bien se puede leer el código en una misma ventana, podemos separar lógica y componentes para leer el código de barras en una ventana distinta y así integrar de mejor manera este lector.
Hace un tiempo hice un ejemplo para abrir una ventana nueva con el lector, cuyo funcionamiento era que al leer el código, la ventana se cerraba; y se devolvía el código de barras gracias a la comunicación entre ventanas de JavaScript.
Si quieres verlo, aquí está el código del ejemplo. La verdad es que es un ejemplo no tan general (de hecho fue para un trabajo que hice) y por lo tanto no lo explico aquí, pero si te gusta explorar el código, estás invitado a hacerlo.
Conclusión
Olvidé mencionar que en todos los ejemplos estoy esperando al evento DOMContentLoaded
, esto es solo para esperar que el DOM se haya cargado correctamente y digamos que simplemente es una buena práctica, es algo así como el $(document).ready()
de jQuery
Por cierto, en los ejemplo estoy detectando códigos de barras en formato EAN, aunque los soportados son los mencionados al inicio.
Te invito a visitar el repositorio de la librería, pues es la principal fuente de documentación. También te dejo algunos enlaces de interés para aprender JavaScript en mi blog.
Wow funciona perfecto muchas gracias por tu aporte!
Como agregarías para que se guarde en mysql el código obtenido?
Hola. Gracias por sus comentarios. Si tiene alguna consulta, solicitud de creación de un programa o solicitud de cambio de software con gusto lo atiendo en https://parzibyte.me/#contacto
Saludos!
Muchas Gracias fue de gran ayuda, consulta, como puedo agregar un beep al realizar la linea roja?
Hola. Me agrada saber que ha funcionado. Si tiene consultas puede hacérmelas llegar en https://parzibyte.me/#contacto
Hola, gracias por la enseñanza pero tengo una duda, al momento de incluir el action al form para mandar el input a un php, el lector de barra deja de funcionar. Sabe la razón ?
Muchas gracias estimado, me viene perfecto para un proyecto en mi trabajo
Me agrada escuchar que le sea de ayuda. Le invito a compartir y a seguirme en mi blog para no perderse mi próximo contenido
Saludos! 🙂
Funciona para leer códigos QR? Y si es así, cuales son los formatos que le debo indicar para que los lea, de antemano gracias.
Hola. Puede leer la documentación de la librería para averiguarlo
Saludos 🙂
Buen día
estoy probando el lector, no logro me reconozca los EAN, se activa la cámara pero no los reconoce. Alguna pista de que me puede estar faltando ?
lo tengo en [url]
muchas gracias
OLB
Hola. Si requiere ayuda personalizada puede contactarme en https://parzibyte.me
Saludos 🙂
Buenas una pregunta sirve para leer con una pistola de códigos de barra?
La pistola de códigos de barra introduce el código y presiona Enter. Es decir, es como un teclado. Así que basta con colocar un campo de texto y escuchar el “enter”
Saludos 🙂
Excelente muchas gracias
Si el post fue de su agrado, le agradecería si lo comparte
Saludos 🙂