Un componente de React que replica el efecto de vidrio líquido de Apple usando distorsión de lente barril con SVG y backdrop-filter. Sin librerías pesadas — solo un mapa de desplazamiento generado en canvas, un filtro SVG y CSS.
- Mapa barril en Canvas — al montarse, un
ResizeObservermide el elemento y genera un mapa de desplazamiento radial:dispX = strength × nx × r². El valor es0en el centro (sin distorsión) y crece cuadráticamente hacia los bordes (efecto ojo de pez / lupa). - SVG
feDisplacementMap— el mapa se carga en un<feImage>oculto y se aplica mediantefeDisplacementMap. El filtro se inyecta en un SVG fijo de0×0fuera del componente. backdrop-filter: url(#id)— se aplica directamente en el div contenedor para que el navegador recorte la distorsión alborder-radiuscorrectamente. Un desenfoque de0.5pxsuaviza el aliasing del desplazamiento.- Capas especulares — un
linear-gradientde luz de borde + borde +box-shadowsimulan cómo la luz se refleja en un vidrio curvo y grueso.
Abre app/GlassSurface.tsx y edita las dos constantes al inicio del archivo:
// Intensidad del efecto barril (0 = ninguno, 1 = máximo)
const BARREL_STRENGTH = 0.85;
// Desplazamiento máximo en píxeles en los bordes
// Mayor → más distorsión / Menor → menos distorsión
const BARREL_SCALE = 110;Copia app/GlassSurface.tsx en tu proyecto. Úsalo como cualquier div — se adapta a su contenido y acepta className para control total del layout.
import { GlassSurface } from "@/app/GlassSurface";
// Básico
<GlassSurface>
<p>Hola</p>
</GlassSurface>
// Con tamaño Tailwind y layout flex
<GlassSurface className="w-80 flex flex-col gap-2">
<h2>Título</h2>
<p>Texto del cuerpo</p>
</GlassSurface>
// Botón píldora con ícono
<GlassSurface className="rounded-full cursor-pointer" onClick={() => {}}>
<HomeIcon />
</GlassSurface>
// Tarjeta de ancho completo
<GlassSurface className="w-full max-w-md">
<p>Contenido de la tarjeta</p>
</GlassSurface>| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
children |
ReactNode |
— | Contenido renderizado dentro del vidrio |
className |
string |
"" |
Clases de Tailwind o CSS personalizadas aplicadas al contenedor. Controla tamaño, layout, forma, cursor, etc. |
onClick |
() => void |
— | Manejador de clic. pointer-events: auto siempre se establece internamente, por lo que funciona incluso dentro de padres con pointer-events: none. |
Nota:
p-4yrounded-3xlse aplican por defecto. Sobreescríbelos conclassNamesi es necesario (p. ej.rounded-full).
- Next.js 16 (App Router)
- Tailwind CSS v4
- TypeScript
npm install
npm run devAbre http://localhost:3000.
npm run dev
# o
yarn dev
# o
pnpm dev
# o
bun devAbre http://localhost:3000 en tu navegador para ver el resultado.
Puedes comenzar a editar la página modificando app/page.tsx. La página se actualiza automáticamente al guardar los cambios.
Este proyecto usa next/font para optimizar y cargar automáticamente Geist, una nueva familia tipográfica de Vercel.
Para aprender más sobre Next.js, consulta los siguientes recursos:
- Documentación de Next.js - aprende sobre las características y la API de Next.js.
- Aprende Next.js - un tutorial interactivo de Next.js.
También puedes revisar el repositorio de Next.js en GitHub — ¡tus comentarios y contribuciones son bienvenidos!
La forma más sencilla de desplegar tu aplicación Next.js es usar la Plataforma Vercel de los creadores de Next.js.
Consulta la documentación de despliegue de Next.js para más detalles.