
La realidad aumentada web (WebAR) ha cambiado radicalmente el desarrollo de experiencias inmersivas. Lo que antes requería aplicaciones nativas complejas hoy puede ejecutarse directamente desde el navegador.
En este tutorial te enseñaré cómo crear una aplicación funcional de Realidad Aumentada con JavaScript, específicamente un Crypto Tracker en WebAR que:
- Detecta una imagen física usando la cámara.
- Superpone un panel 3D.
- Permite buscar la criptomoneda que quieras.
- Agregar la cantidad que tienes de criptomoneda y mira en tiempo real su valor.
- Consulta precios en tiempo real desde una API.
- Calcula el valor total de tu inversión.
- Funciona tanto en móvil como en escritorio
Trabajo con realidad aumentada desde 2008, y si algo he aprendido es que el futuro de la AR no depende de apps pesadas, sino del navegador.
¿Qué vamos a construir en esta app de realidad aumentada?
Crearemos una aplicación WebAR – Realidad Aumentada enfocada en la web que:
- Usa A-Frame para renderizar la escena 3D.
- Usa MindAR para detectar una imagen y convertirla en tu marcador de realidad aumentada.
- Datos en tiempo real desde la API pública de Binance.
- Muestra el precio actual, cambio 24h y valor total en un panel flotante.
Todo desde una URL. Sin instalar nada.
Tecnologías utilizadas en cómo crear Realidad aumentada para este crypto tracker WebAR
A-Frame.
Framework declarativo basado en Three.js que permite crear escenas 3D usando HTML.
MindAR
Utilizamos el Image Tracking para cuando el marcador se muestre en pantalla se activen los elementos AR asociados.
JavaScript + Fetch API
Usaremos fetch() para consultar precios en tiempo real.
Estructura General del Proyecto
Nuestra app tiene 3 partes principales:
- Interfaz HTML (panel de control).
- Escena AR (A-Frame + MindAR).
- Lógica JavaScript (consulta API + actualización UI).
Paso 1: Configuración Base HTML de esta app de realidad aumentada
Incluimos los scripts de JavaScript para hacer llamado a las librerias:
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mind-ar@1.2.5/dist/mindar-image-aframe.prod.js"></script>Esto carga:
- Motor 3D.
- Sistema de cámara. Para teléfonos apple, android y computadores de mesa.
- Reconocimiento de imágenes para que la realidad aumentada funcione.
Paso 2: Crear la Escena WebAR
<a-scene
mindar-image="imageTargetSrc: ./targets.mind;"
color-space="sRGB"
renderer="colorManagement: true; physicallyCorrectLights: true;"
vr-mode-ui="enabled: false"
device-orientation-permission-ui="enabled: false">
<a-camera position="0 0 0" look-controls="enabled: false"></a-camera>
<a-light type="ambient" intensity="1.5"></a-light>
<a-entity mindar-image-target="targetIndex: 0">
<!-- Aquí irá nuestro panel AR -->
</a-entity>
</a-scene>¿Qué hacen estas líneas de código?
- Activa el seguimiento de imagen – Image Tracking de MindAR.
- Configura iluminación física correcta de la escena de realidad aumentada.
- Desactiva modo VR (solo AR).
- Optimiza renderizado.
Paso 3: Construcción del Panel AR
Usamos a-plane como fondo y a-text para mostrar datos.
Ejemplo del precio de la criptomoneda:
<a-text
id="ar-price"
align="center"
width="3.5"
color="#8CC63F"
font="exo2bold"
value="Cargando...">
</a-text>¿Por qué usamos y no text-geometry?
- Es más ligero para nuestra app WebAR.
- Funciona mejor en móviles.
- Usa Signed Distance Fields (SDF).
- Evita errores de triangulación en Safari iOS.
- Además, duplicamos el texto en negro detrás para simular sombra 3D.
Paso 4: Conectar con la API de Binance usando JavaScript para realidad aumentada
const fetchCrypto = async () => {
const symbol = "BTC";
const pair = `${symbol}USDT`;
const url = `https://api.binance.com/api/v3/ticker/24hr?symbol=${pair}`;
const res = await fetch(url);
const data = await res.json();
const price = parseFloat(data.lastPrice);
document.querySelector('#ar-price')
.setAttribute('value', `$${price}`);
};Problema Real: Errores CORS en apps WebAR
En desarrollo WebAR es común ver:
Failed to fetch
CORS policy blockedPor eso implementamos redundancia de red:
const endpoints = [
binanceApiUrl,
`https://api.allorigins.win/raw?url=${encodeURIComponent(binanceApiUrl)}`,
`https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(binanceApiUrl)}`
];Si un endpoint falla, intenta el siguiente. Esto hace tu app mucho más robusta.
Paso 5: Actualización Automática
setTimeout(fetchCrypto, 1000);
setInterval(fetchCrypto, 30000);Esto hace la primera consulta y se actualiza cada 30 segundos.
Cómo Funciona la aplicación de realidad aumentada en formato web (WebAR)
- El usuario apunta la cámara a la imagen que previamente creaste como marcador .mind.
- MindAR la detecta.
- Se activa el mindar-image-target.
- JavaScript consulta Binance.
- A-Frame actualiza los textos.
- Se renderiza el panel flotante en tiempo real.
Optimización para Móviles
En WebAR debes pensar en rendimiento:
- Usar fuentes integradas (exo2bold).
- Activar physicallyCorrectLights.
- Minimizar polígonos en caso de que también utilices modelos 3D para hacer la app más atractiva para tu público.
- Utiliza esta herramienta si quieres optimizar tus modelos 3D: AR Optimizer Pro – Compresor GLB | Realidad Aumentada
- Evitar geometría 3D compleja.
- Reducir descargas externas.
¿Cuál es la imagen que vamos a utilizar como marcador .mind?
Vamos a utilizar una herramienta para la creación de nuestro archivo .mind desde el siguiente link: Compilador de Marcadores AR | Crea Realidad Aumentada Gratis
La imagen que vamos a utilizar es esta:

