Hola, mi nombre es Dmitry Karlovsky y a veces hablo en conferencias, reuniones, y también, recientemente, yo mismo entro en el equipo de organizadores de uno de ellos: PiterJS . Recientemente tuvimos un aniversario: se celebraron 40 reuniones. Pero en lugar de relajarnos y recibir felicitaciones, nos cansamos y preparamos informes de los organizadores .

Pero esto no es suficiente para nosotros, por lo que decidimos celebrar un gran aniversario organizando una conferencia a orillas del Neva PiterJSConf , que se llevará a cabo este sábado 7 de septiembre de 2019. Date prisa para inscribirte, mientras todavía hay asientos vacíos, porque la participación en él será completamente gratis para ti.
Hacemos todo esto no por dinero, sino por la gran idea de que el conocimiento debe ser gratuito. Por lo tanto, todo lo que hacemos está disponible en código abierto . Estamos felices de compartir nuestras mejores prácticas, conocimiento y experiencia con otros. E instamos a la cooperación de organizadores de otras ciudades para crear una plataforma abierta para organizar reuniones tecnológicas de manera regular. Únase a nosotros como organizador , socio , orador , voluntario , patrocinador o simplemente un oyente.
Mientras tanto, le ofrezco una historia sobre la aplicación web de presentación $hyoo_slides
que uso para todas mis presentaciones. La grabación de video está disponible en YouTube , pero no todo está ahí. Puede leer esta historia como un artículo o abrirla en la interfaz de la aplicación misma . A continuación, le diré cuánto puede hacer y cómo funciona.
Interfaz de escucha
Presentación de escucha
Aquí está la interfaz que la audiencia ve durante la presentación. No hay nada superfluo en ello.
El nombre y el número de la diapositiva se muestran en la parte superior. Los oyentes pueden tener preguntas. Y registrando rápidamente este número, podrán nombrarlo después del discurso y así evitar que la audiencia espere tediosamente, cuando el orador encuentre una diapositiva en la que se hace la pregunta.
A continuación puede prestar atención a la barra de progreso, que muestra a los oyentes tardíos cuánto se perdieron. Y para todos los demás: cuánto queda hasta el final. Se calcula no por el número de diapositivas, sino por el volumen del discurso narrado.
Mira como puedo
La idea básica es dejar que el orador se concentre en el contenido y no se preocupe por el diseño. El informe no necesita bellezas especiales y animaciones espectaculares en absoluto. De lo contrario, el diseño llamará la atención sobre sí mismo. Y el contenido corre el riesgo de volar más allá de los oídos.

Sin embargo, el diseño debe ser ordenado para no estropear la impresión del informe. Por lo tanto, el diseño de la aplicación es simple, no pegadizo y, lo más importante, coherente con las recomendaciones de los comités del programa.
Interfaz de altavoz
La interfaz del hablante se divide en dos partes.
Presentación del presentador
A la izquierda está lo que ven los oyentes. Y a la derecha están las notas del orador. Te ayudarán a recordar un pensamiento perdido, sin alejarte de la audiencia y sin forzarlos por un largo ... um ... esto es ... una pausa.
Lo principal es el contenido.
Por lo tanto, en nuestro caso, el contenido se escribe como un artículo en formato MarkDown y se presenta en algunas páginas de GitHub. Y la aplicación web se encarga del resto.
# #
Después del discurso, la transcripción del texto del informe a menudo se presenta en forma de un artículo sobre algunos Habré . Pueden hacerlo durante un mes, dos, medio año. La tarea es una traducción desagradecida del discurso al texto. Pero, debido al hecho de que la fuente de las diapositivas ya está en formato de descuento y contiene los comentarios del orador, se pueden publicar de inmediato en este formulario.
Estilos de texto
El texto sin formato solo se muestra al presentador. Y todo tipo de imágenes, listas, tablas, citas, etc. son visibles para todos.
- ** - ** ** - ~~~~ - ``````
- Acento
- Acento fuerte
Eliminar
Por supuesto, hay varias herramientas de formato en línea disponibles.
Código fuente
Los bloques de código fuente, por supuesto, también son compatibles y están pintados en todos los colores del arco iris. Justo como te gusta.
```javascript const hello = ()=> <body> Hello, "world"! </body> ```
const hello = ()=> <body> Hello, "world"! </body>
Mesas
La comparación de varias cosas te ayudará en las tablas. Por ejemplo, veamos por qué $hyoo_slides
mejor que sus competidores más cercanos: shwr.me y google slides
| | shwr.me | google slides | slides.hyoo.ru | |--------------------------|---------|---------------|----------------| | MarkDown | - | - | + | | | - | + | + | | | - | - | + | | | - | + | + |
Como puede ver, $hyoo_slides
supera a los competidores en todos los frentes. Excepto los que no están incluidos en la tabla, por supuesto.
Bueno, Lano, las mesas son aburridas.
Imágenes
Sostén al gato.


