Cómo funciona el contenido interactivo de la BBC en AMP, aplicaciones y la Web

 

 

 

  • SmashingConf Nueva York 2024
  • Implemente rápidamente. Implementar inteligentemente

  • Índice
    1. Ejemplo: Canónico vs. AMPERIO
    2. Las herramientas son clave
      1. Insertar vs. Ser único
    3. La abstracción es clave
    4. El patrón de envoltura
    5. Estructura de envoltura
      1. API contenedora
      2. Lista de envoltorios
    6. Envolturas de cableado hasta las plataformas
    7. La abstracción es difícil
      1. Las características de la plataforma son difíciles de configurar de forma abstracta
      2. El comportamiento de los componentes puede ser complejo
      3. ¿Cómo manejamos las funciones faltantes?
    8. Planes para el futuro
      1. Otras lecturas

    Cada plataforma tiene sus propias limitaciones y mecanismo de publicación propietario. Crear contenido interactivo que funcione en todos estos entornos es un verdadero desafío. Publicar contenido en tantos medios sin muchos gastos generales de desarrollo adicionales puede resultar complicado. En este artículo, Chris Ashton explica cómo abordaron el problema en el departamento de Periodismo Visual de la BBC.

     

    En el equipo de Periodismo Visual de la BBC, producimos contenido visual interesante, atractivo e interactivo, que va desde calculadoras hasta visualizaciones y nuevos formatos de narración .

    Cada aplicación es un desafío único de producir por sí misma, pero aún más si se considera que tenemos que implementar la mayoría de los proyectos en muchos idiomas diferentes . Nuestro contenido tiene que funcionar no sólo en los sitios web de noticias y deportes de la BBC, sino también en sus aplicaciones equivalentes en iOS y Android, así como en sitios de terceros que consumen contenido de la BBC.

    Ahora considere que existe una gama cada vez mayor de nuevas plataformas como AMP, Facebook Instant Articles y Apple News. Cada plataforma tiene sus propias limitaciones y mecanismo de publicación propietario. Crear contenido interactivo que funcione en todos estos entornos es un verdadero desafío. Voy a describir cómo hemos abordado el problema en la BBC.

    Ejemplo: Canónico vs. AMPERIO

    Todo esto es un poco teórico hasta que lo ves en acción, así que profundicemos en un ejemplo.

    Aquí hay un artículo de la BBC que contiene contenido de periodismo visual:

    Nuestro contenido de Periodismo Visual comienza con la ilustración de Donald Trump, y está dentro de un iframe

    Esta es la versión canónica del artículo, es decir, la versión predeterminada, que obtendrá si navega al artículo desde la página de inicio.

    Ahora veamos la versión AMP del artículo :

    Parece el mismo contenido que el artículo normal, pero incluye un iframe diferente diseñado específicamente para AMP.

    Si bien las versiones canónica y AMP parecen iguales, en realidad son dos puntos finales diferentes con comportamiento diferente:

    • La versión canónica lo lleva al país elegido cuando envía el formulario.
    • La versión AMP no le permite desplazarse, ya que no puede desplazarse por la página principal desde un iframe de AMP.
    • La versión AMP muestra un iframe recortado con un botón "Mostrar más", según el tamaño de la ventana gráfica y la posición de desplazamiento. Esta es una característica de AMP.

    Además de las versiones canónica y AMP de este artículo, este proyecto también se envió a la aplicación News, que es otra plataforma con sus propias complejidades y limitaciones. Entonces, ¿cómo apoyamos todas estas plataformas?

     

    Las herramientas son clave

    No construimos nuestro contenido desde cero. Tenemos un andamio basado en Yeoman que utiliza Node para generar un proyecto repetitivo con un solo comando.

    Los nuevos proyectos vienen con Webpack , SASS , implementación y una estructura de componentes lista para usar. La internacionalización también está integrada en nuestros proyectos, utilizando un sistema de plantillas de manillar . Tom Maslen escribe sobre esto en detalle en su publicación, 13 consejos para hacer que el diseño web responsivo sea multilingüe .

    De fábrica, esto funciona bastante bien para compilar para una plataforma, pero necesitamos admitir múltiples plataformas . Profundicemos en algo de código.

    Insertar vs. Ser único

    En periodismo visual, a veces publicamos nuestro contenido dentro de un iframe para que pueda ser una "incrustación" autónoma en un artículo, sin verse afectada por las secuencias de comandos y el estilo globales. Un ejemplo de esto es el interactivo de Donald Trump incluido en el ejemplo canónico anterior en este artículo.

    Por otro lado, a veces mostramos nuestro contenido como HTML sin formato. Sólo hacemos esto cuando tenemos control sobre toda la página o si necesitamos una interacción de desplazamiento realmente receptiva . Llamemos a estas nuestras salidas “incrustadas” e “independientes” respectivamente.

    Imaginemos cómo podríamos construir el “¿ Un robot quitará tu trabajo?” ”interactivo tanto en formato “incrustado” como “independiente”.

    Ejemplo artificial que muestra una "incrustación" a la izquierda, frente al contenido como una página "independiente" a la derecha

    Ambas versiones del contenido compartirían la gran mayoría de su código, pero habría algunas diferencias cruciales en la implementación de JavaScript entre las dos versiones.

    Por ejemplo, mire el botón "Descubra mi riesgo de automatización". Cuando el usuario presiona el botón enviar, debería desplazarse automáticamente a sus resultados.

    La versión "independiente" del código podría verse así:

    button.on('click', (e) = { window.scrollTo(0, resultsContainer.offsetTop);});

    Pero si estuviera creando esto como salida "incrustada", sabrá que su contenido está dentro de un iframe, por lo que necesitará codificarlo de manera diferente:

    // inside the iframebutton.on('click', () = { window.parent.postMessage({ name: 'scroll', offset: resultsContainer.offsetTop }, '*');});// inside the host pagewindow.addEventListener('message', (event) = { if (event.data.name === 'scroll') { window.scrollTo(0, iframe.offsetTop + event.data.offset); }});

    Además, ¿qué pasa si nuestra aplicación necesita pasar a pantalla completa? Esto es bastante fácil si estás en una página "independiente":

    document.body.className += ' fullscreen';
    .fullscreen { position: fixed; top: 0; left: 0; right: 0; bottom: 0;}

    Utilizamos con éxito la funcionalidad de pantalla completa para aprovechar al máximo nuestro módulo de mapas en dispositivos móviles.

     

    Si intentáramos hacer esto desde dentro de una “incrustación”, este mismo código tendría el contenido escalado al ancho y alto del iframe , en lugar de a la ventana gráfica:

    Puede resultar difícil pasar a pantalla completa desde un iframe

    …así que además de aplicar el estilo de pantalla completa dentro del iframe, tenemos que enviar un mensaje a la página anfitriona para aplicar el estilo al propio iframe:

    // iframewindow.parent.postMessage({ name: 'window:toggleFullScreen' }, '*');// host pagewindow.addEventListener('message', function () { if (event.data.name === 'window:toggleFullScreen') { document.getElementById(iframeUid).className += ' fullscreen'; }});

    Esto puede traducirse en una gran cantidad de código espagueti cuando comienzas a admitir múltiples plataformas:

    button.on('click', (e) = { if (inStandalonePage()) { window.scrollTo(0, resultsContainer.offsetTop); } else { window.parent.postMessage({ name: 'scroll', offset: resultsContainer.offsetTop }, '*'); }});

    Imagine hacer un equivalente de esto para cada interacción DOM significativa en su proyecto. Una vez que hayas terminado de estremecerte, prepárate una relajante taza de té y sigue leyendo.

    La abstracción es clave

    En lugar de obligar a nuestros desarrolladores a manejar estos condicionales dentro de su código, construimos una capa de abstracción entre su contenido y el entorno. A esta capa la llamamos "envoltorio".

    En lugar de consultar el DOM o los eventos del navegador nativo directamente, ahora podemos enviar nuestra solicitud a través del wrappermódulo.

    import wrapper from 'wrapper';button.on('click', () = { wrapper.scrollTo(resultsContainer.offsetTop);});

    Cada plataforma tiene su propia implementación contenedora que se ajusta a una interfaz común de métodos contenedores. El contenedor envuelve nuestro contenido y maneja la complejidad por nosotros.

    Implementación simple de 'scrollTo' mediante el contenedor independiente

    La implementación de la scrollTofunción por parte del contenedor independiente es muy simple, pasando nuestro argumento directamente al window.scrollTointerior.

    Ahora veamos un contenedor separado que implementa la misma funcionalidad para el iframe:

    Implementación avanzada de 'scrollTo' mediante el contenedor de inserción

    El contenedor "incrustado" toma el mismo argumento que en el ejemplo "independiente", pero manipula el valor para que se tenga en cuenta el desplazamiento del iframe. Sin esta adición, habríamos desplazado a nuestro usuario a algún lugar completamente involuntario.

    El patrón de envoltura

    El uso de contenedores da como resultado un código más limpio, más legible y consistente entre proyectos. También permite microoptimizaciones a lo largo del tiempo, a medida que realizamos mejoras incrementales en los contenedores para que sus métodos sean más eficaces y accesibles. Por tanto, su proyecto puede beneficiarse de la experiencia de muchos desarrolladores.

     

    Entonces, ¿cómo es un envoltorio?

    Estructura de envoltura

    Cada contenedor comprende esencialmente tres cosas: una plantilla de manillar, un archivo JS contenedor y un archivo SASS que indica el estilo específico del contenedor. Además, hay tareas de compilación que se conectan con eventos expuestos por el andamio subyacente para que cada contenedor sea responsable de su propia precompilación y limpieza.

    Esta es una vista simplificada del contenedor de inserción:

    embed-wrapper/ templates/ wrapper.hbs js/ wrapper.js scss/ wrapper.scss

    Nuestro andamio subyacente expone su plantilla de proyecto principal como un parcial de Manillar, que es consumido por el contenedor. Por ejemplo, templates/wrapper.hbspodría contener:

    div {{your-application}}/div

    scss/wrapper.scsscontiene un estilo específico del contenedor que el código de su aplicación no debería necesitar definir por sí mismo. El contenedor de inserción, por ejemplo, replica gran parte del estilo de BBC News dentro del iframe.

    Finalmente, js/wrapper.jscontiene la implementación iframed de la API contenedora, que se detalla a continuación. Se envía por separado al proyecto, en lugar de compilarse con el código de la aplicación; lo marcamos wrappercomo global en nuestro proceso de compilación de Webpack. Esto significa que aunque entregamos nuestra aplicación a múltiples plataformas, solo compilamos el código una vez. Literatura y libros

    API contenedora

    La API contenedora abstrae una serie de interacciones clave del navegador. Aquí están los más importantes:

    scrollTo(int)

    Se desplaza a la posición dada en la ventana activa. El contenedor normalizará el número entero proporcionado antes de activar el desplazamiento para que la página del host se desplace a la posición correcta.

    getScrollPosition: int

    Devuelve la posición de desplazamiento actual (normalizada) del usuario. En el caso del iframe, esto significa que la posición de desplazamiento pasada a su aplicación es en realidad negativa hasta que el iframe esté en la parte superior de la ventana gráfica. Esto es muy útil y nos permite hacer cosas como animar un componente solo cuando aparece a la vista.

    onScroll(callback)

    Proporciona un enlace al evento de desplazamiento. En el contenedor independiente, esto es esencialmente conectarse al evento de desplazamiento nativo. En el contenedor de inserción, habrá un ligero retraso en la recepción del evento de desplazamiento ya que se pasa a través de postMessage.

    viewport: {height: int, width: int}

    Un método para recuperar la altura y el ancho de la ventana gráfica (ya que esto se implementa de manera muy diferente cuando se consulta desde dentro de un iframe).

    toggleFullScreen

    En el modo independiente, ocultamos el menú y el pie de página de la BBC y configuramos position: fixednuestro contenido. En la aplicación Noticias, no hacemos nada en absoluto: el contenido ya está en pantalla completa. El complicado es el iframe, que se basa en la aplicación de estilos tanto dentro como fuera del iframe, coordinados mediante postMessage.

     

    markPageAsLoaded

    Dígale al contenedor que se ha cargado su contenido. Esto es crucial para que nuestro contenido funcione en la aplicación de noticias, que no intentará mostrar nuestro contenido al usuario hasta que le indiquemos explícitamente a la aplicación que nuestro contenido está listo. También elimina el control giratorio de carga en las versiones web de nuestro contenido.

    Lista de envoltorios

    En el futuro, prevemos crear contenedores adicionales para grandes plataformas como Facebook Instant Articles y Apple News. Hemos creado seis contenedores hasta la fecha:

    Envoltorio independiente

    La versión de nuestro contenido que debería ir en páginas independientes. Viene incluido con la marca BBC.

    Insertar contenedor

    La versión iframed de nuestro contenido, que es segura para ubicarse dentro de artículos o distribuirse en sitios que no sean de la BBC, ya que conservamos el control sobre el contenido.

    Envoltorio AMP

    Este es el punto final que se incorpora como una amp-iframepágina AMP.

    Envoltorio de aplicación de noticias

    Nuestro contenido debe realizar llamadas a un bbcvisualjournalism://protocolo propietario.

    Envoltorio de núcleo

    Contiene solo HTML, nada de CSS o JavaScript de nuestro proyecto.

    Envoltorio JSON

    Una representación JSON de nuestro contenido, para compartir entre los productos de la BBC.

    Envolturas de cableado hasta las plataformas

    Para que nuestro contenido aparezca en el sitio de la BBC, proporcionamos a los periodistas una ruta con espacio de nombres:

    /include/[department]/[unique ID], e.g. /include/visual-journalism/123-quiz

    El periodista coloca esta "ruta de inclusión" en el CMS, que guarda la estructura del artículo en la base de datos. Todos los productos y servicios se encuentran detrás de este mecanismo de publicación. Cada plataforma es responsable de elegir el tipo de contenido que desea y solicitar ese contenido a un servidor proxy.

    Tomemos el interactivo de Donald Trump de antes. Aquí, la ruta de inclusión en el CMS es:

    /include/newsspec/15996-trump-tracker/english/index

    La página del artículo canónico sabe que quiere la versión "incrustada" del contenido, por lo que la agrega /embeda la ruta de inclusión:

    /include/newsspec/15996-trump-tracker/english/index/embed

    …antes de solicitarlo al servidor proxy:

    https://news.files.bbci.co.uk/include/newsspec/15996-trump-tracker/english/index/embed

    La página AMP, por otro lado, ve la ruta de inclusión y agrega /amp:

    /include/newsspec/15996-trump-tracker/english/index/amp

    El renderizador de AMP hace un poco de magia para renderizar algo de HTML de AMP que hace referencia a nuestro contenido, incorporando la /ampversión como un iframe:

     

    amp-iframe src="https://news.files.bbci.co.uk/include/newsspec/15996-trump-tracker/english/index/amp" !-- some other AMP elements here --/amp-iframe

    Cada plataforma compatible tiene su propia versión del contenido:

    /include/newsspec/15996-trump-tracker/english/index/amp/include/newsspec/15996-trump-tracker/english/index/core/include/newsspec/15996-trump-tracker/english/index/envelope...etcétera

    Esta solución puede ampliarse para incorporar más tipos de plataformas a medida que surjan.

    La abstracción es difícil

    Construir una arquitectura de “escribir una vez e implementar en cualquier lugar” suena bastante idealista, y lo es. Para que la arquitectura contenedora funcione, debemos ser muy estrictos al trabajar dentro de la abstracción. Esto significa que tenemos que luchar contra la tentación de "hacer este truco para que funcione en [inserte el nombre de la plataforma aquí]". Queremos que nuestro contenido desconozca por completo el entorno en el que se envía, pero es más fácil decirlo que hacerlo.

    Las características de la plataforma son difíciles de configurar de forma abstracta

    Antes de nuestro enfoque de abstracción, teníamos control total sobre cada aspecto de nuestra producción, incluido, por ejemplo, el marcado de nuestro iframe. Si necesitáramos modificar algo por proyecto, como agregar un titleatributo al iframe por razones de accesibilidad, simplemente podríamos editar el marcado.

    Ahora que el marcado contenedor existe aislado del proyecto, la única forma de configurarlo sería exponer un gancho en el propio andamio. Podemos hacer esto con relativa facilidad para funciones multiplataforma, pero exponer ganchos para plataformas específicas rompe la abstracción. Realmente no queremos exponer una opción de configuración de 'título de iframe' que solo sea utilizada por un contenedor.

    Podríamos nombrar la propiedad de manera más genérica, por ejemplo title, y luego usar este valor como atributo de iframe title. Sin embargo, empieza a resultar difícil realizar un seguimiento de qué se utiliza y dónde, y corremos el riesgo de abstraer nuestra configuración hasta el punto de no comprenderla. En general, intentamos mantener nuestra configuración lo más sencilla posible, configurando solo propiedades que tengan uso global.

    El comportamiento de los componentes puede ser complejo

    En la web, nuestro módulo sharetools muestra botones para compartir en redes sociales en los que se puede hacer clic individualmente y abren un mensaje para compartir precargado en una nueva ventana.

    Las herramientas para compartir de BBC Visual Journalism presentan una lista de opciones para compartir en redes sociales

    En la aplicación de noticias, no queremos compartir a través de la web móvil. Si el usuario tiene instalada la aplicación correspondiente (por ejemplo, Twitter), queremos compartirla en la propia aplicación. Idealmente, queremos presentarle al usuario el menú para compartir nativo de iOS/Android y luego permitirle elegir su opción para compartir antes de abrirle la aplicación con un mensaje para compartir previamente completado. Podemos activar el menú compartido nativo desde la aplicación haciendo una llamada al bbcvisualjournalism://protocolo propietario.

     

    Menú nativo para compartir en Android

    Sin embargo, esta pantalla se activará si tocas 'Twitter' o 'Facebook' en la sección 'Comparte tus resultados', por lo que el usuario termina teniendo que hacer su elección dos veces; la primera vez dentro de nuestro contenido y una segunda vez en la ventana emergente nativa.

    Este es un viaje de usuario extraño, por lo que queremos eliminar los íconos de compartir individuales de la aplicación Noticias y mostrar en su lugar un botón de compartir genérico. Podemos hacer esto comprobando explícitamente qué contenedor está en uso antes de renderizar el componente.

    Botón genérico para compartir utilizado en la aplicación de noticias

    La creación de la capa de abstracción del contenedor funciona bien para proyectos en su conjunto, pero cuando la elección del contenedor afecta los cambios a nivel de componente , es muy difícil mantener una abstracción limpia. En este caso, hemos perdido un poco de abstracción y tenemos una lógica de bifurcación desordenada en nuestro código. Afortunadamente, estos casos son pocos y espaciados.

    ¿Cómo manejamos las funciones faltantes?

    Mantener la abstracción está muy bien. Nuestro código le dice al contenedor lo que quiere que haga la plataforma, por ejemplo, "ir a pantalla completa". Pero, ¿qué pasa si la plataforma a la que realizamos el envío no puede funcionar en pantalla completa?

    El envoltorio hará todo lo posible para no romperse por completo, pero en última instancia, necesita un diseño que vuelva elegantemente a una solución funcional, independientemente de que el método tenga éxito o no. Tenemos que diseñar a la defensiva.

    Digamos que tenemos una sección de resultados que contiene algunos gráficos de barras. A menudo nos gusta mantener los valores del gráfico de barras en cero hasta que los gráficos se desplacen a la vista, momento en el que activamos las barras que se animan a su ancho correcto.

    Gráfico de barras que muestra valores relevantes para mi área

    Pero si no tenemos un mecanismo para engancharnos en la posición de desplazamiento, como es el caso de nuestro contenedor AMP, entonces las barras permanecerían siempre en cero, lo cual es una experiencia completamente engañosa.

    Cómo podría verse el gráfico de barras si los eventos de desplazamiento no se reenvían

    Intentamos cada vez más adoptar un enfoque de mejora progresiva en nuestros diseños. Por ejemplo, podríamos proporcionar un botón que será visible para todas las plataformas de forma predeterminada, pero que se ocultará si el contenedor admite el desplazamiento. De esa manera, si el desplazamiento no logra activar la animación, el usuario aún puede activar la animación manualmente.

    En su lugar, podríamos mostrar un botón alternativo, que activa la animación al hacer clic.

    Planes para el futuro

    Esperamos desarrollar nuevos contenedores para plataformas como Apple News y Facebook Instant Articles, así como ofrecer a todas las plataformas nuevas una versión "básica" de nuestro contenido lista para usar.

    También esperamos mejorar en la mejora progresiva; Tener éxito en este campo significa desarrollarse defensivamente. Nunca se puede asumir que todas las plataformas, ahora y en el futuro, respaldarán una interacción determinada, pero un proyecto bien diseñado debería poder transmitir su mensaje central sin caer ante el primer obstáculo técnico.

    Trabajar dentro de los límites del contenedor es un cambio de paradigma y se siente como un punto intermedio en términos de solución a largo plazo . Pero hasta que la industria madure hacia un estándar multiplataforma, los editores se verán obligados a implementar sus propias soluciones o utilizar herramientas como Distro para la conversión de plataforma a plataforma, o ignorar por completo secciones enteras de su audiencia.

    Es temprano para nosotros, pero hasta ahora hemos tenido un gran éxito en el uso del patrón contenedor para crear nuestro contenido una vez y entregarlo a la gran cantidad de plataformas que nuestras audiencias están usando ahora.

    Otras lecturas

    • Una descripción general de alto nivel de conceptos, casos de uso y herramientas de modelos de lenguaje grandes
    • Explorando el potencial de los trabajadores web para subprocesos múltiples en la Web
    • Ajuste de desplazamiento CSS alineado con el diseño de página global: un estudio de caso de control deslizante de ancho completo
    • JavaScript básico, bibliotecas y la búsqueda de una representación DOM con estado

    (rb, ra, il, mrn)Explora más en

    • Aplicaciones
    • AMPERIO
    • Estudios de caso
    • javascript





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Cómo funciona el contenido interactivo de la BBC en AMP, aplicaciones y la Web

    Cómo funciona el contenido interactivo de la BBC en AMP, aplicaciones y la Web

    Ejemplo: Canónico vs. AMPERIOLas herramientas son claveLa abstracción es claveEl patrón de envolturaEstructura de envolturaEnvolturas de cableado hasta las

    programar

    es

    https://pseint.es/static/images/programar-como-funciona-el-contenido-interactivo-de-la-bbc-en-amp-948-0.jpg

    2024-05-20

     

    Cómo funciona el contenido interactivo de la BBC en AMP, aplicaciones y la Web
    Cómo funciona el contenido interactivo de la BBC en AMP, aplicaciones y la Web

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Update cookies preferences