Novedades del producto
Ya está aquí el PanelWave Player

El reproductor de Angular con licencia MIT ya está en npm: navegación por grafo con estado real, tres modos de vista incluido el lienzo infinito, viñetas de vídeo, el motor de dibujo ComicBalloon, zonas interactivas y variantes en vivo, reglas de muro de pago con verificación de edad, medición de audiencia que respeta el consentimiento y un sandbox para plugins. Te contamos qué incluye, cómo integrarlo y qué falta todavía.
El PanelWave Player es la mitad abierta del ecosistema: una biblioteca de Angular con licencia MIT (Angular 20, 21 y 22) que toma un manifiesto de PanelWave y lo convierte en una experiencia de lectura, con navegación, localización, multimedia y controles para el lector incluidos. Está en el registro público de npm como @panelwave/player, actualmente en la versión 1.2.0: instálalo con npm install @panelwave/player. Todas las fases de funciones principales están implementadas y las pruebas unitarias pasan en verde. Una batería de pruebas de extremo a extremo con Playwright, con comprobaciones de accesibilidad de axe-core, se ejecuta en navegadores de escritorio y móviles. Y la documentación del reproductor describe la biblioteca tal como se comporta de verdad, con sus imperfecciones.
El código fuente está en github.com/panelwave/player, y una demo en directo ejecuta las historias de ejemplo en tu navegador. En este artículo recorremos lo que incluye el reproductor, cómo integrarlo en cinco minutos, los puntos de integración que interesan a quien lo aloja, lo que trae la próxima versión y una lista honesta de lo que aún no está terminado. Si solo quieres la API, ve directamente a Entradas y salidas.
Lo que muestra el reproductor
Una obra es un conjunto de capítulos cuyas viñetas son nodos de un grafo dirigido. El reproductor recorre ese grafo, evaluando condiciones JSON Logic en las aristas, y compone cada viñeta a partir de sus capas: imágenes con carga diferida y caché, capas de vídeo con modos de reproducción y disparadores de inicio, capas de texto y de plugin aisladas en un sandbox, y bocadillos dibujados por el motor ComicBalloon. Las viñetas se leen de una en una en la vista de viñeta, se componen en páginas de cómic en la vista de página o se recorren en un plano continuo en la vista de lienzo. La versión 1.2.0 lee el formato PanelWave hasta la versión 1.6; la visión general tiene la tabla completa de funciones.
Ramificación real, con estado
La ramificación no es un modo especial. El motor de flujo reúne las aristas de salida de la viñeta actual, evalúa sus condiciones con los valores del almacén de variables y elige la coincidencia de mayor prioridad. Los cambios de variables que lleva una arista se aplican cuando el lector la recorre, y al navegar hacia atrás se restauran tanto la posición como el estado. Cuando hay varios caminos abiertos, el botón Choices de la barra de herramientas deja elegir al lector; cada opción lleva el texto de su arista. Las variables viven en cinco ámbitos (global, chapter, page, session, persistent), tienen tipo y se validan en cada escritura, y el ámbito persistente sobrevive a las recargas gracias a localStorage. Ante un error, las condiciones se cierran: un fallo de evaluación cuenta como falso, y una arista sin condición siempre se puede recorrer. La mecánica del runtime está documentada paso a paso en Estado, condiciones y navegación, y los detalles del almacenamiento en Guardar el progreso.
Las definiciones de variables del manifiesto están conectadas al almacén, así que los valores predeterminados, los tipos, los rangos y los indicadores de solo lectura se aplican desde la primera viñeta. Y la ventana de ajustes tiene una pestaña Variables: las definiciones marcadas como públicas aparecen con un editor según su tipo. Así, un creador puede poner a propósito interruptores de la historia en manos de los lectores (Ventana de ajustes).
Tres modos de vista, incluido el lienzo infinito
La vista de viñeta y la vista de página existen desde las primeras fases. La vista de lienzo, añadida con el formato 1.4, coloca todas las viñetas de un capítulo en un único plano y desliza una cámara entre ellas siguiendo el grafo narrativo: en línea recta, en arco o por puntos de paso que define el autor, con zoom fijo, de alejamiento o de inmersión. Cualquier acción del lector interrumpe el deslizamiento, como en una aplicación de mapas. Solo se montan las viñetas cercanas a la cámara, doce como máximo sea cual sea el tamaño del capítulo, y los modos de revelado mantienen ocultas las ramas secretas hasta que el lector llega a ellas. La semántica de navegación no cambia: «siguiente» sigue preguntando al motor de flujo. Detalles en Vista de lienzo y en la referencia del formato.
Viñetas de vídeo y un motor de audio de cuatro buses
Las capas de vídeo admiten los modos de reproducción once, loop y ping-pong, los disparadores de inicio al aparecer y al hacer clic, y el encadenamiento en la vista de página, donde los vídeos de una página se reproducen uno tras otro en orden de lectura. La reproducción automática tiene en cuenta el vídeo: espera a que un vídeo termine una pasada completa en lugar de seguir un reloj fijo, y un vigilante de bloqueos fuerza el avance si una fuente nunca termina. Nunca suena más de un vídeo a la vez. El motor de audio mezcla cuatro buses (ambiente, música, voz en off y efectos de sonido) con volumen y fundidos independientes, y respeta la política de reproducción automática del navegador. Consulta Audio, la referencia del formato de vídeo y Reproducción automática.
El motor de dibujo ComicBalloon
Los bocadillos son auténticos bocadillos de cómic, dibujados como SVG por una clase de TypeScript sin dependencias de framework: se mide el texto, el cuerpo es un squircle (o una nube de pensamiento, un estallido de grito, un susurro discontinuo, un cartucho de narrador de esquinas rectas, formas de cartucho con bordes cortados o un conector), el rabillo se integra en el contorno y las actualizaciones posteriores son ligeras. Hay diez tipos de bocadillo, protuberancias y picos deterministas, un efecto que oculta el borde de los bocadillos que se funden con el de la viñeta y fuentes de rotulación con licencia abierta incluidas en el paquete. El estilo se resuelve en cascada: valores predeterminados de la obra, ajuste por personaje, preajuste con nombre y ajuste por bocadillo. Como el CMS integra este mismo motor de dibujo, lo que rotula un creador es lo que ven los lectores. Balloon Renderer explica el proceso; Bocadillos cubre el lado del manifiesto.
Zonas interactivas y variantes de viñeta, en vivo
Las zonas interactivas que dibuja un creador funcionan en el reproductor: las regiones rectangulares, circulares y poligonales se muestran como áreas clicables con un contorno que pulsa suavemente (desactivado con movimiento reducido). Al activar una se ejecuta su acción: ir a una viñeta con una transición, asignar variables, abrir los extras en un elemento concreto, mostrar una ventana modal localizada o pasar el evento a un plugin. Las zonas interactivas se pueden usar con el teclado y anuncian sus etiquetas a los lectores de pantalla. Cada clic se registra como evento de medición con coordenadas normalizadas, y de ahí sale el mapa de calor de clics del CMS. Las variantes de viñeta también se resuelven en tiempo de ejecución: la primera variante cuya condición se cumple sustituye el contenido de la viñeta y se vuelve a evaluar cada vez que cambia una variable. Si una obra ofrece alternativas, el botón Alt de la barra de herramientas las recorre. Consulta Zonas interactivas y Variantes.
Localización sin recargar
Cada cadena que ve el lector es un LocalizedString con clave de idioma BCP-47, y los recursos pueden tener variantes por idioma. El reproductor resuelve ambos mediante una cadena de respaldo (idioma exacto, idioma base, idioma predeterminado de la obra, su idioma base, el primero disponible) y cambia de idioma al instante desde la ventana de idiomas de la barra de herramientas o con el método changeLocale. La interfaz propia del reproductor se traduce por separado mediante archivos de ngx-translate que sirve tu aplicación; el paquete incluye inglés y alemán. Localización explica ambos niveles y la cadena de respaldo.
Rendimiento en redes lentas y dispositivos modestos
Tres mecanismos hacen el trabajo pesado. Una cola de precarga por prioridades con concurrencia limitada se adapta a la Network Information API, baja a cero cuando el lector tiene activado el ahorro de datos y carga por adelantado las ilustraciones a las que llevan las aristas de salida de la viñeta actual. Una caché de imágenes LRU decodifica fuera del hilo principal con createImageBitmap, con un presupuesto de 100 MB. Y la selección de variantes elige el escalón de imagen más pequeño que cubre el ancho real de visualización por viñeta, por modo de vista y por nivel de zoom, cuantizado en pasos de 256 píxeles y solo hacia arriba, de modo que en un móvil se descargan escalones WebP pequeños y en una pantalla 4K con zoom llega la codificación completa. Todos los componentes usan OnPush. Los detalles están en la página Rendimiento.
Accesibilidad por defecto
Cada botón de la barra de herramientas lleva un aria-label traducido y los interruptores exponen aria-pressed. El área de visualización es una región etiquetada que se activa con el teclado, las viñetas de la vista de página pueden recibir el foco y las zonas interactivas están en el orden de tabulación. El movimiento reducido se activa cuando lo pide el sistema operativo, el interruptor del propio lector en la ventana de ajustes o la entrada reducedMotion del sitio anfitrión: desactiva las animaciones de transición y convierte el vídeo que se inicia al aparecer en vídeo que se reproduce al hacer clic. La batería de Playwright ejecuta comprobaciones con axe-core en la integración continua. Consulta Accesibilidad.
Muros de pago, medición y plugins
El reproductor nunca procesa pagos. El manifiesto declara qué está restringido, por obra, capítulo, viñeta o bloque de extras, y el reproductor evalúa esas reglas con una instantánea de los derechos de acceso: se la pasa tu aplicación o la pide él mismo a tu endpoint una vez al arrancar. Quien llega a contenido bloqueado ve el muro de pago superpuesto, con las opciones Buy y Subscribe de la regla. Las viñetas de vista previa gratuita siguen abiertas, y una verificación de edad integrada en el reproductor protege el contenido con clasificación por edades. La elección del lector vuelve a tu aplicación por la salida paywallAction. Para decidir viñeta a viñeta desde tu propio servicio existe además un adaptador de derechos de acceso. Muro de pago y derechos de acceso te ayuda a elegir la integración adecuada.
La medición de audiencia respeta el consentimiento desde el diseño. Si el manifiesto exige consentimiento, no se registra nada hasta obtenerlo; solo se conservan los tipos de evento permitidos, los eventos de alta frecuencia se agrupan y los lotes se envían al endpoint que indica el manifiesto. Los sitios anfitriones también pueden prescindir del servicio y reenviar las salidas del shell a sus propias analíticas. Consulta Medición de audiencia.
Los plugins son páginas web normales en iframes aislados que se comunican con el anfitrión mediante postMessage bajo un modelo de permisos de doce capacidades, con estados de ciclo de vida y un protocolo documentado. Las viñetas también pueden integrar contenido de plugin directamente como capa de plugin, por ejemplo para un visor de 360 grados. Consulta Plugins.
Intégralo en cinco minutos
El componente que integras es el shell del reproductor. Es standalone, así que no hay ningún módulo que importar: añade provideHttpClient y un loader de TranslateModule a la configuración de tu aplicación, incluye una vez la hoja de estilos de las fuentes de bocadillos y apunta el shell a la URL de tu manifiesto (o descarga tú el JSON y pásalo como objeto). Tienes un ejemplo completo y funcional con un manifiesto mínimo válido en Inicio rápido: integración.
<pw-player-shell [manifestUrl]="manifestUrl" [locale]="'en-US'" [showToolbar]="true" [entitlementSnapshot]="snapshot" (ready)="onReady()" (panelChange)="savePosition($event)" (paywallAction)="onPaywall($event)" (localeChange)="onLocale($event)"> </pw-player-shell>
A partir de ahí, el shell te da todo lo que necesita un sitio de lectura: initialChapterId e initialPanelId para retomar donde lo dejó un lector, panelChange (con el id de la viñeta) y chapterChange para registrar el progreso y crear enlaces profundos, navigationAttempt para pantallas intermedias, error para tu propia interfaz de respaldo, y setVariable y changeLocale como métodos públicos. Entradas como locale, autoplay y el movimiento reducido se aplican en vivo mientras la obra está abierta. initialVariables pasa datos que conoce el anfitrión por una vía privilegiada, que aceptan incluso las variables de solo lectura. Los lectores pueden poner un marcador desde la barra de herramientas y la obra se vuelve a abrir ahí; un «sigue donde lo dejaste» automático es, deliberadamente, tarea del anfitrión, y Guardar el progreso contiene una implementación completa con localStorage que puedes pegar. Los valores predeterminados definidos en el manifiesto, como la visibilidad de los diálogos, los tiempos de reproducción automática, los preajustes tipográficos y la estrategia de precarga, se enumeran en Configuración.
Lo que añade la próxima versión
La próxima versión para npm ya está integrada en el código, y es la que se ve hoy en el lector web de PanelWave (read.panelwave.org) y en la vista previa del CMS. Lo más destacado:
Cada elemento está documentado con la nota «from the release after 1.2.0» en la documentación del reproductor, para que sepas de un vistazo qué hace la versión que tienes instalada.
- Formato 1.7. Los capítulos sin aristas en el grafo siguen sin más el orden de sus viñetas. Las viñetas que un lector no ha desbloqueado llegan del servidor como marcadores bloqueados. Las zonas interactivas pueden mostrar su etiqueta como un botón, así que las opciones de una decisión se ven aunque la ilustración no las pinte. Y los bocadillos se pueden rotular en cualquier color.
- Una vista de página que se ajusta a la pantalla. El reproductor elige la maquetación de página que el creador diseñó para el dispositivo, una para móvil en un móvil y la de pantalla grande en una pantalla 4K, y cambia al redimensionar la ventana. La rotulación se escala con la página y nunca baja de un tamaño legible.
- Una portada y un inicio de lectura claro. Una obra se abre en su portada y después en la vista de página; cada página y cada viñeta tiene su propia dirección para compartir, y ante una decisión, «siguiente» pregunta al lector en lugar de elegir por él.
- Pantalla completa, animaciones y más. Un botón de pantalla completa, animaciones de capas con fotogramas clave y movimientos de cámara dentro de una viñeta, varias portadas alternativas y una gestión más estricta del muro de pago, para que una viñeta bloqueada siga bloqueada también en la vista de página y en la de lienzo.
Para quienes quieran contribuir
Si quieres trabajar en la propia biblioteca, la documentación tiene un itinerario para contribuir: Arquitectura para la estructura del workspace, la gestión del estado y el flujo de datos del manifiesto al dibujo; Servicios principales para los servicios de manifiesto, estado, almacén de variables, motor de flujo, acciones de zonas interactivas, caché de imágenes, precarga, audio, vídeo, medición de audiencia y derechos de acceso, y cómo interactúan; Componentes para el shell, el área de visualización, los dibujantes de capas, las superposiciones, las ventanas modales y la barra de herramientas; y Desarrollo para la configuración, las baterías de Jasmine y Playwright, el linting y la compilación de producción.
Lo que queda pendiente
Preferimos que lo leas aquí a que lo descubras en un registro de la consola:
Cada uno de estos puntos tiene su incidencia abierta y está documentado justo donde te lo encontrarías.
- Los comentarios y la opción de compartir son solo interfaz. El cajón de comentarios y la ventana de compartir funcionan para el lector, pero guardar los comentarios es tarea del anfitrión (Controles de la barra de herramientas).
- El modo manga y el alto contraste se guardan, pero aún no se aplican. La ventana de ajustes conserva la elección del lector, pero la maquetación no cambia con ella.
- No hay reanudación automática. El reproductor restaura el marcador del lector, no la última viñeta leída; continuar donde lo dejó un lector corresponde al anfitrión, con una receta lista para usar en la documentación.
Pruébalo, intégralo, rómpelo
La aplicación de demostración del repositorio es la integración de referencia y puede cargar cualquier manifiesto desde una URL, así que una obra publicada desde el CMS como enlace de vista previa se abre en ella directamente. Si construyes algo con el reproductor, o encuentras un manifiesto que se muestra mal, el gestor de incidencias y la documentación del formato son los dos sitios por donde empezar. El formato es abierto, el reproductor es MIT y lo que ves en la vista previa del CMS es exactamente esta biblioteca.

