Saltar al contenido
apis-del-navegador.js · devschool

APIs del navegador

Lección 34 de 38 · 5 min de lectura · Actualizado el

En esta lección
  1. Geolocalización
  2. Mapas con Leaflet
  3. Portapapeles
  4. Notificaciones
  5. Web Workers: trabajo en segundo plano
  6. Canvas: dibujar con JavaScript
  7. Intersection Observer: saber si algo se ve
  8. Otras que te encontrarás

Además del lenguaje y del DOM, los navegadores ofrecen decenas de APIs: conjuntos de funciones para acceder a capacidades del dispositivo o hacer tareas complejas. Muchas nacieron con HTML5. Estas son las que más vas a usar.

Casi todas las que acceden a cosas sensibles (ubicación, cámara, notificaciones, portapapeles) piden permiso al usuario y solo funcionan en páginas servidas por HTTPS (o en localhost mientras desarrollas).

Geolocalización

Con permiso del usuario, el navegador puede saber dónde está. En móviles usa el GPS; en ordenadores, las redes WiFi cercanas o la dirección IP, con menos precisión.

if ("geolocation" in navigator) {
  navigator.geolocation.getCurrentPosition(
    (posicion) => {
      const { latitude, longitude, accuracy } = posicion.coords;
      console.log(`Estás en ${latitude}, ${longitude} (±${Math.round(accuracy)} m)`);
    },
    (error) => {
      console.log("No se pudo obtener la ubicación:", error.message);
    },
    { enableHighAccuracy: true, timeout: 10000 }
  );
}
  • El primer argumento es la función que recibe la posición.
  • El segundo, la función que se ejecuta si hay un error (por ejemplo, si el usuario deniega el permiso). Tenlo siempre en cuenta: muchas personas dirán que no.
  • El tercero, las opciones.

Pide la ubicación solo cuando el usuario haga algo que la necesite (pulsar “Buscar cerca de mí”), nunca nada más cargar la página: la mayoría rechaza los permisos que se piden sin contexto.

Mapas con Leaflet

Para mostrar un mapa, lo más sencillo es la librería libre Leaflet con los mapas de OpenStreetMap, un proyecto colaborativo parecido a Wikipedia pero para mapas:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

<div id="mapa" style="height: 400px"></div>

<script>
  const mapa = L.map("mapa").setView([43.4623, -3.8100], 14);   // latitud, longitud, zoom

  L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution: "&copy; colaboradores de OpenStreetMap",
  }).addTo(mapa);

  L.marker([43.4623, -3.8100]).addTo(mapa).bindPopup("Santander").openPopup();
</script>
  • El contenedor del mapa necesita una altura en CSS, o no se verá.
  • El mapa se compone de teselas (tiles): imágenes cuadradas de 256 píxeles que se cargan según la zona y el zoom (0 es el mundo entero; 18, una calle).
  • Los datos de OpenStreetMap son libres, pero sus servidores de teselas tienen límites de uso. Para una web con mucho tráfico hay que contratar un proveedor o montar uno propio.

Portapapeles

botonCopiar.addEventListener("click", async () => {
  try {
    await navigator.clipboard.writeText(codigo.textContent);
    botonCopiar.textContent = "¡Copiado!";
  } catch {
    botonCopiar.textContent = "No se pudo copiar";
  }
});

Solo funciona como respuesta a una acción del usuario (un clic), nunca de forma automática.

Notificaciones

const permiso = await Notification.requestPermission();
if (permiso === "granted") {
  new Notification("DevSchool", { body: "Tienes un reto nuevo esperándote" });
}

Úsalas con muchísima moderación: son de las cosas que más molestan a los usuarios.

Web Workers: trabajo en segundo plano

JavaScript en el navegador se ejecuta en un solo hilo: si un cálculo tarda 3 segundos, la página se congela 3 segundos. Un Web Worker es un script que se ejecuta en paralelo, en otro hilo, sin bloquear la página. Es útil para cálculos pesados: procesar imágenes, analizar un archivo grande, simulaciones.

// worker.js: no tiene acceso al DOM
self.addEventListener("message", (evento) => {
  const n = evento.data;
  let primos = 0;
  for (let i = 2; i < n; i++) {
    if (esPrimo(i)) primos++;
  }
  self.postMessage(primos);           // devuelve el resultado
});

function esPrimo(x) {
  for (let d = 2; d * d <= x; d++) if (x % d === 0) return false;
  return true;
}
// app.js
const worker = new Worker("worker.js");
worker.addEventListener("message", (evento) => {
  resultado.textContent = `Hay ${evento.data} primos`;
});
worker.postMessage(5_000_000);   // envía el trabajo; la página sigue respondiendo

El worker y la página se comunican solo con mensajes (postMessage y el evento message). Con worker.terminate() lo detienes. Como los módulos, necesitan que la página se sirva desde un servidor, no con doble clic.

Canvas: dibujar con JavaScript

El elemento <canvas> es un lienzo en el que dibujas píxel a píxel. Se usa para gráficos, juegos y edición de imágenes:

<canvas id="lienzo" width="300" height="150"></canvas>
<script>
  const ctx = document.querySelector("#lienzo").getContext("2d");
  ctx.fillStyle = "#2d6cdf";
  ctx.fillRect(20, 20, 100, 60);          // rectángulo: x, y, ancho, alto
  ctx.beginPath();
  ctx.arc(200, 75, 40, 0, Math.PI * 2);   // círculo: x, y, radio
  ctx.fillStyle = "#c47f00";
  ctx.fill();
</script>

Para gráficos vectoriales (que se ven nítidos a cualquier tamaño), la alternativa es SVG, que se puede escribir directamente en el HTML. Y para gráficos de datos, librerías como Chart.js o D3.js hacen casi todo el trabajo.

Intersection Observer: saber si algo se ve

Avisa cuando un elemento entra o sale de la pantalla al hacer scroll. Es la base de la carga diferida, del scroll infinito o de las animaciones que se activan al llegar a una sección:

const observador = new IntersectionObserver((entradas) => {
  for (const entrada of entradas) {
    if (entrada.isIntersecting) {
      entrada.target.classList.add("visible");
      observador.unobserve(entrada.target);   // solo la primera vez
    }
  }
});

document.querySelectorAll(".seccion").forEach((s) => observador.observe(s));

Otras que te encontrarás

  • matchMedia: comprobar media queries desde JavaScript, como matchMedia("(prefers-color-scheme: dark)").matches.
  • Historial (history.pushState): cambiar la URL sin recargar la página, la base de las aplicaciones de una sola página.
  • Almacenamiento: Web Storage e IndexedDB.
  • Multimedia: controlar <video> y <audio> (video.play(), video.pause()), acceder a la cámara con getUserMedia.
  • Compartir (navigator.share): abre el menú nativo de compartir del móvil.

La referencia completa, con ejemplos y compatibilidad de cada navegador, está en MDN Web Docs (developer.mozilla.org), que tiene gran parte de su contenido en español.

Pon a prueba lo que has aprendido

[JavaScript] ¿Qué debes hacer siempre al pedir la ubicación con geolocation?

[JavaScript] ¿Para qué sirve un Web Worker?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.