自分を癒すためだけに『Pendulum waves』を作ってみた


Pendulum waves(ペンデュラムウェーブ)とは?

Pendulumとは英語で『振り子』です。
Pendulum wavesとは、その名の通り『振り子を揺らします』
※ここで言う『waves』とは『波』ではなく、一時期流行った野球やサッカーの観戦時にやるアレっぽいヤーツです

最終的な完成物

紆余曲折ありつつ最終的には下記のようなモノになりました。

See the Pen Pendulum waves by nanba (@nanba) on CodePen.

複数個の振り子にて、不思議で美しいパターンが表現できていますよね?
※70秒周期で繰り返します
ザックリ説明すると、糸の長さを順番に少しづつ変えて、周期をズラすことによって、ずっと見てても飽きない美しい癒しがソコに現れます。
1列に揺れていたかと思えば、バラバラになり、3列になったかと思えば、4列になったりと、なんとも言えず不思議で心地よい感情が溢れてきます。(やや大げさな表現)

一日中モニターとニラメッコしつつ、日々多方面からの無理難題と向き合っている我々(少なくとも私)には必要な『癒し』です。

『癒し』を手にするためには?

物理的な方法だと【購入】するか【作成】するかということになるかと思います。

購入するとなると結構な出費になります…下記サイト参照
amazon.co.jp

自作するとなると…超大変そうです…下記サイト参照
自由研究でPendulum Wave【ペンデュラムウェーブ】を作りました

この時点で費用対効果など総合的に考慮し、物理的な『癒し』は諦めざるを得ないという結論に達しました。

手軽にお金をかけずに『癒し』を手に入れる方法を考えながら、イロイロとググっていた時に、ふと
どうせ一日中眺めているモニターに表示させておけばイイんじゃね?ってことに気付く
「一番手軽で簡単に出来るhtml+cssでサクっと作ろう!」
※動画サイトやら、wikiなどに頼らずに、自作しちゃおうっていうコーダー魂のカケラぐらいは残っていた

当初の構築予定

  • 振り子っぽく見せるために支える『糸・紐』は必須!
  • htmlは複雑にしない!(疑似要素もあるしタグ要素は ol>li のみでイイよね…時間ないし)
  • cssは複雑にしない!(球体と紐を繋いで、紐の端っこ支点で rotate させればOKだよね…時間ないし)

※結局、上記のみの実装では当然のように『癒し』にはなりませんでした

具体的Pugったhtml

ol
  - for (var x = 0; x < 20; x++)
    li
      span

これっぽっちです。
ここはまぁ説明するまでもないリスト構造でしかありえないでしょうね。

最終的に書いたscss全文

ただ普通に20個の振り子を少しづつズラして動かすだけなら、こんなにガチャガチャと書く必要はないのですが…
作っていくうちに「もう少しリアルに…」「もう少し滑らかに…」などと、欲張っていくうちに長くなりました。

ol{
  li{
    list-style:none;
    width:40px;
    position:absolute;
    left:calc(50% - 20px);
    transform-origin:top;
    span{
      display:flex;
      align-items:center;
      justify-content:center;
      position:relative;
      overflow:hidden;
      border-radius:50%;
      box-shadow:2px 2px 10px rgba(255,255,255,.6);
      &::before{
        content:"";
        display:block;
        width:10px;
        height:10px;
        position:absolute;
        top:10px;
        left:10px;
        background:#fff;
        border-radius:50%;
        z-index:2;
        filter:blur(3px);
      }
      &::after{
        content:"";
        display:block;
        width:45px;
        height:45px;
        position:absolute;
        background:transparent;
        border-radius:50%;
        z-index:1;
        filter:blur(5px);
        box-shadow:inset -5px -5px 0 2px #333;
      }
    }
    &::before{
      content:"";
      width:2px;
      position:absolute;
      top:0;
      left:calc(50% - 1px);
    }
  }
}
$deg: 20;
@for $i from 0 to $deg{
  ol li:nth-child(#{$i + 1}) {
    height: calc(650px - #{$i * 25}px);
    padding-top: calc(610px - #{$i * 25}px);
    animation:pendulum #{70 / (52 - $i)}s infinite;
    &::before{
      height:calc(610px - #{$i * 25}px);
      background:rgba(($i + 8) * 8,($i + 8) * 8,($i + 8) * 8,1);
    }
    span{
      margin-left:calc(0px - #{$i / 2}px);
      width:calc(40px + #{$i}px);
      height:calc(40px + #{$i}px);
      background:rgba(($i + 8) * 8,($i + 8) * 8,($i + 8) * 8,1);
    }
  }
}
@keyframes pendulum{
  0%{transform:rotate(-25deg);animation-timing-function:cubic-bezier(.45,0,.55,1);}
  50%{transform:rotate(25deg);animation-timing-function:cubic-bezier(.45,0,.55,1);}
  100%{transform:rotate(-25deg);animation-timing-function:cubic-bezier(.45,0,.55,1);}
}

当初の構築予定から大幅に路線変更したcss記述の詳細解説的なアレ

下記に欲張った項目ごとに解説をザックリと

振り子(球体)をソレっぽくする

  • 重なり合った時に少しだけ影というか、ぼかした感じにしたかったので球体に box-shadow を設定
  • 球体に光沢と影を出したかったため球体疑似要素に fliter(blurを使用) を設定

遠近法を少しだけ意識する

  • 奥にある球体が小さく見えるよう幅・高さに calc(40px + #{$i}px) を設定
  • メリハリをつけるため奥にある球体・紐の色自体を濃くするように background:rgba(($i + 8) * 8,($i + 8) * 8,($i + 8) * 8,1); を設定

力学的エネルギー保存の法則を少しだけ意識する

  • 両端に行くほど遅く、中央に近づくほど速く動くように animation-timing-function を設定

制作時間

  • 構想:5分
  • 初期構築:5分
  • 最終調整:1時間(もはや調整の域を超えて時間かけましたね…)

オリジナルページはこちら