| Resumen | Plugin de Discourse que permite personalizar la pantalla de bienvenida (splash screen) utilizando HTML y CSS definidos por el administrador. | |
| Enlace al repositorio | https://github.com/VaperinaDEV/custom-splash-html-builder | |
| 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 bienvenida utilizando HTML y CSS definidos por el administrador, sin necesidad de mantener una copia modificada de la plantilla principal de la pantalla de bienvenida de Discourse.
La motivación original para crear este plugin fue en realidad el rendimiento en móviles.
Quería crear una pantalla de bienvenida animada más sofisticada, pero descubrí que las animaciones SVG soportadas por la implementación actual de la pantalla de bienvenida principal de Discourse podían convertirse en un problema sorprendente en dispositivos móviles.
En escritorio, la animación podía verse perfectamente fluida, mientras que en móviles podía volverse notablemente entrecortada, perder cuadros, 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 para manejar la animación como una operación de composición utilizando el hardware gráfico del dispositivo.
El resultado fue una animación mucho más fluida en móviles, 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 con retrasos y detenida)
Después (HTML animado: Animación fluida)
El problema con animar SVGs
La implementación original de la pantalla de bienvenida 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 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 donde la animación:
- se volvía visiblemente entrecortada
- se congelaba temporalmente
- parecía detenerse
- se comportaba significativamente peor que en escritorio
La parte interesante fue que la misma animación visual podía comportarse 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:
.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 casos compatibles, promoverla a una capa compuesta manejada por el hardware gráfico.
Esto produjo un resultado dramáticamente más fluido en dispositivos móviles.
La distinción importante es, por lo tanto:
Enfoque principal:
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 amigable para el compositor
Esto no garantiza que cada animación sea acelerada por la GPU. El navegador decide finalmente cómo se compone una animación, pero en mis pruebas la diferencia fue muy notable.
Por qué creé el Generador de HTML Personalizado para la Pantalla de Bienvenida
Una vez que tuve este enfoque funcionando, también necesitaba una forma de construir realmente la pantalla de bienvenida en torno a él.
La plantilla de pantalla de bienvenida estándar no proporciona 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
- colores conscientes del tema
- marcado completamente diferente al de la pantalla de bienvenida predeterminada
Así que, en lugar de crear otra implementación de pantalla de bienvenida codificada, decidí exponer la parte visual a través de dos configuraciones del sitio.
El plugin añade:
splash_custom_html
El marcado HTML/SVG renderizado dentro de la pantalla de bienvenida.
splash_custom_css
El CSS utilizado por la pantalla de bienvenida personalizada, incluyendo animaciones, keyframes, posicionamiento y comportamiento responsivo.
Esto hace que la pantalla de bienvenida sea efectivamente personalizable sin tener que modificar el código fuente del plugin cada vez que cambia la animación.
Editor de administrador integrado
El plugin también proporciona un pequeño editor de administrador integrado para gestionar la pantalla de bienvenida personalizada.
Añade una sección dedicada de Generador de HTML de Pantalla de Bienvenida en la interfaz de administrador de Discourse, con editores separados para:
- HTML personalizado
- CSS personalizadon
Los cambios se pueden guardar directamente desde la interfaz de administrador 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 gestionarlos.
Esto también significa que el plugin no requiere modificar archivos de código fuente del plugin cada vez que se necesita cambiar la animación de la pantalla de bienvenida.
Ejemplo
Una pantalla de bienvenida personalizada puede contener múltiples capas independientes:
<div class="splash-logo-container">
<div class="ring-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
<div class="logo-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
</div>
Y cada capa puede tener su propia animación:
.ring-layer {
animation: rotate 2.2s linear infinite;
will-change: transform;
}
.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 hace posible crear animaciones de pantalla de bienvenida considerablemente más complejas manteniendo el trabajo de animación costoso fuera del propio SVG.
¿Por qué no simplemente anular la plantilla principal de la pantalla de bienvenida?
Otro objetivo importante fue evitar mantener una copia de la plantilla principal de la pantalla de bienvenida de Discourse.
Un enfoque directo sería anular:
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 bienvenida en una versión futura, el plugin seguiría conteniendo la versión antigua.
Eso podría resultar potencialmente en:
- perder nuevos cambios principales
- perder 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.
Retroceso a la versión principal
Por lo tanto, el plugin soporta una pantalla de bienvenida personalizada con un retroceso a la versión principal.
Se configura HTML personalizado
Si:
SiteSetting.splash_custom_html.present?
entonces el plugin renderiza la pantalla de bienvenida personalizada.
El HTML personalizado está vacío
Si no se ha configurado ninguna pantalla de bienvenida personalizada, el plugin retrocede a la plantilla principal de la pantalla de bienvenida actual 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 bienvenida.
Consideraciones de rendimiento
El plugin no intenta afirmar que cada animación CSS se convertirá mágicamente en acelerada por GPU.
El navegador sigue decidiendo 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/escalado/rotación - evitar operaciones de repintado innecesariamente costosas
- usar
will-changedonde sea apropiado
Por ejemplo:
.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óviles que estaba viendo con la animación SVG original.
Habilitar o deshabilitar la pantalla de bienvenida personalizada
El plugin también proporciona una configuración del sitio custom_splash_html_builder_enabled.
Cuando está deshabilitado, se utiliza la pantalla de bienvenida estándar de Discourse independientemente de si se ha configurado HTML o CSS personalizado.
Esto proporciona un interruptor de seguridad adicional para deshabilitar temporalmente la pantalla de bienvenida personalizada sin eliminar el HTML/CSS guardado.
La pantalla de bienvenida 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 bienvenida principal actual de Discourse.
Lo más importante, proporciona una forma de construir una pantalla de bienvenida animada personalizada que tiene un rendimiento mucho mejor en móviles animando capas HTML alrededor de contenido SVG estático en lugar de animar directamente el propio SVG.