wandres.dev
MÁS ALLÁ DEL IPHONE · iPad, Mac, watch, visionOS

visionOS: ventanas, volúmenes y espacios cuando la interfaz deja la pantalla

En visionOS la interfaz ya no vive dentro de un rectángulo que la persona sostiene, sino en la habitación donde está. Esta lección examina los tres contenedores que ofrece la plataforma y el contrato que impone cada uno, el modelo de entrada basado en mirada y pellizco, las consecuencias de que la profundidad y la escala sean reales, y el criterio para decidir qué parte de una app existente merece salir del cristal.

⏱ 19 min

Todas las plataformas anteriores comparten un supuesto tan básico que nunca hizo falta enunciarlo: la interfaz vive dentro de un rectángulo, y ese rectángulo está en algún lugar del mundo pero no forma parte de él. El teléfono se sostiene, el portátil se abre, el reloj se lleva; en los tres casos hay un adentro y un afuera perfectamente delimitados. visionOS disuelve esa frontera. Tu ventana se apoya sobre la mesa real de la persona, proyecta sombra sobre su pared real y compite por la atención con su gato real. Y en el momento en que la interfaz comparte espacio con el mundo, deja de heredar las convenciones del cristal y empieza a heredar las de los objetos: escala, distancia, peso visual, ergonomía y una noción de comodidad física que ninguna guía de estilo anterior tuvo que abordar.

🎯 Al terminar esta lección sabrás
  • Distinguir ventana, volumen y espacio inmersivo por el contrato que impone cada uno.
  • Diseñar para un modelo de entrada basado en la mirada y en gestos indirectos.
  • Aplicar profundidad, escala y materiales con criterio ergonómico, no decorativo.
  • Decidir qué parte de una app existente gana algo al salir del rectángulo.

Tres contenedores y tres contratos

La plataforma ofrece exactamente tres formas de ocupar el espacio, y cada una es un compromiso distinto con el entorno de la persona. Una ventana es un plano bidimensional que flota donde se la coloque y convive con las ventanas de otras apps; es el contenedor por defecto y, en la enorme mayoría de los casos, el correcto. Un volumen es una caja tridimensional con dimensiones declaradas, pensada para un objeto que se mira desde cualquier ángulo y que sigue conviviendo con lo demás. Un espacio inmersivo es la concesión mayor: tu app pasa a ser la única y recibe el control de la escena completa, con el resto atenuado o ausente.

@main
struct MiApp: App {
    var body: some Scene {
        WindowGroup { Panel() }                       // plano, convive con otras apps

        WindowGroup(id: "modelo") { Modelo3D() }
            .windowStyle(.volumetric)                 // caja con dimensiones reales
            .defaultSize(width: 0.6, height: 0.4, depth: 0.6, in: .meters)

        ImmersiveSpace(id: "taller") { Taller() }      // la app se queda sola
            .immersionStyle(selection: $estilo, in: .mixed, .progressive, .full)
    }
}

Merece la pena detenerse en el detalle más revelador de ese fragmento: el tamaño por defecto del volumen se declara en metros. No en puntos, no en píxeles, no en unidades abstractas escaladas por un factor de densidad, sino en la misma unidad con la que se mide una mesa. Es la señal más clara de que has cambiado de dominio: aquí una cifra mal elegida no produce un elemento pequeño, produce un objeto que no cabe en la habitación o que resulta amenazante por su cercanía.

🪟

Ventana

Contenido plano, convivencia con otras apps, coste cognitivo mínimo. Es el destino natural de casi toda app portada y no hay nada humilde en quedarse aquí.

🧊

Volumen

Un objeto con tres dimensiones y escala real, mirable desde cualquier ángulo. Justificado cuando la tridimensionalidad es el contenido, no un adorno.

🌄

Espacio inmersivo

Control de la escena entera. Se pide para una experiencia deliberada y acotada, y se devuelve en cuanto termina.

🎚️

Grado de inmersión

Mezclado deja ver la habitación, progresivo la sustituye según la corona, completo la reemplaza. La transición debe ser gradual y reversible.

⚠️
El espacio inmersivo no es el nivel superior de calidad

La lectura equivocada más frecuente consiste en ordenar los tres contenedores como una escala de ambición, con la ventana abajo y la inmersión arriba, y aspirar a subir. Pero pedir un espacio inmersivo significa expulsar de la vista al resto de las apps y aislar a la persona de su habitación, y eso solo se justifica cuando el aislamiento es el valor que entregas. Una app de notas inmersiva no es más avanzada: es más molesta.

Mirar y pellizcar

