Kawaii Bubbles!

Category : CSS, jQuery

最近疲れてたので気晴らしに CSS Animations を使ったサンプルを作ってみました。
めちゃくちゃ重いので低スペック環境の人は気をつけてください。できれば Google Chrome で見たほうがいいと思います。

Kawaii Bubbles! スクリーンショット

名前が「Kawaii Bubbles」となってますが、可愛いかどうかは個人の感性に任せます。

Kawaii Bubbles!

デモファイルをダウンロード

背景画像には cammy♥claudia さんの virginie and lambie2 を使用しています。この画像は CC BY-NC-SA 2.0 でライセンスされていますので、ダウンロードしたファイル内の画像も同様のライセンスとなります。

一応、中身はこんな感じになっています。今回は解説なしです。
(あんまり関係部分は省略しています)

<ul id="container" class="bubbles">
  <li>muffin</li>
  <li>brownie</li>
  <li>soufflé</li>
  ...
</ul>
@import url("http://fonts.googleapis.com/css?family=Sevillana");

html {
  background-image     : url("bg.jpg");
  background-attachment: fixed;
  background-position  : bottom center;
  background-size      : cover;
}

body {
  font-family: "Sevillana", "Helvetica Neue", "Segoe UI", "Arial", sans-serif;
}

html,
body {
  height  : 100%;
  overflow: hidden;
}

.bubbles {
  position  : relative;
  top       : 10%;
  margin    : 0 10%;
  width     : 80%;
  height    : 80%;
  list-style: none;
}

.bubbles li {
  position         : absolute;
  padding          : 20px;
  border           : 2px solid;
  border-radius    : 50%;
  text-align       : center;
  text-shadow      : 1px 1px 1px rgba(255, 255, 255, 0.7),
                     1px -1px 1px rgba(255, 255, 255, 0.7),
                     -1px 1px 1px rgba(255, 255, 255, 0.7),
                     -1px -1px 1px rgba(255, 255, 255, 0.7);
  white-space      : nowrap;
  -webkit-transform: scale(0);
  -moz-transform   : scale(0);
  -ms-transform    : scale(0);
  -o-transform     : scale(0);
  transform        : scale(0);
}

@keyframes bubble {

  0% {
    opacity: 1;
    transform: translateY(0px) scale(0);
  }

  3.5% {
    opacity: 1;
    transform: translateY(0px) scale(1.1);
  }

  5% {
    opacity: 0.95;
    transform: translateY(0px) scale(0.9);
  }

  10% {
    opacity: 0.9;
    transform: translateY(-5px) scale(1);
  }

  15% {
    opacity: 0.85;
    transform: translateY(-10px) scale(0.95);
  }

  20% {
    opacity: 0.8;
    transform: translateY(-15px) scale(1);
  }

  25% {
    opacity: 0.75;
    transform: translateY(-20px) scale(0.95);
  }

  30% {
    opacity: 0.7;
    transform: translateY(-25px) scale(1);
  }

  35% {
    opacity: 0.65;
    transform: translateY(-35px) scale(0.95);
  }

  40% {
    opacity: 0.6;
    transform: translateY(-45px) scale(1);
  }

  45% {
    opacity: 0.55;
    transform: translateY(-50px) scale(0.95);
  }

  50% {
    opacity: 0.5;
    transform: translateY(-55px) scale(1);
  }

  55% {
    opacity: 0.45;
    transform: translateY(-60px) scale(0.95);
  }

  60% {
    opacity: 0.4;
    transform: translateY(-65px) scale(1);
  }

  65% {
    opacity: 0.35;
    transform: translateY(-70px) scale(0.95);
  }

  70% {
    opacity: 0.3;
    transform: translateY(-75px) scale(1);
  }

  75% {
    opacity: 0.25;
    transform: translateY(-80px) scale(0.95);
  }

  80% {
    opacity: 0.2;
    transform: translateY(-85px) scale(1);
  }

  85% {
    opacity: 0.15;
    transform: translateY(-90px) scale(0.95);
  }

  90% {
    opacity: 0.1;
    transform: translateY(-95px) scale(1);
  }

  95% {
    opacity: 0.05;
    transform: translateY(-100px) scale(0.95);
  }

  100% {
    opacity: 0;
    transform: translateY(-105px) scale(1);
  }

}
jQuery(function ($) {

  var bubbleContainer = $('#container'),
      bubbles = bubbleContainer.find('li'),

      rand = function (min, max, integer) {
        var num = Math.random() * (max - min);
        if (integer) {
          num = Math.floor(num);
        }
        num = num + min;
        return num;
      },

      rgb = function (min, max) {
        var channels = [];
        for (var i = 0; i < 3; i++) {
          channels.push(rand(min, max, true));
        }
        return channels.join(',');
      },

      rising = function (el) {
        var fSize = rand(20, 40, true),
            color = rgb(100, 200),
            delay = rand(0, 20, true);
        $(el).css({
                    top        : rand(0, bubbleContainer.height(), true),
                    left       : rand(-($(window).width() - bubbleContainer.width()) / 2, bubbleContainer.width(), true),
                    borderColor: 'rgb(' + color + ')',
                    color      : 'rgb(' + color + ')',
                    fontSize   : fSize + 'px'
                  });
        var range = $(el).outerWidth() - (el.style.borderWidth * 2);
        $(el).css({
                    width               : range,
                    height              : range,
                    lineHeight          : range + 'px',
                    boxShadow           : '0 0 10px 0 rgba(' + color + ', 0.8),' +
                                          '0 0 ' + range + 'px' + ' 0 rgba(' + color + ', 0.9) inset,' +
                                          '0 0 ' + range * 0.3 + 'px' + ' 0 rgba(' + color + ', 0.5) inset',
                    webkitAnimation     : 'bubble 10s linear',
                    MozAnimation        : 'bubble 10s linear',
                    msAnimation         : 'bubble 10s linear',
                    OAnimation          : 'bubble 10s linear',
                    animation           : 'bubble 10s linear',
                    webkitAnimationDelay: delay + 's',
                    MozAnimationDelay   : delay + 's',
                    msAnimationDelay    : delay + 's',
                    OAnimationDelay     : delay + 's',
                    animationDelay      : delay + 's'
                  });
      };

  bubbles.each(function () {
    rising(this);
    $(this).on('webkitAnimationEnd MSAnimationEnd OAnimationEnd animationend', function () {
      $(this).css({
                    width          : '',
                    height         : '',
                    webkitAnimation: '',
                    MozAnimation   : '',
                    msAnimation    : '',
                    OAnimation     : '',
                    animation      : ''
                  });
      rising(this);
    });
  });

});

例によって jQuery 部分はアレな感じだと思います。

自分としてはなかなかよくできたと思ってますが、いかんせん重すぎですね……。
たぶん実用性はないです。

Leave a Reply