electronでデスクトップにマスコットを表示させる的なもの作ってみた

WallpaperEnginみたいなものを作りたいと思いったのでelectronとtree.jsでなんとかしてみようという記事です

とりあえずelectronのクイックスタートを書き換えてWindowを画面いっぱいにして透明にします
それとwindowをクリックしても反応しないようにしてます

```javascript:main.js

const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow

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

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow

function createWindow () {
  const size = electron.screen.getPrimaryDisplay().size
  // Create the browser window.
  mainWindow = new BrowserWindow({
    left: 0,
    top: 0,
    width: size.width,
    height: size.height,
    frame: false,
    show: true,
    transparent: true,
    resizable: false
  });

  mainWindow.setIgnoreMouseEvents(true);
  mainWindow.maximize();

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  //mainWindow.webContents.openDevTools()

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
```

あとはこれにtree.jsで3Dモデルを表示させるだけです
今回は三つほどGLTFモデルを使ってみようと思います
ポジションはモデルと表示させたい場所に合わせて適当に
(hogeは任意のモデル名)

```javascript:scripts/scene.js

'use strict';
// 幅、高さ取得
const width  = window.innerWidth;
const height = window.innerHeight;

// レンダラの作成、DOMに追加
const renderer = new THREE.WebGLRenderer({ alpha: true ,antialias:true});
renderer.setSize(width, height);
renderer.setClearColor( new THREE.Color(0xffffff),0.0);
document.body.appendChild(renderer.domElement);

// シーンの作成、カメラの作成と追加、ライトの作成と追加
const scene  = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, width / height, 1, 100 );
camera.position.set(0, 0, -10);

var directionalLight = new THREE.DirectionalLight( 0xffeedd, 3);
directionalLight.position.set( 0, 0, 50 );
scene.add( directionalLight );

var directionalLight2 = new THREE.DirectionalLight( 0xffeedd, 3);
directionalLight2.position.set( 0, 0, -50 );
scene.add( directionalLight2 );

var directionalLight3 = new THREE.DirectionalLight( 0xffeedd,1);
directionalLight3.position.set( 50, 0, 0 );
scene.add( directionalLight3 );

var directionalLight4 = new THREE.DirectionalLight( 0xffeedd,1);
directionalLight4.position.set( -50, 0, 0 );
scene.add( directionalLight4 );

var directionalLight5 = new THREE.DirectionalLight( 0xffeedd, 2);
directionalLight5.position.set( 0, 50, 0 );
scene.add( directionalLight5 );

const light  = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);

const clock = new THREE.Clock();
const windmillClock = new THREE.Clock();

let mixer;
let mixerWindmill;


//GLTFの読み込み
const loader = new THREE.GLTFLoader();
loader.load('hoge.gltf', (data) => {
  const object = data.scene;
  const animations = data.animations;

  if (animations && animations.length) {
    let i;

    mixer = new THREE.AnimationMixer(object);
    for (i = 0; i < animations.length; i ++ ) {
      mixer.clipAction( animations[ i ] ).play();
    }

  }

  object.rotation.y =91.1;
  object.position.set(-6, -4, 0);
  scene.add(object);
});

loader.load('hogehoge.gltf', (data) => {
  const object = data.scene;
  const animations = data.animations;

  if (animations && animations.length) {
    let i;
    mixerWindmill = new THREE.AnimationMixer(object);
    for (i = 0; i < animations.length; i ++ ) {
      mixerWindmill.clipAction( animations[ i ] ).play();
    }
  }

  object.rotation.y = -90;
  object.position.set(-6, -4.3, 2)
  scene.add(object)
  
});

loader.load('hogehogehoge.gltf',(data) => {
  const object = data.scene;
  object.position.set(-8, -4.3, 0) 
  scene.add(object);
})

// レンダリング
const animation = () => {
  renderer.render(scene, camera);
  controls.update();

  if(mixer) {
    mixer.update(clock.getDelta());
  }

  if(mixerWindmill) {
    mixerWindmill.update(windmillClock.getDelta());
  }

  requestAnimationFrame(animation);
};

animation();

```
[BlenderでFBX形式をglTF形式に変換してThree.jsでアニメーションさせる （2/2）](https://ryo620.org/2018/02/threejs-animation/)
この記事を参考にしました

ちょっとライトを設置しすぎかなと思うんですけど、均等にあてると二次元的になってしまうのでなんだかなぁ

これとtree.jsとGLTFLoaderをHTMLで読み込んでcssでスクロールバーを非表示にすれば完成です

```html:index.js
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="sc.css">
    <title>Hello World!</title>
  </head>
  <body>
    <script src="three.js/three.min.js"></script>
    <script src="three.js/OrbitControls.js"></script>
    <script src="three.js/GLTFLoader.js"></script>
    <script src="script/scene.js"></script>
    </body>
</html>
```
```css:sc.css
::-webkit-scrollbar{
  display: none;
}
```
---------------
初めて書いたし文章が余り得意じゃないのでぎこちない感じになってます