読者です 読者をやめる 読者になる 読者になる

LIVESENSE made*

リブセンスのエンジニアやデザイナーの活動や注目していることをまとめたブログです。

MENU

ジョブセンスに桜を咲かせてみた

イントロダクション

ジョブセンスでフロントエンドを担当している小林です。

4月の頭、ジョブセンスではエイプリルフールネタは行わなかったのですが、 時間をかけずに面白いことをやってみよう、 遊び心をもってなにかやってみようということで、 トップページ(PC)に桜を降らせてみました。

f:id:livesense-blog:20160405125046g:plain

コンセプト

12月には雪が降るアニメーションを実施しましたが、 数種類の結晶が垂直に落ちるというシンプルなものでした。

今回は「前回を上回ろう!」という意気込みのもと制作。 がっつりこってり書いて派手にできるのは当たり前かなと思ったので、 「コードはシンプルに、動きはリッチに」をテーマとして作りました。

イメージは

  • 邪魔にならない程度にひらひら・ふわふわ・ゆらゆら
  • CSSアニメーションだけで自作
    • 縦に移動しながら横揺れ
    • 横に揺れながら縦回転
  • SASS の random 関数を使ってスタート位置やアニメーションの間隔・遅延を設定

ざっくりこんな感じ。 18枚(8種類)ある画像も、都度 CSSルールを書くのではなく、SASSのおかげで楽できます。

デモ

PCトップで4月の2週目くらいまで公開しています。

j-sen.jp

ソース

ライセンスはパブリックドメインとしますので、 槍でも豚でも降らせたいものがあるときにはご自由にお使いください。

HTML

7+1種類の画像をSVGで用意し、それぞれ設置。 1枚はジョブセンスのキャラクターをあしらった桜を用意しました。

<div class="flake flake-p1"><img src="/img/home/blossom01.svg"></div>
<div class="flake flake-p2"><img src="/img/home/blossom02.svg"></div>
<div class="flake flake-p3"><img src="/img/home/blossom03.svg"></div>
<div class="flake flake-p4"><img src="/img/home/blossom04.svg"></div>
<div class="flake flake-p5"><img src="/img/home/blossom05.svg"></div>
<div class="flake flake-p6"><img src="/img/home/blossom06.svg"></div>
<div class="flake flake-p7"><img src="/img/home/blossom07.svg"></div>
<div class="flake flake-p8"><img src="/img/home/blossom01.svg"></div>
<div class="flake flake-p9"><img src="/img/home/blossom02.svg"></div>
<div class="flake flake-p10"><img src="/img/home/blossom03.svg"></div>
<div class="flake flake-p11"><img src="/img/home/blossom04.svg"></div>
<div class="flake flake-p12"><img src="/img/home/blossom05.svg"></div>
<div class="flake flake-p13"><img src="/img/home/blossom06.svg"></div>
<div class="flake flake-p14"><img src="/img/home/blossom07.svg"></div>
<div class="flake flake-p15"><img src="/img/home/blossom01.svg"></div>
<div class="flake flake-p16"><img src="/img/home/blossom02.svg"></div>
<div class="flake flake-p17"><img src="/img/home/blossom03.svg"></div>
<!-- 1個だけ特別処理 -->
<div class="flake flake-p18"><img src="/img/home/blossom08.svg" height="25" width="25"></div>

SASS

コメントをつけたので読んでいただければわかると思いますが、

  • forとrandomを使って個別の花びらをランダムに処理
  • 中央にはコンテンツがあるのでそこには降らないように
  • アニメーションは二種類を組み合わせる

といった感じです。

