9
0

More than 3 years have passed since last update.

ターミナルに雪を降らせる

Last updated at Posted at 2019-12-12

LIFULLその2 Advent Calendar 2019の13日目です。
去年も13日目だった気がする。しかも今年は13日の金曜日。

すっかり冬になりました。
冬といえば雪
どうせなら雪を見ながら作業したいなーなんて思いました。
というわけで

雪を降らせる(ターミナルに)

使うもの

  • Hyper

雪を降らせるための作戦

HyperはUIコンポーネントが以下のようになっています。
公式より、コンポーネントについて
Termのコンポーネントに雪を降らせるための要素を重ねて表示させることにします

とりあえず、ローカルのプラグインを読み込ませる

Macの場合は、~/.hyper_plugins/local/以下にプラグインを自作して、読み込ませます

mkdir ~/.hyper_plugins/local/snow
touch ~/.hyper_plugins/local/snow/index.js

設定ファイルを編集して、ローカルのプラグインを読み込むようにする

~/.hyper.js
localPlugins: [
  "snow"
],

ローカルプラグインの準備ができたので、あとは雪を降らせるためにいじるだけです

まずは雪を降らせる場所作り

作成したindex.jsで雪を降らせる場所(div)を追加します

index.js
exports.decorateTerm = (Term, { React, notify }) => {
  return class extends React.Component {
    render () {
      return React.createElement('div',{style: { width: '100%', height: '100%', position: 'relative' }}, [
        React.createElement('div', { class: 'snowfall' }), //雪を降らせるためのdiv要素
        React.createElement(Term, this.props), //元々のターミナル
      ]);
    }
  }
}

細かい説明は省きますが、元々のTermコンポーネントに雪を表示するための要素を追加しています。
詳細については、このあたりが参考になります。

index.jsを変更したら、⇧⌘Rでリロードしてください。

実際に降らせる雪づくり

雪を降らせる場所に、雪の要素を追加します。

index.js
exports.decorateTerm = (Term, { React, notify }) => {
  return class extends React.Component {
    render () {
      return React.createElement('div',{style: { width: '100%', height: '100%', position: 'relative' }}, [
        React.createElement('div', { class: 'snowfall' },
          React.createElement('div', { class: 'snow' }, '')
        ),
        React.createElement(Term, this.props),
      ]);
    }
  }
}

誰がどう見ても、雪が追加されました。
スクリーンショット 2019-12-12 2.25.05.png

雪を降らせる

スタイルを追加して、雪を降らせるアニメーションやら表示位置やらを調整します。
特に凝ったことはしないので、アニメーションもcssで完結させます。

index.js
exports.decorateTerm = (Term, { React, notify }) => {
  return class extends React.Component {
    render () {
      return React.createElement('div',{style: { width: '100%', height: '100%', position: 'relative' }}, [
        React.createElement('div', { class: 'snowfall' },
          React.createElement('div', { class: 'snow' }, '')
        ),
        React.createElement('style', {}, `
          .snowfall {
            position: absolute;
            height: 100%;
            width: 100%;
            pointer-events: none;
            z-index: 100;
          }

          div.snow {
            animation: snowfall 3s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 10%;
          }

          @keyframes snowfall {
            0% {
              transform: translateY(0) rotateY(0);
            }
            50% {
              transform: translateY(50%) rotateY(180deg);
            }
            100% {
              transform: translateY(100%) rotateY(360deg);
              opacity: 0;
            }
          }
        `),
        React.createElement(Term, this.props),
      ]);
    }
  }
}

<style>の要素を直接追加して、cssを当てるようにしています。
単純なのでとりあえずこれで良いかなと

自分なりのポイントを解説すると、z-index: 100;の部分がポイントで、
開発者コンソールで確認すると、元々のTerm要素にz-indexが設定されているようで、
問答無用で最前面に出すために100とかの数値を設定してます。
最前面に出すためなので、値は100でも1000でも10000でも問題ないです。

とりあえずここまでで雪が降り始めました。
snowfall#1.gif

雪をふやす

あとは適当に雪を追加して、アニメーションの時間などをいじって雪っぽさを演出します。

長いので省略
index.js
exports.decorateTerm = (Term, { React, notify }) => {
  return class extends React.Component {
    render () {
      return React.createElement('div',{style: { width: '100%', height: '100%', position: 'relative' }}, [
        React.createElement('div', { class: 'snowfall' },
          React.createElement('div', { class: 'snow'}, ''),
          React.createElement('div', { class: 'snow2'}, ''),
          React.createElement('div', { class: 'snow3'}, ''),
          React.createElement('div', { class: 'snow4'}, ''),
          React.createElement('div', { class: 'snow5'}, ''),
          React.createElement('div', { class: 'snow6'}, ''),
          React.createElement('div', { class: 'snow7'}, ''),
          React.createElement('div', { class: 'snow8'}, ''),
          React.createElement('div', { class: 'snow9'}, ''),
        ),
        React.createElement('style', {}, `
          .snowfall {
            position: absolute;
            height: 100%;
            width: 100%;
            pointer-events: none;
            z-index: 100;
          }

          div.snow {
            animation: snowfall 3s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 10%;
          }

          div.snow2 {
            animation: snowfall 8s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 20%;
          }

          div.snow3 {
            animation: snowfall 2s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 30%;
          }

          div.snow4 {
            animation: snowfall 5s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 40%;
          }

          div.snow5 {
            animation: snowfall 10s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 50%;
          }

          div.snow6 {
            animation: snowfall 7s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 60%;
          }

          div.snow7 {
            animation: snowfall 9s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 70%;
          }

          div.snow8 {
            animation: snowfall 4s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 80%;
          }

          div.snow9 {
            animation: snowfall 2s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 90%;
          }

          @keyframes snowfall {
            0% {
              transform: translateY(0) rotateY(0);
            }
            50% {
              transform: translateY(50%) rotateY(180deg);
            }
            100% {
              transform: translateY(100%) rotateY(360deg);
              opacity: 0;
            }
          }
        `),
        React.createElement(Term, this.props),
      ]);
    }
  }
}

完成したやつ && 作業風景

snowfall#2.gif

まとめ

ターミナルに雪を降らせたけど、予想以上に鬱陶しいので、
雪が見たければ本物の雪を見にいこう

参考

9
0
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
9
0