LoginSignup
5
4

More than 5 years have passed since last update.

Electron - デスクトップにクリスマスツリーを飾りたい

Last updated at Posted at 2016-12-22

この記事は J2complexed Advent Calendar 2016 の15日目の記事です。

深夜まで見てるこの画面と街中にあふれるイルミネーションの落差に絶望してませんか?
でも、ぼくたちにはエンジニアリングがある!
エンジニアの画面がいつも真っ黒だと思ったら、大間違いなんだ!

クリスマスツリーを飾るためだけのアプリをElectronでさくっと作ってしまいましょう!

Electronの準備

Electronは知ってますよね?JavaScriptでクロスプラットフォームのデスクトップアプリを作れるアレです。おなじみのJavaScriptで簡単に作れたりします。ステキです。

Electron

Electronのインストール

以下のコマンドを入力すれば、インストールが完了です。

$ npm -g install electron-prebuilt

制作の説明

これから紹介する順番に作っていけば、みなさんもデスクトップだけはクリスマス気分になれます!

package.json

まず、package.jsonのご紹介です。

package.json
{
  "name": "electron-tree",
  "version": "1.0.0",
  "description": "A Christmas tree on desktop",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "author": "garakuta",
  "license": "ISC",
  "devDependencies": {
    "electron": "^1.4.12"
  },
  "dependencies": {
    "pixi-particles": "^2.0.0"
  }
}

基本的に公式のクイックスタートのpackage.jsonを真似てます。
今回はパーティクルを使おうと思ったので、pixi-particlesを入れてます。

main.js

このjsでelectronを起動します。

main.js
const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow

const path = require('path')
const url = require('url')

let mainWindow

function createWindow () {
  const electronScreen = electron.screen
  const size = electronScreen.getPrimaryDisplay().workAreaSize
  mainWindow = new BrowserWindow({
      width: size.width,
      height: size.height,
      transparent: true,
      frame: false,
      alwaysOnTop: true,
      resizable: false
    })
  mainWindow.setIgnoreMouseEvents(true)

  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'dist/index.html'),
    protocol: 'file:',
    slashes: true
  }))

  mainWindow.on('closed', function () {
    mainWindow = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  if (mainWindow === null) {
    createWindow()
  }
})

やはり基本的に公式のクイックスタートのmain.jsを真似てます。
違う箇所はウィンドウを立ち上げるときのオプションですね。
変更箇所は以下のとおりです。

const electronScreen = electron.screen
const size = electronScreen.getPrimaryDisplay().workAreaSize

ディスプレイのサイズを取得してます。

width: size.width,
height: size.height,

オプションで、ディスプレイのサイズを渡しておきます。これで、ウィンドウが全画面のサイズになります。

transparent: true,
ウィンドウの背景を透明にしています。

frame: false,
ウィンドウの枠を消しています。

alwaysOnTop: true,
常に全面に出るようにしています。

resizable: false
ウィンドウの大きさを変更できないようにしています。

mainWindow.setIgnoreMouseEvents(true)
これでウィンドウを触ることができません。

index.html

electronで描画するhtmlです。

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron Tree</title>
<script src="assets/js/libs/pixi.min.js"></script>
<script src="assets/js/libs/pixi-particles.min.js"></script>

<style type="text/css">
  body {
    margin: 0;
    padding: 0;
  }
</style>

<script>
var stage, renderer, loader, view, snow, twinkle;
var elapsed = Date.now();
var WIDTH = window.innerWidth
var HEIGHT = window.innerHeight

function initialize() {
  stage = new PIXI.Container();
  renderer = PIXI.autoDetectRenderer(WIDTH, HEIGHT, {transparent: true});
  document.body.appendChild(renderer.view);

  loader = new PIXI.loaders.Loader();
  loader.add("snow", "assets/img/snow.png");
  loader.add("twinkle", "assets/img/twinkle.png");
  loader.add("tree", "assets/img/tree.png");
  loader.on("complete", complete);
  loader.load();

  update();
}

function update() {
  if (snow && twinkle) {
    var time = Date.now();
    snow.update((time - elapsed)/1000);
    twinkle.update((time - elapsed)/1000);
    elapsed = time;
  }

  renderer.render(stage);
  requestAnimationFrame(update);
}
function complete() {
  view = new PIXI.Container();
  stage.addChild(view);

  var snowTexture = PIXI.Texture.fromImage("assets/img/snow.png");
  var treeTexture = PIXI.Texture.fromImage("assets/img/tree.png");
  var twinkleTexture = PIXI.Texture.fromImage("assets/img/twinkle.png");

  var snowConfig = {
    alpha: { start: 0.6, end: 0.0 },
    scale: { start: 0.5, end: 0.3 },
    color: { start: "FFFFFF", end: "FFFFFF" },
    speed: { start: 75, end: 75 },
    startRotation: { min: 0, max: 360 },
    rotationSpeed: { min: -90, max: 90 },
    lifetime: { min: 2, max: 20 },
    frequency: 0.008,
    emitterLifetime: 0,
    maxParticles: 100,
    pos: { x: 0, y: 0 },
    addAtBack: false,
    spawnType: "rect",
    spawnRect: { x: 0, y: -20, w: 1960, h: 0 }
  };
  var twinkleConfig = {
    alpha: { start: 0.7, end: 0 },
    scale: { start: 0.2, end: 0.3, minimumScaleMultiplier: 1 },
    color: { start: "#e2ff29", end: "#3ff588" },
    speed: { start: 0, end: 0, minimumSpeedMultiplier: 1 },
    acceleration: { x: 0, y: 5 },
    maxSpeed: 0,
    startRotation: { min: 0, max: 0 },
    noRotation: false,
    rotationSpeed: { min: 0, max: 0 },
    lifetime: { min: 1, max: 3 },
    blendMode: "normal",
    frequency: 0.008,
    emitterLifetime: -1,
    maxParticles: 10,
    pos: { x: WIDTH - 350, y: HEIGHT - 100 },
    addAtBack: false,
    spawnType: "circle",
    spawnCircle: { x: 0, y: 0, r: 75 }
  }
  snow = new PIXI.particles.Emitter(view, snowTexture, snowConfig);
  snow.updateOwnerPos(300, 0);
  twinkle = new PIXI.particles.Emitter(view, twinkleTexture, twinkleConfig);
  twinkle.updateOwnerPos(300, 0);
  var tree = new PIXI.Sprite(treeTexture);
  tree.position.x = WIDTH - 51;
  tree.position.y = HEIGHT - 88;
  stage.addChild(tree);
}
</script>
</head>
<body onload="initialize();">
</body>
</html>

pixi.jsを使用しています。particleを作るのにPixi Particles Editorを使いました。
簡単にパーティクルの設定を試せて、その設定をダウンロードまでできてしまいます。便利。

Pixi Particles Editor

けっこう雑になってしまいましたが、完成です。

素材類について

雪の結晶、クリスマスツリー、サンタはこちらからお借りしました。ありがとうございます。

シルエットデザイン

できたもの

electron.gif

WebGLなので、処理はGPUがやってくれているようで、このままで作業自体には問題がありませんでした。
無事完成したのはいいのですが、予想通りマシンが熱くなります。
クリスマス気分には代償が必要だったようです・・・。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4