El modelo de entrada por defecto rompe con todo lo anterior de una manera que conviene interiorizar antes de escribir una sola vista: la persona no toca nada. Mira el elemento que quiere y junta dos dedos en cualquier lugar cómodo, típicamente sobre el regazo. La mirada selecciona, el pellizco confirma, y el brazo no necesita levantarse ni extenderse. Esta indirección tiene tres consecuencias de diseño que ninguna otra plataforma comparte.

La primera es que el sistema conoce dónde miras y tu app no. La información de la mirada es privada y no llega al código, de modo que el resaltado al enfocar lo dibuja el sistema a partir de las formas que tú declaras. Eso convierte a hoverEffect y a las formas de contenido en piezas centrales y no en refinamientos: si la región interactiva no coincide con lo dibujado, la persona verá iluminarse algo distinto de lo que quería pulsar.

La segunda es que los objetivos deben ser grandes y estar separados. La precisión de la mirada es buena pero no puntual, y dos controles juntos producen un titubeo del resaltado que resulta agotador en pocos segundos. La tercera es que el diseño debe respetar la ergonomía del cuello: lo importante va al frente y ligeramente por debajo de la horizontal, nunca arriba ni en los extremos laterales, porque mirar hacia arriba de forma sostenida es incómodo y girar la cabeza para encontrar un botón es un fallo de disposición.

Button(action: abrir) {
    Etiqueta()
        .padding(20)                       // objetivo generoso, separado de sus vecinos
}
.buttonStyle(.plain)
.contentShape(.hoverEffect, .capsule)      // la region enfocable coincide con el dibujo
.hoverEffect(.highlight)
💡
Comprueba el diseño con la cabeza quieta

Una prueba barata y sorprendentemente severa consiste en recorrer la tarea principal sin mover el cuello, solo con los ojos. Todo lo que obligue a girar la cabeza es candidato a reubicarse, y todo lo que quede por encima de la línea del horizonte es candidato a bajar. Las apps que aprueban esta prueba se pueden usar durante una hora; las que no, se abandonan por cansancio y nadie sabe explicar por qué.

La profundidad es real y por tanto tiene coste

En una pantalla, la sombra es un truco pictórico que sugiere elevación. Aquí no: la separación entre dos capas es una distancia física que el sistema visual mide con paralaje y convergencia, y por tanto tiene consecuencias reales sobre la fatiga. De ahí que la profundidad se use con parsimonia y con propósito, elevando solo lo que debe destacar —un modal, un control flotante, un elemento seleccionado— y en cantidades pequeñas.

Panel()
    .glassBackgroundEffect()          // material del sistema: legible sobre cualquier fondo
    .offset(z: 12)                    // elevacion sutil, medida en puntos reales

El material vítreo del sistema no es una elección estética sino funcional. Tu ventana se dibuja sobre lo que haya detrás, que puede ser una pared blanca, una estantería o una ventana con sol, y ningún fondo opaco que elijas funcionará en los tres casos. El material del sistema se adapta al entorno y garantiza legibilidad, y por eso desviarse de él suele producir un panel que es perfecto en la demostración y ilegible en la casa de quien lo usa.

flowchart TB
a[Contenido de tu app] --> b[Cabe en un plano]
b --> c[Ventana con material del sistema]
a --> d[Es un objeto con tres dimensiones]
d --> e[Volumen con escala en metros]
a --> f[Requiere aislar a la persona]
f --> g[Espacio inmersivo acotado y reversible]
c --> h[Convivencia con otras apps]
e --> h
g --> i[Salida clara y devolucion del entorno]

Queda una dimensión que no aparece en ninguna otra plataforma y que conviene tratar como requisito y no como refinamiento: la comodidad física. El movimiento amplio de contenido que rodea a la persona puede provocar malestar vestibular real, y no basta con moderarlo, hay que respetar el ajuste de reducir movimiento. Los elementos anclados a la cabeza que siguen la mirada resultan opresivos y deben evitarse salvo excepciones muy justificadas. Y los contenidos muy cercanos fuerzan una convergencia ocular que cansa en minutos: hay una distancia cómoda de trabajo, y acercarse a la cara para llamar la atención es la versión espacial de gritar.

Qué merece salir del rectángulo

Con todo lo anterior sobre la mesa, la decisión práctica se simplifica. Una app de iPad razonablemente adaptativa ya se ejecuta en visionOS como ventana, y con frecuencia lo hace bien: el contenido plano en un plano es una correspondencia honesta. El trabajo de adaptación empieza por lo pequeño —comprobar objetivos y separaciones, adoptar el material del sistema, revisar que nada dependa del tacto directo ni de gestos de varios dedos sobre la superficie— y solo después plantea la pregunta interesante.