Tenga en cuenta que el fondo de las diapositivas es ligeramente gris. Por lo tanto, es mejor preparar imágenes no sobre un fondo blanco, sino con transparencia para que no haya un rectángulo blanco desagradable alrededor de las imágenes. Esto se hace para que las áreas blancas se vean en contraste y no se fusionen con el fondo.
Video
Puede publicar videos, páginas web y cualquier otro contenido externo utilizando la misma sintaxis de MarkDown que para insertar imágenes.

Público objetivo
Por ejemplo, inserté un video que ilustra que las interfaces modernas son tan simples y convenientes que incluso un mono puede manejarlas.
Teclado de navegación
Puede cambiar las diapositivas con flechas en el teclado. Pero para no estar conectado a la computadora portátil, sino para caminar libremente por el escenario, necesitará un cable de extensión de radio para su dedo. El es un clicker.

Pero, ¿y si el clicker está roto?
Frases de código
¿Probablemente piensas que en la habitación tengo un cosaco maltratado que cambia de diapositivas en lugar de mí? Sin embargo, esto no es así.
- Más por favor.
- De vuelta , por favor.
- Diapositiva número 5, sé amable.
- Al principio , por favor.
- Al final , por favor.
- Encuentra el "gato", sé amable.
- Repite , por favor.
- Cállate , sé amable.
- Por favor continua .
- Apaga la luz , por favor.
Repite, por favor. Una voz desde arriba repite la última frase.
Sí, las diapositivas pueden controlar completamente la voz, dejando las manos libres para gestos. Utiliza una API web estándar para el reconocimiento y síntesis de voz.
Pero repetir estas frases de código diez veces seguidas es aburrido, por lo que $hyoo_slides
puede analizar las notas del orador y, cuando dices la última palabra, cambia la diapositiva automáticamente.
Gestos con los dedos
De acuerdo, complicando la situación. Alguien después de escuchar su discurso, decidió ver sus diapositivas de la tableta mientras viajaba en metro a su casa.

No hay teclado Los trenes son ruidosos. Aquí, los gestos comunes de los dedos vienen al rescate.
Fuera de línea
Pero luego llama al túnel y su conexión desaparece.

No importa, tenemos Web2.0 HTML5 Progressive Web Application con funcionalidad completa incluso cuando no hay Internet.
Impresión de PDF
Pero aquí los organizadores se acercan a usted y le dicen: "Queremos un PDF".