Antes de continuar quiero invitarte a mi PATREON.
Para este tutorial en específico encontraras:
- Archivo index.html.
- Index.html comentada línea por línea para el correcto aprendizaje y desarrollo de aplicaciones de realidad aumentada WebAR.
- Archivo .mind listo para ser utilizando.
- Archivos fuentes.
Si deseas apoyar mi trabajo este es el link directo a mi PATREON: Realidad Aumentada Empezando Desde Cero – Ingcarlosreina | Tutoriales de Realidad Aumentada – Augmented Reality Tutorials | Patreon
Link directo a este articulo para DESCARGAR LOS ARCHIVOS: Cómo Crear un Crypto Tracker en Realidad Aumentada Web (WebAR) con JavaScript y MindAR
Código Completo de la aplicación que utiliza realidad aumentada para hacer seguimiento a criptomonedas
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="data:,">
<title>Crypto AR: Rastreador Impecable</title>
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
<script src="mindar-image-aframe.prod.js"></script>
<style>
body { margin: 0; overflow: hidden; font-family: 'Segoe UI', sans-serif; background: #000; }
#control-panel {
position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
width: 90%; max-width: 400px; background: rgba(30, 32, 38, 0.98);
padding: 15px; border-radius: 12px; border: 1px solid #F0B90B;
z-index: 100; display: flex; flex-direction: column; gap: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.7);
}
input {
width: 100%; box-sizing: border-box; background: #2b2f36; border: 1px solid #444;
color: white; padding: 10px; border-radius: 6px; font-size: 16px; outline: none;
}
input:focus { border-color: #F0B90B; }
#search-btn {
background: #F0B90B; color: #1e2026; border: none; padding: 12px;
border-radius: 6px; font-weight: bold; cursor: pointer; text-transform: uppercase;
}
#status-overlay {
position: absolute; top: 10px; left: 10px; color: #F0B90B; font-size: 11px;
background: rgba(0,0,0,0.8); padding: 6px 12px; border-radius: 4px; z-index: 100;
}
.label { color: #888; font-size: 12px; margin-bottom: -5px; }
</style>
<script>
AFRAME.registerComponent('content-stabilizer', {
tick: function() {
var parentEuler = new THREE.Euler().setFromQuaternion(this.el.parentEl.object3D.quaternion, 'XYZ');
this.el.object3D.rotation.z = -parentEuler.z;
}
});
document.addEventListener("DOMContentLoaded", function() {
const statusLabel = document.querySelector('#status-label');
const symbolInput = document.querySelector('#symbol-input');
const amountInput = document.querySelector('#amount-input');
const updateUI = (id, value, color) => {
const el = document.querySelector(id);
const shadow = document.querySelector(id + '-shadow');
if (el) {
el.setAttribute('value', value);
if (color) el.setAttribute('color', color);
}
if (shadow) {
shadow.setAttribute('value', value);
}
};
const fetchCrypto = async () => {
const symbol = symbolInput.value.trim().toUpperCase() || 'BTC';
const amount = parseFloat(amountInput.value) || 0;
statusLabel.innerText = `Actualizando ${symbol}...`;
const pair = `${symbol}USDT`;
const binanceApiUrl = `https://api.binance.com/api/v3/ticker/24hr?symbol=${pair}`;
const endpoints = [
binanceApiUrl,
`https://api.allorigins.win/raw?url=${encodeURIComponent(binanceApiUrl)}`,
`https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(binanceApiUrl)}`,
`https://thingproxy.freeboard.io/fetch/${binanceApiUrl}`
];
let data = null;
for (let url of endpoints) {
try {
const res = await fetch(url);
if (res.ok) {
const text = await res.text();
let parsed;
try {
parsed = JSON.parse(text);
} catch (err) {
continue;
}
if (parsed && parsed.lastPrice !== undefined) {
data = parsed;
console.log("Datos obtenidos exitosamente vía:", url);
break;
}
}
} catch (e) {
}
}
if (data) {
const price = parseFloat(data.lastPrice);
const change = parseFloat(data.priceChangePercent);
const totalValue = price * amount;
const priceStr = `$${price.toLocaleString('en-US')}`;
const totalStr = `$${totalValue.toLocaleString('en-US', {minimumFractionDigits: 2})}`;
const changeStr = `${change >= 0 ? '+' : ''}${change.toFixed(2)}% (24h)`;
const color = change >= 0 ? '#00ff00' : '#ff0000';
updateUI('#ar-name', symbol, '#F0B90B');
updateUI('#ar-price', priceStr, '#8CC63F');
updateUI('#ar-change', changeStr, color);
document.querySelector('#ar-arrow').setAttribute('color', color);
document.querySelector('#ar-arrow').setAttribute('rotation', change >= 0 ? '0 0 0' : '0 0 180');
document.querySelector('#ar-arrow-shadow').setAttribute('rotation', change >= 0 ? '0 0 0' : '0 0 180');
updateUI('#ar-total', totalStr, '#00BFFF');
statusLabel.innerText = "Datos Listos ✅";
} else {
statusLabel.innerText = "Error de conexión ❌";
}
};
document.querySelector('#search-btn').addEventListener('click', fetchCrypto);
setTimeout(fetchCrypto, 1000);
setInterval(fetchCrypto, 30000);
});
</script>
</head>
<body>
<div id="status-overlay"><span id="status-label">Iniciando Cámara...</span></div>
<div id="control-panel">
<div class="label">Nombre Cripto (ej: BTC, ETH)</div>
<input type="text" id="symbol-input" value="BTC" autocomplete="off">
<div class="label">Cantidad que tienes</div>
<input type="number" id="amount-input" value="1">
<button id="search-btn">BUSCAR Y CALCULAR 🔍</button>
</div>
<a-scene
mindar-image="imageTargetSrc: ./targets.mind; filterMinCF:0.001; filterBeta: 10;"
color-space="sRGB" renderer="colorManagement: true; physicallyCorrectLights: true;" vr-mode-ui="enabled: false"
device-orientation-permission-ui="enabled: false">
<a-assets><img id="custom-plane" src="./plane.png"></a-assets>
<a-camera position="0 0 0" look-controls="enabled: false"></a-camera>
<a-light type="ambient" intensity="1.5"></a-light>
<a-entity mindar-image-target="targetIndex: 0">
<a-entity content-stabilizer>
<a-plane material="src: #custom-plane; transparent: true" width="1" height="0.6" position="0 0 -0.01"></a-plane>
<a-plane color="#ffffff" opacity="0.6" width="0.95" height="0.55" position="0 0 -0.005"></a-plane>
<a-entity position="0 0.20 0">
<a-text id="ar-name-shadow" align="center" width="2.8" color="#000000" opacity="0.7" position="0.005 -0.005 0.01" font="exo2bold" value="BTC"></a-text>
<a-text id="ar-name" align="center" width="2.8" color="#FF8C00" position="0 0 0.02" font="exo2bold" value="BTC"></a-text>
</a-entity>
<a-entity position="0 0.05 0">
<a-text id="ar-price-shadow" align="center" width="3.5" color="#000000" opacity="0.7" position="0.005 -0.005 0.01" font="exo2bold" value="Cargando..."></a-text>
<a-text id="ar-price" align="center" width="3.5" color="#8CC63F" position="0 0 0.02" font="exo2bold" value="Cargando..."></a-text>
</a-entity>
<a-entity position="0 -0.10 0">
<a-text id="ar-change-shadow" align="center" width="1.5" color="#000000" opacity="0.7" position="0.003 -0.003 0.01" font="exo2bold" value="--"></a-text>
<a-text id="ar-change" align="center" width="1.5" position="0 0 0.02" font="exo2bold" value="--"></a-text>
<a-triangle id="ar-arrow-shadow" color="#000000" opacity="0.7" scale="0.05 0.05 0.05" position="0.353 0.017 0.01"></a-triangle>
<a-triangle id="ar-arrow" scale="0.05 0.05 0.05" position="0.35 0.02 0.02"></a-triangle>
</a-entity>
<a-plane color="#000" opacity="0.2" width="0.8" height="0.005" position="0 -0.16 0.01"></a-plane>
<a-entity position="0 -0.22 0">
<a-text align="right" value="Valor:" width="2.2" color="#000000" opacity="0.7" position="-0.045 -0.005 0.01" font="exo2bold"></a-text>
<a-text id="ar-total-shadow" align="left" width="2.2" color="#000000" opacity="0.7" position="0.055 -0.005 0.01" font="exo2bold" value="--"></a-text>
<a-text align="right" value="Valor:" color="#008be3" width="2.2" position="-0.05 0 0.02" font="exo2bold"></a-text>
<a-text id="ar-total" align="left" color="#00BFFF" width="2.2" position="0.05 0 0.02" font="exo2bold" value="--"></a-text>
</a-entity>
</a-entity>
</a-entity>
</a-scene>
</body>
</html>¿Por Qué Este Proyecto Es Importante?
Este Crypto Tracker demuestra algo clave para todos nosotros los desarrolladores de aplicaciones de realidad aumentada enfocada en la web con javascript.
La realidad aumentada web ya puede hacer muchas cosas, te dejo un pequeño listado:
- Consumir APIs externas.
- Procesar datos en tiempo real.
- Funcionar en móviles iOS, Android, tabletas, computadores de mesa.
- Ejecutarse sin app. Desde el navegador de tu dispositivo.
- Integrarse con sistemas financieros.
Eso abre posibilidades enormes para el desarrollo de WebAR (Realidad Aumentada en la web):
- Visualización de datos.
- Marketing interactivo.
- Educación.
- E-commerce.
- Dashboards inmersivos.
Crear aplicaciones de Realidad Aumentada Web con JavaScript ya no es experimental, hay un mundo de posibilidades.
Con herramientas como A-Frame y MindAR, puedes desarrollar experiencias AR accesibles, ligeras y escalables directamente desde el navegador.
Después de más de una década trabajando con esta tecnología, puedo decirlo con claridad: El futuro de la realidad aumentada no depende de descargar una app. Depende de abrir un enlace.
En este blog de Realidad Aumentada puedes encontrar muchos artículos interesantes para que puedas seguir desarrollando Apps WebAR. Te dejo los siguientes links: