| Resumo | Plugin do Discourse que permite personalizar a tela de abertura (splash screen) usando HTML e CSS definidos pelo administrador. | |
| Link do Repositório | https://github.com/VaperinaDEV/custom-splash-html-builder | |
| Achou útil? | > ./support --coffee | |
| Guia de Instalação | Como instalar plugins no Discourse |
Olá ![]()
Criei um pequeno plugin para o Discourse que permite personalizar a tela de abertura usando HTML e CSS definidos pelo administrador, sem a necessidade de manter uma cópia modificada do template de splash do núcleo do Discourse.
A motivação original para a criação deste plugin foi, na verdade, o desempenho em dispositivos móveis.
Eu queria criar uma tela de abertura animada mais sofisticada, mas percebi que as animações SVG suportadas pela implementação atual do splash do núcleo do Discourse podiam se tornar surpreendentemente problemáticas em dispositivos móveis.
No desktop, a animação podia parecer perfeitamente suave, enquanto no mobile ela podia ficar visivelmente travada, com quedas de quadros, lentidão ou até parecer parar durante a animação.
Depois de experimentar diferentes abordagens, descobri que mover a animação do próprio SVG para um elemento HTML circundante, como um <div>, fez uma diferença muito significativa.
Em vez de animar continuamente o conteúdo do SVG, o SVG pode permanecer estático enquanto o navegador anima a camada HTML contêiner usando transforms CSS.
Isso dá ao navegador uma oportunidade muito melhor de tratar a animação como uma operação de composição usando a hardware gráfica do dispositivo.
O resultado foi uma animação muito mais suave no mobile, sem os travamentos e congelamentos que eu estava vendo com a abordagem baseada em SVG.
Essa foi a principal razão pela qual este plugin foi criado.
Antes (SVG Animado: A animação com atrasos e paradas)
Depois (HTML Animado: Animação suave)
O problema de animar SVGs
A implementação original do splash é perfeitamente adequada para um logotipo simples ou uma animação relativamente leve.
No entanto, assim que a animação se torna mais complexa, a renderização de SVG pode se tornar cara.
Por exemplo, uma animação aplicada diretamente a um SVG ou aos seus elementos internos pode exigir que o navegador processe ou repinte repetidamente partes do SVG durante a animação.
Em dispositivos móveis, isso pode se tornar particularmente perceptível.
Durante os testes, vi casos em que a animação:
- ficava visivelmente irregular
- congelava temporariamente
- parecia parar
- se comportava significativamente pior do que no desktop
A parte interessante era que a mesma animação visual podia se comportar de forma muito diferente dependendo do que estava sendo animado.
Movendo a animação para uma camada HTML
A abordagem que funcionou muito melhor foi manter o próprio SVG estático e colocá-lo dentro de um elemento HTML normal.
Por exemplo:
<div class="logo-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
Em vez de animar o SVG, a animação é aplicada ao contêiner:
#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);
}
}
O próprio SVG não muda.
Portanto, o navegador pode lidar com a transformação da camada HTML de forma muito mais eficiente e, nos casos suportados, promovê-la para uma camada composta tratada pela hardware gráfica.
Isso produziu um resultado muito mais suave em dispositivos móveis.
A distinção importante é, portanto:
Abordagem do núcleo:
SVG
└── animação SVG
└── conteúdo do SVG é animado
vs:
Abordagem personalizada:
Camada HTML
└── SVG
└── transform CSS na camada HTML
└── animação amigável ao compositor
Isso não é uma garantia de que toda animação será acelerada por GPU. O navegador, em última análise, decide como uma animação é composta, mas em meus testes a diferença foi muito perceptível.
Por que criei o Custom Splash HTML Builder
Depois que esta abordagem começou a funcionar, eu também precisava de uma maneira de realmente construir a tela de abertura em torno dela.
O template padrão de splash não oferece flexibilidade suficiente para este tipo de implementação.
Para uma animação mais complexa, eu poderia precisar de:
- múltiplas camadas SVG
- múltiplos contêineres HTML
- elementos animados independentemente
- keyframes CSS personalizados
- diferentes tempos de animação
- posicionamento personalizado
- markup completamente diferente do splash padrão
Então, em vez de criar outra implementação de splash com código fixo (hard-coded), decidi expor a parte visual por meio de duas configurações do site.
O plugin adiciona:
splash_custom_html
O markup HTML/SVG renderizado dentro da tela de abertura.
splash_custom_css
O CSS usado pelo splash personalizado, incluindo animações, keyframes, posicionamento e comportamento responsivo.
Isso torna o splash efetivamente personalizável sem precisar modificar o código-fonte do plugin toda vez que a animação muda.
Editor de administrador embutido
O plugin também fornece um pequeno editor de administrador embutido para gerenciar o splash personalizado.
Ele adiciona uma seção dedicada Splash HTML Builder na interface administrativa do Discourse, com editores separados para:
- HTML Personalizado
- CSS Personalizado
As alterações podem ser salvas diretamente da interface administrativa sem editar manualmente as configurações do site correspondentes.
As configurações subjacentes ainda são:
splash_custom_htmlsplash_custom_css
O editor é simplesmente uma interface mais conveniente para gerenciá-las.
Isso também significa que o plugin não requer a modificação de arquivos de fonte do plugin sempre que a animação do splash precisar ser alterada.
Exemplo
Um splash personalizado pode conter múltiplas camadas independentes:
<div class="ring-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
<div class="logo-layer">
<svg viewBox="0 0 500 500">
...
</svg>
</div>
E cada camada pode ter sua própria animação:
#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);
}
}
Os SVGs permanecem estáticos enquanto as camadas HTML circundantes são animadas.
Isso permite criar animações de splash consideravelmente mais complexas, mantendo o trabalho de animação caro fora do próprio SVG.
Por que não simplesmente sobrescrever o template de splash do núcleo?
Outro objetivo importante foi evitar manter uma cópia do template de splash do núcleo do Discourse.
Uma abordagem direta seria sobrescrever:
app/views/common/_discourse_splash.html.erb
e copiar a implementação atual do Discourse para o plugin.
O problema é que isso cria uma carga de manutenção.
Se o Discourse alterar sua implementação de splash em uma versão futura, o plugin ainda contaria a versão antiga.
Isso poderia potencialmente resultar em:
- falta de novas mudanças no núcleo
- falta de melhorias de desempenho
- comportamento quebrado após uma atualização do Discourse
- necessidade de comparar manualmente o template do plugin com o núcleo após cada atualização
Eu queria evitar isso por completo.
Fallback para o núcleo
Portanto, o plugin suporta um splash personalizado com fallback para o núcleo.
HTML personalizado está configurado
Se:
SiteSetting.splash_custom_html.present?
então o plugin renderiza o splash personalizado.
HTML personalizado está vazio
Se nenhum splash personalizado tiver sido configurado, o plugin faz fallback para o template de splash do núcleo do Discourse atual.
O plugin localiza o arquivo real do núcleo a partir da instalação do Discourse em execução:
Rails.root/app/views/common/_discourse_splash.html.erb
e renderiza essa implementação.
Conceitualmente:
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
Isso significa que o plugin não carrega uma segunda cópia do template de splash do núcleo.
Considerações de desempenho
O plugin não está tentando afirmar que toda animação CSS se tornará magicamente acelerada por GPU.
O navegador ainda decide como as animações individuais são renderizadas e compostas.
O objetivo é, em vez disso, dar ao navegador uma estrutura muito mais favorável para composição acelerada por hardware:
- manter o conteúdo SVG estático
- isolar elementos animados independentemente
- animar camadas HTML
- preferir
transformpara movimento/escala/rotação - evitar operações de repintura desnecessariamente caras
- usar
will-changeonde apropriado
Por exemplo:
#d-splash .ring-layer {
will-change: transform;
animation: rotate 2.2s linear infinite;
}
Esta abordagem funcionou particularmente bem para meu caso de uso e eliminou os travamentos no mobile que eu estava vendo com a animação SVG original.
Ativar ou desativar o splash personalizado
O plugin também fornece uma configuração do site custom_splash_html_builder_enabled.
Quando desativado, a tela de splash padrão do Discourse é usada, independentemente de HTML ou CSS personalizados terem sido configurados.
Isso fornece um interruptor de segurança adicional para desativar temporariamente o splash personalizado sem excluir o HTML/CSS salvo.
O splash personalizado só é renderizado quando ambos:
custom_splash_html_builder_enabled = true
splash_custom_html não está vazio
Caso contrário, o splash do núcleo do Discourse atual é usado.
O mais importante é que ele fornece uma maneira de construir um splash animado personalizado que tem muito melhor desempenho no mobile, animando camadas HTML ao redor de conteúdo SVG estático, em vez de animar diretamente o próprio SVG.