Splash Screen
Una splash screen è una finestra di caricamento che appare mentre l’applicazione si inizializza, dando feedback visivo all’utente durante l’avvio.
Implementazione Base
Il pattern è semplice: mostra una finestra splash, carica la finestra principale in background, poi chiudi la splash.
// main.js
const { app, BrowserWindow } = require('electron');
const path = require('node:path');
let splashWindow;
let mainWindow;
function createSplashWindow() {
splashWindow = new BrowserWindow({
width: 400,
height: 300,
frame: false, // Nessun bordo
transparent: true, // Sfondo trasparente
alwaysOnTop: true, // Sopra le altre finestre
resizable: false,
skipTaskbar: true, // Non mostrare nella taskbar
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
splashWindow.loadFile('splash.html');
splashWindow.center();
}
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false, // Non mostrare subito
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
mainWindow.loadFile('index.html');
// Quando la finestra principale è pronta, chiudi la splash
mainWindow.once('ready-to-show', () => {
// Piccolo delay per una transizione più fluida
setTimeout(() => {
splashWindow.close();
splashWindow = null;
mainWindow.show();
mainWindow.focus();
}, 500);
});
}
app.whenReady().then(() => {
createSplashWindow();
createMainWindow();
});
HTML della Splash Screen
<!-- splash.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; style-src 'self' 'unsafe-inline'">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: transparent;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.splash {
background: linear-gradient(135deg, #1e1e2e 0%, #313244 100%);
border-radius: 20px;
padding: 3rem;
text-align: center;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
width: 380px;
height: 280px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.logo {
width: 80px;
height: 80px;
margin-bottom: 1.5rem;
}
.app-name {
color: #89b4fa;
font-size: 1.8rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.version {
color: #6c7086;
font-size: 0.85rem;
margin-bottom: 1.5rem;
}
.loader {
width: 200px;
height: 3px;
background: #313244;
border-radius: 3px;
overflow: hidden;
}
.loader-bar {
width: 0%;
height: 100%;
background: linear-gradient(90deg, #89b4fa, #74c7ec);
border-radius: 3px;
animation: loading 2s ease-in-out forwards;
}
@keyframes loading {
0% { width: 0%; }
30% { width: 40%; }
60% { width: 70%; }
100% { width: 100%; }
}
.status {
color: #a6adc8;
font-size: 0.75rem;
margin-top: 0.8rem;
}
</style>
</head>
<body>
<div class="splash">
<img class="logo" src="assets/icon.png" alt="Logo">
<div class="app-name">La Mia App</div>
<div class="version">v1.0.0</div>
<div class="loader">
<div class="loader-bar"></div>
</div>
<div class="status">Caricamento in corso...</div>
</div>
</body>
</html>
Splash con Progresso Reale
Per mostrare il progresso reale del caricamento:
// main.js
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
// Aggiorna la splash con il progresso
updateSplashStatus('Caricamento interfaccia...');
mainWindow.loadFile('index.html');
mainWindow.webContents.on('did-finish-load', () => {
updateSplashStatus('Inizializzazione servizi...');
// Simula inizializzazione
initializeServices().then(() => {
updateSplashStatus('Pronto!');
setTimeout(() => {
splashWindow?.close();
mainWindow.show();
}, 300);
});
});
}
function updateSplashStatus(message) {
if (splashWindow && !splashWindow.isDestroyed()) {
splashWindow.webContents.send('splash:status', message);
}
}
// preload.js (per la splash)
const { ipcRenderer } = require('electron');
ipcRenderer.on('splash:status', (_event, message) => {
const statusEl = document.querySelector('.status');
if (statusEl) statusEl.textContent = message;
});
Splash Screen con Fade Out
Per un effetto di transizione più elegante:
// main.js
mainWindow.once('ready-to-show', () => {
// Fade out della splash
let opacity = 1;
const fadeInterval = setInterval(() => {
opacity -= 0.05;
if (opacity <= 0) {
clearInterval(fadeInterval);
splashWindow?.close();
splashWindow = null;
mainWindow.show();
mainWindow.focus();
} else {
splashWindow?.setOpacity(opacity);
}
}, 16); // ~60fps
});
Timeout di Sicurezza
Aggiungi un timeout nel caso il caricamento impieghi troppo:
const SPLASH_TIMEOUT = 10000; // 10 secondi
const timeout = setTimeout(() => {
// Se la splash è ancora visibile dopo il timeout, mostra comunque la main
if (splashWindow && !splashWindow.isDestroyed()) {
splashWindow.close();
splashWindow = null;
mainWindow.show();
}
}, SPLASH_TIMEOUT);
mainWindow.once('ready-to-show', () => {
clearTimeout(timeout);
// ... logica normale
});
Best Practice
- Mantieni la splash leggera — deve caricarsi istantaneamente
- Non usare risorse pesanti — evita immagini grandi o animazioni complesse
- Aggiungi un timeout — la splash non deve bloccare l’app indefinitamente
- Mostra il progresso — un indicatore visivo rassicura l’utente
- Transizioni fluide — usa fade o animazioni per passare dalla splash all’app