Esa pregunta no es qué parte de mi app puede volverse tridimensional, sino qué información de mi app pierde algo al estar aplastada. Un plano de una casa, una molécula, una pieza mecánica, un terreno o una escultura son objetos que la representación plana empobrece, y ahí un volumen añade comprensión medible. Un panel de control, una lista de mensajes, un formulario o una tabla no ganan nada al ganar grosor; solo pierden legibilidad y añaden trabajo ocular.

@Environment(\.openWindow) private var abrirVentana

Button("Ver en tres dimensiones") {
    abrirVentana(id: "modelo")      // el volumen es un destino, no el punto de partida
}

Ese patrón —una ventana plana como base y un volumen que se abre bajo demanda— es el que mejor envejece, y por una razón que va más allá de la prudencia. La ventana es donde se navega, se busca y se lee, tareas para las que el plano es superior; el volumen es donde se examina un objeto concreto, tarea para la que el plano es inferior. Repartir así el trabajo respeta la fortaleza de cada contenedor en lugar de pedir a uno que haga el trabajo del otro, que es exactamente la clase de decisión que el nivel entero viene reclamando desde la primera lección.

Hay también una consideración social que ninguna plataforma anterior planteaba. La persona que usa el visor puede estar acompañada, y lo que tu app muestre determina cuánto del entorno sigue visible para ella y cuánto de su rostro sigue visible para los demás. Una app que ocupa el espacio completo sin necesidad convierte una habitación compartida en un aislamiento, y una que atenúa el entorno a media tarea puede sorprender a alguien en mitad de una conversación. Por eso las transiciones entre grados de inmersión deben ser graduales, anunciadas y siempre reversibles con un gesto que la persona ya conozca.

ℹ️
Lo que se rompe al portar sin revisar

Los gestos de varios dedos sobre una superficie no existen. Las esquinas de la pantalla no son zonas alcanzables. El texto blanco pequeño sobre fondos oscuros se lee peor que en un panel emisor. Y cualquier suposición sobre un ancho fijo desaparece, porque la persona redimensiona la ventana con las manos y la coloca a la distancia que le conviene.

Cuando el contenedor deja de ser neutral, el diseño deja de poder ignorar el cuerpo

Durante cuarenta años el diseño de interfaces pudo permitirse tratar al cuerpo humano como un supuesto de fondo: había un ojo a cierta distancia, un dedo o un ratón, y todo lo demás era problema de la ergonomía de la silla. visionOS retira esa comodidad. Aquí la disposición de los elementos determina cuánto gira un cuello, la profundidad determina cuánto converge un par de ojos, la escala determina si un objeto resulta acogedor o invasivo, y el movimiento determina si alguien siente náusea. Nada de eso es metafórico ni se resuelve con una constante de animación bien elegida: son magnitudes físicas con umbrales fisiológicos documentados, y por primera vez el diseño de software tiene que rendirles cuentas del mismo modo que se las rinde una silla o una herramienta manual. La conclusión que conviene extraer no es que visionOS sea más difícil, sino que hace explícito un compromiso que siempre existió y que las pantallas ocultaban por caridad: toda interfaz impone una postura, un ritmo y un esfuerzo a un cuerpo concreto. La diferencia es que en el cristal el cuerpo podía compensar los errores del diseñador acercándose, girando el aparato o cambiando de mano, y en el espacio no puede, porque el aparato ya está puesto y la habitación es la que es. Diseñar aquí bien enseña a mirar hacia atrás y descubrir cuántas de las decisiones que tomabas por costumbre eran, en realidad, apuestas sobre el cuerpo de otra persona.

📝
Lo esencial

Hay tres contenedores con tres contratos: ventana para contenido plano y convivencia, volumen para objetos con escala real en metros, espacio inmersivo para cuando el aislamiento es el valor entregado. La entrada es mirada más pellizco: objetivos grandes y separados, formas de contenido que coincidan con el dibujo, y la mirada nunca llega a tu código. La profundidad es física y por tanto se usa poco y con propósito, con el material del sistema como fondo. Y solo merece volumen aquello que la representación plana empobrece.

⚔️ Sacar una app del cristal con criterio
  1. Ejecuta tu app existente como ventana y recorre la tarea principal anotando cada objetivo demasiado pequeño o demasiado próximo a su vecino.
  2. Sustituye los fondos opacos por el material del sistema y comprueba la legibilidad contra una pared clara y contra una ventana con luz.
  3. Recorre la misma tarea sin mover el cuello y reubica todo lo que te obligue a girar la cabeza o a mirar por encima del horizonte.
  4. Identifica un único elemento de tu contenido que pierda información al estar aplastado y prototípalo como volumen con dimensiones en metros.
  5. Si añades un espacio inmersivo, diseña primero su salida: cómo se cierra, qué devuelve al entorno y qué ocurre si alguien entra en la habitación.