// 花びらの共通ルール
.flake {
  position: absolute;
  transform-origin: 0 0;
  // 縦のアニメーションを再生
  -moz-animation: move-v 25s linear infinite;
  -webkit-animation: move-v 25s linear infinite;
  animation: move-v 25s linear infinite;
  -moz-animation-fill-mode: forwards;
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
  img {
    // 横のアニメーションを再生
    -moz-animation: move-h 3s ease infinite alternate;
    -webkit-animation: move-h 3s ease infinite alternate;
    animation: move-h 3s ease infinite alternate;
    -moz-animation-fill-mode: forwards;
    -webkit-animation-fill-mode: forwards;
    animation-fill-mode: forwards;
  }
}
// 個別の花びらのルールを生成
$flake-gutter: 20px;
@for $i from 1 through 17 {
  .flake-p#{$i} {
    // まとまって落ちるのを防ぐため、スタート位置をずらす
    top: -#{random(20) * 20 + 20px};
    // i の数が増減してもいいように、偶奇で左右の始点を変える
    @if $i % 2 == 0 {
      right: $i * $flake-gutter;
      -moz-animation-delay: 0.5s;
      -webkit-animation-delay: 0.5s;
      animation-delay: 0.5s;
    } @else {
      left: $i * $flake-gutter;
    }
    // 縦のアニメーションの時間の長さを15s以上でバラバラにする
    -moz-animation-duration: random(20) + 15s;
    -webkit-animation-duration: random(20) + 15s;
    animation-duration: random(20) + 15s;
    img {
      // 横のアニメーションの時間の長さを5s以上でバラバラにする
      -moz-animation-duration: random(10) + 5s;
      -webkit-animation-duration: random(10) + 5s;
      animation-duration: random(10) + 5s;
    }
  }
}
// 1個だけ特別処理
.flake-p18 {
  top: -400px;
  right: 0;
  -moz-animation-iteration-count: 2;
  -webkit-animation-iteration-count: 2;
  animation-iteration-count: 2;
  img {
    -moz-animation: none;
    -webkit-animation: none;
    animation: none;
  }
}
// translate3d: 縦移動
// rotate: 左上を軸に半回転
@keyframes move-v {
  0% {
    -moz-transform: translate3d(0, 0, 0) rotate(60deg);
    -ms-transform: translate3d(0, 0, 0) rotate(60deg);
    -webkit-transform: translate3d(0, 0, 0) rotate(60deg);
    transform: translate3d(0, 0, 0) rotate(60deg);
  }
  100% {
    -moz-transform: translate3d(0, 2000px, 0) rotate(-60deg);
    -ms-transform: translate3d(0, 2000px, 0) rotate(-60deg);
    -webkit-transform: translate3d(0, 2000px, 0) rotate(-60deg);
    transform: translate3d(0, 2000px, 0) rotate(-60deg);
    opacity: 0;
  }
}
// translate3d: 横揺れ
// rotateY: Y軸を中心に回転
@keyframes move-h {
  0% {
    -moz-transform: translate3d(-30px, 0, 0) rotateY(0deg);
    -ms-transform: translate3d(-30px, 0, 0) rotateY(0deg);
    -webkit-transform: translate3d(-30px, 0, 0) rotateY(0deg);
    transform: translate3d(-30px, 0, 0) rotateY(0deg);
  }
  50% {
    -moz-transform: translate3d(0, 0, 0) rotateY(360deg);
    -ms-transform: translate3d(0, 0, 0) rotateY(360deg);
    -webkit-transform: translate3d(0, 0, 0) rotateY(360deg);
    transform: translate3d(0, 0, 0) rotateY(360deg);
  }
  100% {
    -moz-transform: translate3d(30px, 0, 0) rotateY(0deg);
    -ms-transform: translate3d(30px, 0, 0) rotateY(0deg);
    -webkit-transform: translate3d(30px, 0, 0) rotateY(0deg);
    transform: translate3d(30px, 0, 0) rotateY(0deg);
  }
}

まとめ

こういったちょっとしたお遊びはユーザーもチームメンバーも楽しめるものですが、 なかなか作るための時間を捻出するのが難しいところです。

今回はCSSアニメーションをSASSから使うことで、 「コードはシンプルに、動きはリッチに」を実現できたかなと思います。

またこうしてパブリックドメインでコードを公開することで、 次に作る方々がもっと簡単に作れるようになっていき、 こういった取り組みが増えていけばさいわいです。