| Resumen | Plugin de Discourse que permite personalizar la pantalla de inicio (splash screen) utilizando HTML y CSS definidos por el administrador. | |
| Enlace al repositorio | https://github.com/VaperinaDEV/custom-splash-html-builder | |
| ¿Te resultó útil? | > ./support --coffee | |
| Guía de instalación | Cómo instalar plugins en Discourse |
Hola ![]()
He creado un pequeño plugin de Discourse que permite personalizar la pantalla de inicio (splash screen) utilizando HTML y CSS definidos por el administrador, sin necesidad de mantener una copia modificada de la plantilla principal de la pantalla de inicio de Discourse.
La motivación original para crear este plugin fue, en realidad, el rendimiento en dispositivos móviles.
Quería crear una pantalla de inicio animada más sofisticada, pero descubrí que las animaciones SVG admitidas por la implementación actual de la pantalla de inicio principal de Discourse podían volverse sorprendentemente problemáticas en dispositivos móviles.
En escritorio, la animación podía verse perfectamente fluida, mientras que en móvil podía volverse visiblemente entrecortada, perder fotogramas, tener retrasos o incluso parecer que se detenía durante la animación.
Después de experimentar con diferentes enfoques, descubrí que mover la animación desde el propio SVG a un elemento HTML circundante, como un <div>, hacía una diferencia muy significativa.
En lugar de animar continuamente el contenido del SVG, el SVG puede permanecer estático mientras el navegador anima la capa HTML contenedora usando transformaciones CSS.
Esto le da al navegador una oportunidad mucho mejor de manejar la animación como una operación de composición utilizando la hardware gráfica del dispositivo.
El resultado fue una animación mucho más fluida en móvil, sin los tirones y congelamientos que estaba viendo con el enfoque basado en SVG.
Esa fue la razón principal por la que se creó este plugin.
Antes (SVG animado: La animación se retrasa y se detiene)
Después (HTML animado: Animación fluida)
El problema con la animación de SVG
La implementación original de la pantalla de inicio es perfectamente adecuada para un logotipo simple o una animación relativamente ligera.
Sin embargo, una vez que la animación se vuelve más compleja, el renderizado de SVG puede volverse costoso.
Por ejemplo, una animación aplicada directamente a un SVG o a sus elementos internos puede requerir que el navegador procese o repinte repetidamente partes del SVG durante la animación.
En dispositivos móviles, esto puede ser particularmente notable.
Durante las pruebas, vi casos en los que la animación:
- se volvía visiblemente entrecortada
- se congelaba temporalmente
- parecía detenerse
- se comportaba significativamente peor que en escritorio
Lo interesante era que la misma animación visual podía comportarse de manera muy diferente dependiendo de qué se estaba animando realmente.
Mover la animación a una capa HTML
El enfoque que funcionó mucho mejor fue mantener el propio SVG estático y colocarlo dentro de un elemento HTML normal.
Por ejemplo:
<div class="logo-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
En lugar de animar el SVG, la animación se aplica al contenedor:
#d-splash .logo-layer {
animation: pulse 1.8s ease-in-out infinite;
will-change: transform;
}
@keyframes pulse {
0%,
100% {
transform: scale(0.8);
}
50% {
transform: scale(0.85);
}
}
El propio SVG no cambia.
Por lo tanto, el navegador puede manejar la transformación de la capa HTML de manera mucho más eficiente y, en los casos compatibles, promoverla a una capa compuesta manejada por la hardware gráfica.
Esto produjo un resultado dramáticamente más fluido en los dispositivos móviles.
La distinción importante es, por lo tanto:
Enfoque principal (Core):
SVG
└── Animación SVG
└── El contenido del SVG se anima
vs:
Enfoque personalizado:
Capa HTML
└── SVG
└── Transformación CSS en la capa HTML
└── Animación apta para el compositor
Esto no es una garantía de que cada animación será acelerada por la GPU. El navegador decide en última instancia cómo se compone una animación, pero en mis pruebas la diferencia fue muy notable.
Por qué creé el Custom Splash HTML Builder
Una vez que este enfoque funcionó, también necesitaba una forma de construir realmente la pantalla de inicio en torno a él.
La plantilla de pantalla de inicio estándar no ofrece suficiente flexibilidad para este tipo de implementación.
Para una animación más compleja, podría necesitar:
- múltiples capas SVG
- múltiples contenedores HTML
- elementos animados de forma independiente
- keyframes CSS personalizados
- tiempos de animación diferentes
- posicionamiento personalizado
- una marca (markup) completamente diferente a la de la pantalla de inicio predeterminada
Por lo tanto, en lugar de crear otra implementación de pantalla de inicio codificada de forma rígida, decidí exponer la parte visual a través de dos configuraciones del sitio.
El plugin agrega:
splash_custom_html
La marca HTML/SVG que se renderiza dentro de la pantalla de inicio.
splash_custom_css
El CSS utilizado por la pantalla de inicio personalizada, incluyendo animaciones, keyframes, posicionamiento y comportamiento responsivo.
Esto hace que la pantalla de inicio sea efectivamente personalizable sin tener que modificar el código fuente del plugin cada vez que cambia la animación.
Editor de administración integrado
El plugin también proporciona un pequeño editor de administración integrado para gestionar la pantalla de inicio personalizada.
Agrega una sección dedicada Splash HTML Builder en la interfaz de administración de Discourse, con editores separados para:
- HTML personalizado
- CSS personalizado
Los cambios se pueden guardar directamente desde la interfaz de administración sin editar manualmente las configuraciones del sitio correspondientes.
Las configuraciones subyacentes siguen siendo:
splash_custom_htmlsplash_custom_css
El editor es simplemente una interfaz más conveniente para gestionarlas.
Esto también significa que el plugin no requiere modificar los archivos fuente del plugin cada vez que se necesita cambiar la animación de la pantalla de inicio.
Ejemplo
Una pantalla de inicio personalizada puede contener múltiples capas independientes:
<div class="ring-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
<div class="logo-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
Y cada capa puede tener su propia animación:
#d-splash .ring-layer {
animation: rotate 2.2s linear infinite;
will-change: transform;
}
#d-splash .logo-layer {
animation: pulse 1.8s ease-in-out infinite;
will-change: transform;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes pulse {
0%,
100% {
transform: scale(0.8);
}
50% {
transform: scale(0.85);
}
}
Los SVG permanecen estáticos mientras las capas HTML circundantes se animan.
Esto permite crear animaciones de pantalla de inicio considerablemente más complejas manteniendo el trabajo de animación costoso fuera del propio SVG.
¿Por qué no simplemente sobrescribir la plantilla principal de la pantalla de inicio?
Otro objetivo importante fue evitar mantener una copia de la plantilla principal de la pantalla de inicio de Discourse.
Un enfoque directo sería sobrescribir:
app/views/common/_discourse_splash.html.erb
y copiar la implementación actual de Discourse en el plugin.
El problema es que esto crea una carga de mantenimiento.
Si Discourse cambia su implementación de la pantalla de inicio en una versión futura, el plugin aún contendría la versión antigua.
Eso podría resultar potencialmente en:
- falta de nuevos cambios principales
- falta de mejoras de rendimiento
- comportamiento roto después de una actualización de Discourse
- tener que comparar manualmente la plantilla del plugin con la principal después de cada actualización
Quería evitar eso por completo.
Fallback principal (Core fallback)
Por lo tanto, el plugin admite una pantalla de inicio personalizada con un fallback principal.
Se configura HTML personalizado
Si:
SiteSetting.splash_custom_html.present?
entonces el plugin renderiza la pantalla de inicio personalizada.
El HTML personalizado está vacío
Si no se ha configurado una pantalla de inicio personalizada, el plugin vuelve a la plantilla principal actual de la pantalla de inicio de Discourse.
El plugin localiza el archivo principal real desde la instalación de Discourse en ejecución:
Rails.root/app/views/common/_discourse_splash.html.erb
y renderiza esa implementación.
Conceptualmente:
core_splash_path = Rails.root.join("app", "views", "common", "_discourse_splash.html.erb")
if File.exist?(core_splash_path)
render inline: File.read(core_splash_path), type: :erb
end
Esto significa que el plugin no lleva una segunda copia de la plantilla principal de la pantalla de inicio.
Consideraciones de rendimiento
El plugin no intenta afirmar que cada animación CSS se volverá mágicamente acelerada por la GPU.
El navegador aún decide cómo se renderizan y componen las animaciones individuales.
El objetivo es, en cambio, darle al navegador una estructura mucho más favorable para la composición acelerada por hardware:
- mantener el contenido SVG estático
- aislar elementos animados de forma independiente
- animar capas HTML
- preferir
transformpara movimiento/escala/rotación - evitar operaciones de repintado innecesariamente costosas
- usar
will-changedonde sea apropiado
Por ejemplo:
#d-splash .ring-layer {
will-change: transform;
animation: rotate 2.2s linear infinite;
}
Este enfoque funcionó particularmente bien para mi caso de uso y eliminó los tirones en móvil que estaba viendo con la animación SVG original.
Habilitar o deshabilitar la pantalla de inicio personalizada
El plugin también proporciona una configuración del sitio custom_splash_html_builder_enabled.
Cuando está deshabilitado, se utiliza la pantalla de inicio estándar de Discourse sin importar si se ha configurado HTML o CSS personalizado.
Esto proporciona un interruptor de seguridad adicional para deshabilitar temporalmente la pantalla de inicio personalizada sin eliminar el HTML/CSS guardado.
La pantalla de inicio personalizada solo se renderiza cuando:
custom_splash_html_builder_enabled = true
splash_custom_html no está vacío
De lo contrario, se utiliza la pantalla de inicio principal actual de Discourse.
Lo más importante es que proporciona una forma de construir una pantalla de inicio animada personalizada que rinde mucho mejor en móvil animando capas HTML alrededor de contenido SVG estático en lugar de animar directamente el propio SVG.