Cual pdf? Tenemos aquí la aplicación web interactiva multimedia HTML5 progresiva Web2.0. Sin embargo, le explican que la aplicación es hoy y mañana ya no está allí. Y si lo hay, quiere dinero. Y si no lo desea, las diapositivas ya se pueden cambiar más allá del reconocimiento. Y el PDF está en silencio en el archivo con exactamente el contenido que corresponde al video grabado durante la presentación.
Bueno, no importa, presione Ctrl+P
, seleccione "Imprimir en PDF" y obtenga lo que necesita. Esto se hace simplemente: se onbeforeprint
evento onbeforeprint
y, cuando ocurre, en lugar de solo la diapositiva actual, se procesan todas las diapositivas. Y onafterprint
, todos menos el actual, las diapositivas se eliminan.
En esto, las listas de características han terminado.
Cómo crear una presentación
Probar $hyoo_slides
es fácil. Necesitará readme.md
con su contenido e imágenes. También cerca tendrá que copiar y pegar index.html
, que redirige a la aplicación web y abre su presentación en ella. Y también offline.js para soporte fuera de línea.
Tenga en cuenta que este index.html
le dará a la aplicación todos los archivos a los que se pueda acceder desde el dominio en el que coloca todo. GitHub Pages es una opción muy conveniente y segura. Lo uso yo mismo.
Otras aplicaciones
Si le gustó esta aplicación, puede echar un vistazo a otras aplicaciones interesantes implementadas en el marco $ mol. Son tan livianos que incluso unas pocas docenas no tienen miedo de cargarlos todos a la vez en una diapositiva.
Galería de aplicaciones
Pero sobre ellos de alguna manera más tarde ...
Ejemplos de presentación
Puede obtener más información sobre el marco en una presentación separada. Puede profundizar en una presentación sobre el PPR. Y puede levantar el telón del futuro en una presentación sobre la cuantización de los cálculos.
Todos usan $ hyoo_slides para mostrar. Espero que pronto haya más presentaciones de este tipo.
Estructura de aplicación
Y ahora, abramos un poco el capó y veamos cómo está organizada la aplicación y cómo hacer nuestro similar en solo una noche.
$hyoo_slides_page $mol_view sub / <= Listener <= Speaker
export class $hyoo_slides_page extends $mol_view { sub() { return [ this.Listener() , this.Speaker() , ] } }
Aquí hay una descripción de nivel superior de una sola pantalla en view.tree y código TypeScript equivalente. Aquí declaramos el componente $hyoo_slides_page
, que extiende el componente base $mol_view
. Este componente tiene una propiedad sub
. Todo lo que devuelva esta propiedad se representará dentro del componente. Por lo tanto, lo redefinimos, pasando como valor una matriz de dos elementos: Listener
, un componente para enviar una diapositiva a los oyentes y Speaker
, un componente de un panel de altavoces adicional.
Cambiar diseño de página
Además de la descripción de la estructura, también podemos aplicar la lógica del programa que permite que cualquier propiedad se calcule dinámicamente.
sub() { const role = this.role() return [ this.Listener() , ... ( role === 'speaker' ) ? [ this.Speaker() ] : [] , ] }
Aquí la lógica es simple: siempre mostramos diapositivas para los oyentes, pero el panel del orador se muestra solo si el rol actual es el speaker
. Si el rol cambia, el diseño de la aplicación también cambiará debido a la magia de la programación reactiva de objetos.
Enrutamiento
Tomaremos el rol del parámetro de dirección, a través de la API reactiva especial $mol_state_arg
.
role() : 'speaker' | 'listener' { return $mol_state_arg.value( 'role' ) || 'speaker' }
Por alguna razón, la dirección ha cambiado: el rol se extraerá automáticamente y se pasará a este método.
Estructura de interfaz de escucha
Describamos la interfaz del oyente.
Listener $mol_page title <= title tools / <= Slide_switcher body / <= Listener_content <= Progress
Utiliza el componente estándar $mol_page
que dibuja una página típica con un encabezado y cuerpo. En el encabezado hay un área donde se muestra el nombre de la página. A través de la propiedad de title
, puede especificar qué generar allí. Lo que hicimos al asociar su propiedad de title
con nuestra propiedad del mismo nombre. Ahora, al cambiar nuestra propiedad, tenemos control total sobre lo que se mostrará en la página como título.
A la derecha en el encabezado, hay un área de salida para herramientas adicionales: tools
. En él, mostramos Slides_switcher
, un componente para mostrar el número de diapositiva y cambiar entre diapositivas adyacentes.
Y finalmente, como body
página en body
mostramos el contenido de la diapositiva y la barra de progreso.
Estructura de cambio de página
¿Cómo implementar Slide_switcher
? Simplemente use el componente estándar $mol_paginator
.
Slide_switcher $mol_paginator value?val <=> slide?val
Todo lo que tiene es un value
propiedad mutable, que asociamos bilateralmente con nuestra propiedad que contiene el número de la diapositiva actual. Sin importaciones, devoluciones de llamada, eventos y otra basura. Estas dos líneas son todo lo necesario para que un cambio de página de trabajo aparezca en su página.
Estructura de contenido de diapositiva
Para mostrar el contenido de la diapositiva, nuevamente usamos el componente estándar $mol_text
.
Listener_content $mol_text uri_base <= uri_base text <= listener_content
Toma markdown
y lo renderiza. Dado que los enlaces en este texto serán relativos al archivo fuente y no a nuestra aplicación, pasamos el enlace a la propiedad uri_base, con respecto a la cual se resolverán todas las rutas.
Estructura del indicador de progreso
Como probablemente ya haya adivinado, también hay un componente estándar para mostrar el progreso: $mol_portion
.
Progress $mol_portion portion <= progress
portion: [ 0 .. 1 ]
Le damos un número del 0 al 1 y obtenemos un indicador para este porcentaje.
Estructura de interfaz de altavoz
Tenemos algo más interesante en la interfaz del orador. Las herramientas que se muestran en el encabezado no están asociadas a la página actual de ninguna manera, son comunes a toda la aplicación. Por lo tanto, en lugar de codificarlos aquí, speaker_tools
esa única ranura speaker_tools
través de la cual transferiremos la lista de componentes desde el exterior.
Speaker $mol_page head <= speaker_tools /$mol_view body / <= Speaker_content
Estructura de aplicación
Ahora suba un nivel y cree un componente de aplicación $hyoo_slides
que use el componente de página.
$hyoo_slides $mol_view Page!index $hyoo_slides_page - ... plugins / <= Nav <= Touch <= Speech_next - ...
Cualquier componente $mol_view
tiene una propiedad de plugins
través de la cual se puede conectar lógica adicional. Los complementos de complementos viven en el mismo nodo DOM que el componente en sí. El componente los inicia durante su representación. Y cuando se deja de procesar, los complementos se destruyen automáticamente.
También anunciamos la propiedad Page
, que para cada índice devuelve una instancia separada del componente $hyoo_slides_page
que desarrollamos anteriormente.
Configuración de página externa
Page!index $hyoo_slides_page role <= role slide?val <=> page_slide!index?val speaker_tools / <= Speech_toggle <= Speech_text <= Open_listener
Pasamos la propiedad de role
al subcomponente tal como está. La propiedad de slide
del componente de página está conectada por comunicación bidireccional con la propiedad page_slide
de la aplicación. Tenga en cuenta que page_slide
acepta no solo el nuevo valor opcional, sino también el índice de la página. Esto le permite devolver un número para cada página. Finalmente, en la ranura speaker_tools
que anunciamos anteriormente, colocamos tres componentes para ayudar a administrar las diapositivas.
Estructura del interruptor de control por voz
Implementamos Speech_toggle
través del componente estándar $mol_check_icon
, que dibuja un ícono. Cuando hace clic en él, alterna la bandera checked
. Y el estado actual se muestra cambiando el color del icono.
Speech_toggle $mol_check_icon Icon <= Speech_toggle_icon $mol_icon_microphone checked?flag <=> speech_enabled?flag
Tomamos el ícono del $mol_icon
, donde de los 4000 íconos realizados en el estilo de diseño de material ascético, es fácil encontrar el correcto.
Estructura del botón de apertura de la ventana esclava
Todo es simple aquí. Este botón será el enlace $mol_link
. Puede establecer la propiedad uri
con una dirección, o puede hacer algo más astuto y simplemente parchear la dirección actual, reemplazando algunos parámetros a través de arg
.
Listener_open $mol_link target \_blank arg * role \listener slide null sub / <= Listener_open_icon $mol_icon_external
Aquí borramos el número de diapositiva de la dirección para que la ventana esclava lo tome del almacenamiento local, y no de la dirección. Esto asegurará que las ventanas se sincronicen entre sí. También indicaron que el papel debería ser un "oyente". Dentro del enlace, ponemos un icono en lugar de texto.
Complementos
Los complementos pueden expandir significativamente las capacidades del componente. Los utilizaremos al máximo.
plugins / <= Nav <= Touch <= Speech_next <= Speech_prev <= Speech_start <= Speech_end - ...
Todos los complementos utilizados por nosotros se pueden dividir en 3 categorías: navegación por teclado, control por gestos y control por voz.
Teclado de navegación
A través de $mol_nav
es fácil implementar la navegación por teclado tanto vertical como horizontalmente. Todo lo que se necesita es proporcionar al complemento una lista de teclas por las cuales cambiará y una comunicación bidireccional al valor actual.
Nav $mol_nav keys_y <= slide_keys keys_x <= slide_keys current_y?val <=> slide?val current_x?val <=> slide?val
slide_keys: [ 0 , 1 , 2 , 3 , ... , 30 ] ^ slide
Gestos con los dedos
Para el seguimiento de dedos, hay un $mol_touch
. Con él, puede hacer zoom, desplazarse y deslizar. Es la última oportunidad que nos interesa ahora.
Touch $mol_touch swipe_to_left?event <=> go_next?event swipe_to_right?event <=> go_prev?event
go_next( event? : Event ) { this.slide( this.slide() + 1 ) }
Hay dos tipos de deslizamiento. Por ejemplo, deslice hacia la izquierda o hacia la derecha desde cualquier parte de la pantalla y deslice hacia el centro debido al borde derecho o izquierdo de la pantalla. En el código presentado, colgamos nuestros controladores en el primer tipo de deslizamiento.
Control por voz
Para el control por voz, use el $mol_speech
. Es necesario crear una instancia del complemento para cada versión de la acción.
Sing $mol_speech event_catch?val <=> sing?val patterns / \sing( \S+?)* \( \S+?)*
El complemento acepta un controlador de acciones y un conjunto de patrones, al detectar cuáles se activará un evento. Puede usar paréntesis de captura en los patrones para obtener las palabras correspondientes a su contenido en el controlador.
Interruptor deslizante automático
Por defecto, $mol_speech
requiere un manejo amable. Por ejemplo, debe decir no "cantar", sino "cantar, por favor". Puede anular la propiedad de suffix
para cambiar o eliminar esta palabra de código por completo.
Speech_next_auto $mol_speech event_catch?val <=> go_next?val suffix \ patterns <= speech_next_auto_patterns
Por ejemplo, para implementar el cambio automático de diapositivas, no necesitamos palabras mágicas. Pero generaremos un conjunto de patrones dinámicamente, basados en el análisis del contenido del texto del hablante.
Lanzamiento de la aplicación
Al tener un componente de aplicación, puede instanciarlo manualmente como cualquier clase ordinaria. Pero usaremos el lanzamiento automático a través del atributo especial mol_view_root
.
<body mol_view_root="$hyoo_slides"> <script src="web.js" charset="utf-8"></script> </body>
El nombre del atributo es el nombre del componente. Renderizar de esta manera, por supuesto, puede ser absolutamente cualquier componente.
Fuera de línea
Para agregar soporte fuera de línea, solo incluya el módulo mol/offline/install
en el paquete.
include \/mol/offline/install
Levanta automáticamente un ServiceWorker, que almacena en caché todas las solicitudes. Y si la red no está disponible, devuelve datos del caché. Esta no es la mejor implementación, pero para casos simples en los que no desea molestarse, lo hará.
Modo de impresión
Dije anteriormente que durante la impresión debe renderizar todas las páginas, pero no es necesario monitorear manualmente onbeforeprint
y después de onafterprint
, porque tenemos una programación reactiva a toda altura, por lo que usaremos el estado reactivo $mol_print
, que nos da una bandera reactiva a la que podemos Ate la representación.
sub() { if( !this.$.$mol_print.active() ) { return [ this.Page( this.slide() ) ] } return $mol_range2( index => this.Page( index ) , ()=> this.slide_keys().length , ) }
Aquí devolvemos solo una página si el indicador active
no está active
. De lo contrario, devolvemos una matriz perezosa que calcula su longitud y elementos de acuerdo con las fórmulas dadas.
Epílogo
Como resultado, obtuvimos una aplicación web moderna con un montón de funcionalidades y un peso de solo 35kb. Agregue manifiesto y habrá una aplicación web progresiva completa. Por supuesto, muchos detalles no fueron considerados. Puedes verlos en el código en el github. Para todas las preguntas, escriba telegramas en el chat.
Estas diapositivas están en la aplicación: slides.hyoo.ru
Fuentes de aplicación: hyoo-ru / slides.hyoo.ru
Ejemplos de presentación: nin-jin / diapositivas
Telegram chat: @mam_mol
Me alegrará si intentas hacer tu presentación con $hyoo_slides
. Y estaré muy feliz si me ayudas a hacerlo aún mejor de lo que es ahora. Gracias por su atencion!