JavaScript
React
babel
Electron

ElectronでSplatoon2のルール・エリア通知desktopアプリを作成する

Splatoon2開幕

いよいよ待ちに待ったSplatoon2が開幕しました!皆さん楽しんでますか?
今回からルール・エリアの変更が2時間ごとになり,苦手なルール・エリアに当たってしまっても少し待てば好みのものが回ってくる可能性が高くなりました(もちろん逆も言えますが).
事前にルール・エリアの変更予定がわかっていれば,遊び始めるタイミングをそこに合わせる等々できて嬉しいなと思い,今回はルール・エリア通知desktopアプリをElectronで作ってみることにしましたtwitterにもbotがありますが気にしない

こんな感じの通知アプリを作りました.

image.png

なお,本記事,公開しているコードは非公式であり,任天堂株式会社とは一切関係ありません.

Electron

Electronとは,Atomエディタを開発するために生まれたCross Platform Desktop Application Engineです.
Node.js + HTML + CSSでアプリケーションを作成でき,同じコードでWindows,Linux,OS X用のアプリケーションを生成することができます.Electronを使ったアプリケーションの作り方は,すでに様々なサイトで紹介されていますのでそちらを参考にしてください.
今回は,デスクトップのメニューバーに表示するElectron製アプリをReactを使って作ってみます.

Babel + Electron + Menubar + React + Browserify + SASS

今回はメニューバーに表示するアプリを作りたいので,Electronのmenubarプラグインを使用します.
そして,コンテンツの設計はReactで行い,jsxやsassが変更された時は自動でリコンパイルが走って変更結果がリアルタイムに反映されるようにしてほしい... というわがままにドンピシャで対応してくれるコードが...なんとこちらにあります.

https://github.com/itsnauman/electron-menubar-boilerplate

今回はこちらのコードをありがたく使わせていただくことにします.
本コードでは,

npm install -g gulp-cli electron-prebuilt
git clone --depth=1 --branch=master https://github.com/itsnauman/electron-menubar-boilerplate.git (project-name)
cd (project-name)
rm -rf .git
npm install

して

gulp serve

を起動しておくだけで,jsx,sassのリコンパイルからelectronアプリへの反映までを自動で行ってくれます.
client(コンテンツ)側(jsx, sass)のコードはapp以下,main(システム)側のコードはsrc以下に置き,更新がかかるとコンパイル後のコードがbuild以下に置かれるような設定になっています.

プロジェクト構成は以下のような感じ

project-name
  |- package.json
  |- gulpfile.js
  |- app
      |- index.html
      |- index.js
      |- index.scss
  |- src
      |- index.js
  |- node-modules
  |- build

なお,今回はapp以下の構成をjsxとscssで階層分けしたかったので,gulpfileを若干書き換えてあります.

(余談ですが,「boilerplate(ボイラープレート)」とは,もともとは活版印刷に使われた鋼板でできた鋳型のことを指し,そこから転じてIT分野では雛形プロジェクトのことを指します.なので今回のケース以外でも,boilerplate + 使いたい機能で検索すると,github等にあげられている非常にありがたいテンプレートプロジェクトが見つかることがあります.)

イカルール・エリア通知desktopアプリ

今回作ったアプリのコードはこちらになります(アイコンやフォントは含んでいません).masterはsplatoon用,feature/spla2ブランチはsplatoon2用になります.

ルール・エリアの変更予定情報の取得

Splatoon2用エリア,ルール情報は,https://splatoon2.ink/(非公式)のものを使用しています. apiとしてはhttps://splatoon2.ink/data/schedules.jsonとして使用可能です.詳しい情報はコードを参照してください.

メニューバーへのアプリ設置

index.js
// main側
const menubar = require('menubar')
const {app} = require('electron')

var mb = menubar({index: path.join('file://', __dirname, '/index.html'), width:300, height:200, preloadWindow:true})

mb.on('ready', function ready() {
  console.log('app is ready')
})

menubarプラグインを導入しておけば,electronでmain側で設定する必要があるのはこれだけで済みます.

index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Splarm</title>
    <meta charset="UTF-8"> 
    <link rel="stylesheet" href="css/index.css" />
  </head>
  <body  bgcolor="#e5e5e5">
    <div id="container"></div>
    <script src="js/index.js"></script>
    <!-- build:remove -->
    <!-- Connect to server process -->
    <script>require('electron-connect').client.create()</script>
    <!-- end:build -->
  </body>
</html>

require('electron-connect').client.create()はgulp側で立てたserverへ接続するために記述しています.あとはcontainer idのdivにreactでガンガンコンテンツを生成していくだけです.

index.htmlが呼び出している,client側のindex.jsは例えばこんな感じ

index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Container from './components/Container'


ReactDOM.render(
  <Container />,
  document.getElementById('container')
)

main側とclient側の連携

clientでpostした情報をmainに持って来たり,mainからclientに返すためにはipcMain, ipcRendererを使います. 

main.js
// main側
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg)  // prints "ping"
  event.sender.send('asynchronous-reply', 'pong')
})

ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg)  // prints "ping"
  event.returnValue = 'pong'
})
client.js
// client(web page)側
const {ipcRenderer} = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"

ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')

ipcRenderer.onで非同期通信のreturn待ち,ipcRenderer.sendで非同期送信です.簡単ですね.

デスクトップ通知

デスクトップ通知もElectronなら簡単にできます.

let n = new Notification("title", {body: "content", timeout: 2000});

で,以下のような通知を出すことができます.

image.png

アイコン変更

メニューバーのアイコンを変更するためにはルートディレクトリにIconTemplate.pngをおいてください.menubarプラグインのデフォルトアイコンは猫マークですが,pngを設置することで変更できます.今回は24x24の画像を作成し,使用しました.

image.png

また,アプリアイコンや,デスクトップ通知時に表示されるアイコンを変更したい場合は,アプリとしてパッケージングする際に,


electron-packager . Splarm --platform=darwin --arch=x64 --icon=./path/to/icon

のようにパスを指定してあげればOKです(上はOSXの例)

おまけ(フォントの修正)

最後にアプリの雰囲気を出すためにフォントを変えてみましょう.

Splatoonのフォントに近いものとして,

があげられていたのでそちらを使うこととします(イカモドキは公開当時ダウンロードしていたものを使用しました).

それぞれのttfファイルをリソースパスに配置し,

@font-face {
    font-family: 'フォント名';
    src: url('フォントファイルのurl');
}

のように読み込んであげれば,以降font-familyに指定してあげることでフォントを読み込めるようになります.

最終的に以下のような様相になりました.

image.png

おわりに

アプリを起動しておけば,自分の狙ったタイミングで遊べるようになります.
興味のある方はgitから落として使ってみてください.
ただ,手元の環境上OSX版しか挙動は確認できていませんのであしからず.

それではみなさん良いイカライフを!!