[Electron] アプリ起動時にスプラッシュ画面を表示する

アプリの本体のウィンドウが起動する前に、会社やアプリのロゴが表示される画面を見たことがある方も多いと思います。いわゆる「スプラッシュ」と呼ばれる画面です。今回はこちらの実装を行ってみます。

スプラッシュはブランディングなどが目的の場合もありますが、裏側でこっそり通信を行っている場合もありますね。またはここでファイルをメモリ上にロードする場合もあります。

ソースコード

実際に稼働するソースはGitHubからも確認できます。
github.com

基本的な原理

フレームレスウィンドウ

一般的にスプラッシュ画面ではアプリや会社のロゴやイメージ画像のみを表示することが多いわけですが、Electronでは「フレームレスウィンドウ」を利用するとそれっぽく作成することができます。

Windows10ではタイトルバーやウィンドウの枠、メニューが非表示になります。キーボードショートカットは有効です。

macOSではメニューバーはそのまま表示されますが、Windowsと同様にタイトルバーやウィンドウの枠が非表示になります。

利用方法

通常のウィンドウを作成する際との違いは8行目、引数のframefalseを指定するだけです。後は通常のウィンドウと同じ様に操作できます。

const { app, BrowserWindow } = require('electron')

let splashWin

function createSplash () {
  // スプラッシュを開く
  splashWin = new BrowserWindow({
    frame: false,   // フレームレスにする
    width: 800,
    height: 322,
  })

  // スプラッシュ用のHTMLを表示
  splashWin.loadFile('public/splash.html')
}

app.whenReady().then(()=>{
  // スプラッシュを最初に表示
  createSplash()
})

サンプル

デモ

実際に動作させた動画です。


www.youtube.com

メインプロセス

大きく以下のような処理の流れになります。

  1. Electronの準備が整うとスプラッシュを表示
  2. 2秒後にスプラッシュを非表示
  3. メインウィンドウを表示
  4. スプラッシュを閉じる(見た目の変化はなし)

スプラッシュを閉じてからメインウィンドウを表示すると、WindowsLinuxwindow-all-closedイベントが発生するので、それを回避するために一度非表示にしてから閉じています。

/**
 * スプラッシュ画面を表示してから起動する
 *
 */

//------------------------------------
// モジュール
//------------------------------------
const { app, BrowserWindow } = require('electron')

//------------------------------------
// グローバル変数
//------------------------------------
// ウィンドウ管理用
let mainWin
let splashWin

/**
 * スプラッシュ画面を作成する
 */
function createSplash () {
  // ウィンドウを新たに開く
  splashWin = new BrowserWindow({
    show: false,
    frame: false,   // フレームレスにする
    width: 800,
    height: 322,
  })

  // スプラッシュ用のHTMLを表示
  splashWin.loadFile('public/splash.html')

  // 準備が整ったら表示
  splashWin.once('ready-to-show', () => {
    splashWin.show()
  })
}

/**
 * メインウィンドウを作成する
 */
function createWindow () {
  // ウィンドウを新たに開く
  mainWin = new BrowserWindow({
    show: false,
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  // アプリ本体のHTMLを表示
  mainWin.loadFile('public/index.html')

  // 準備が整ったら表示
  mainWin.once('ready-to-show', () => {
    mainWin.show()
  })
}

//------------------------------------
// [app] イベント処理
//------------------------------------
// 初期化が終了したらウィンドウを新規に作成する
app.whenReady().then(()=>{
  // スプラッシュを最初に表示
  createSplash()

  // 2秒経過したらアプリ画面を表示
  setTimeout(()=>{
    splashWin.hide()       // スプラッシュを非表示
    createWindow()         // アプリを開始
    splashWin.destroy()    // スプラッシュを削除
  }, 2000)
})


// すべてのウィンドウが閉じられたときの処理
app.on('window-all-closed', () => {
  // macOS以外はアプリを終了する
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

// アプリがアクティブになった時の処理
// (macOSはDocのアイコンがクリックされたとき)
app.on('activate', () => {
  // ウィンドウがすべて閉じられている場合は新しく開く
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

レンダラープロセス

今回はスプラッシュもアプリ本体も特別なことはしていない通常のHTMLです。

スプラッシュ

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  <title>Electron Smaple - splash</title>
  <style>
    html, body{
      margin: 0px;
      height: 100%;
    }
    body{
      background-image: url('image/splash.jpeg');
      background-size: cover;
      background-repeat: no-repeat;
    }
    .container {
      border: 2px solid #1b0303;
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .box {
      width: 500px;
      height: 100px;
      font-size: 32pt;
      text-align: center;
      padding-top: 20px;
      background-color: rgba(255,255,255,0.5);
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="box">ねこの足跡R</div>
  </div>
</body>
</html>

アプリ本体

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  <title>Electron Smaple - splash</title>
  <style>
    body{ background-color:white; }
  </style>
</head>
<body>

<h1>ねこの足跡R</h1>
<p>起動しました</p>

</body>
</html>

参考ページ