Unformed Building

CSS3とJavaScriptで手裏剣を作る

公開:
更新:

パーマリンク

少し前に『jsdo.it』で手裏剣を作って遊んでたんですが、そのときのメモです。
最終的には全然違うものになってしまいましたが、色々と学べたので良しとしますw

とりあず最終的に出来上がったものをどうぞ。Webkitブラウザなら大丈夫だと思いますが、一応Safariで見ることをお勧めします。

CSS3とJavaScriptで八方手裏剣

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

手裏剣はキャッチできますよ。

最初は要素を無限に回転させたかった

<h1 id="rotate">R</h1>
h1 {
  display: inline-block;
  margin: 40px;
  font-size: 80px;
}
var elm = document.getElementById('rotate');
var degree = 0;
var maxDeg = 360;

function r() {

  elm.style.WebkitTransform = 'rotate(' + degree + 'deg)';
  elm.style.MozTransform = 'rotate(' + degree + 'deg)';
  elm.style.OTransform = 'rotate(' + degree + 'deg)';
  elm.style.MsTransform = 'rotate(' + degree + 'deg)';
  elm.style.transform = 'rotate(' + degree + 'deg)';
  degree += +1;
  if (degree < maxDeg) {
    setTimeout(arguments.callee, 1);
  } else if (degree === maxDeg) {
    degree = 0;
    r();
  }
}

r();

CSS3のtransformrotate()を使って止まることなく回転させようと思って作ったものです。
角度が360度以内なら角度を1度ずつ足し続けて、360度になったら角度を0に戻すという処理です。

これを作ったあとに@GeckoTangさんがフォークしてくれました。

そうでした、角度は360度以内じゃなきゃいけないなんてことはなかったんですw
他にはJavaScript部分がwith(){...}を使って、まとめられています。

せっかくなので手裏剣にしてみた

<div id="shuriken" class="shu edge">
  <div class="shu body"></div>
</div>

<div id="shuriken2" class="shu edge">
  <div class="shu body"></div>
</div>
body {
  padding: 50px;
  background: #000;
}

.shu {
  position: relative;
  width: 100px;
  height: 100px;
  background: #eef;
}

.shu:before {
  display: block;
  position: absolute;
  width: 100px;
  height: 100px;
  content: "";
  background: #eef;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
}

.body {
  background: #101010;
  -webkit-transform: scale(0.95);
  -moz-transform: scale(0.95);
  -o-transform: scale(0.95)
  -ms-transform: scale(0.95)
  transform: scale(0.95)
}

.body:before {
  background: #101010;
}

.body:after {
  display: block;
  position: absolute;
  top: 10px;
  left: 10px;
  width: 80px;
  height: 80px;
  content: "\00273f";
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  border-radius: 50%;
  background: -webkit-gradient(radial, center center, 0, center center, 40, from(rgba(255, 255, 255, 0.1)), to(rgba(255, 255, 255, 0)));
  background: -moz-radial-gradient(center center, farthest-side, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0));
  color: #200;
  font-size: 40px;
  text-align: center;
  text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, 1px 1px 0 #000, -1px 1px 0 #000;
  line-height: 80px;
}


/* ここからCSSアニメーション用 */


#shuriken2 {
  margin-top: 50px;
  -webkit-animation-name: rotation;
  -webkit-animation-duration: 3s;
  -webkit-animation-timing-function: linear;
  -webkit-animation-iteration-count: infinite;
}

@-webkit-keyframes rotation {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(-360deg);
  }
}
function rotateAnim(id, direction, speed) {

  var elm = document.getElementById(id);
  var degree = 0;
  var d = direction.toLowerCase();
  var s = speed;

  if (d === 'right') {
    d = '+';
  } else if (d === 'left') {
    d = '-';
  }

  var c = parseFloat(d + s);

  function r() {

    with(elm.style) {
      WebkitTransform = 'rotate(' + degree + 'deg)';
      MozTransform = 'rotate(' + degree + 'deg)';
      OTransform = 'rotate(' + degree + 'deg)';
      MsTransform = 'rotate(' + degree + 'deg)';
      transform = 'rotate(' + degree + 'deg)';
    }
    degree += c;
    setTimeout(arguments.callee, 1);
  }

  r();

}

window.onload = rotateAnim('shuriken', 'left', 0.5);

ここでは、回転させる要素を手裏剣にして、回転させる部分を関数化してみました。
対象要素・回転方向・スピードを指定することができます。
おまけでCSSアニメーションバージョンがついています。

手裏剣の作り方はCSS部分を読んでもらえると分かるかと思います。

これを更にフォークしてCSS3のtransitionwebkitTransitionEndイベントを使って無限に回転させるものを作りました。
また、最後に3D Transformsを使って奥行きのある動きのものも追加しました。

以上を踏まえて作ったもの

出来上がったものはデモページをご覧ください。

CSS3とJavaScriptで八方手裏剣

簡単に説明すると、通常状態、セットされた状態、飛んでいる最中にクラス名を振って、それぞれにCSSで指定をしています。
1回クリックすると、セット状態のクラスを追加。
2回目で投げる(CSSアニメショーン)。
3回目で初期状態に(その前にちょろっとお遊びを入れてますがw)。

JavaScript部分は以下のようになります。
CSSなどはデモページで見るかダウンロードしてご確認ください。

var $elm = $('#shuriken');

/* クリックしたときにクラス名を変更していく */
$elm.toggle(
        function() {
            $(this).addClass('set');
        },
        function() {
            $(this).removeClass('set').addClass('throw');
        },
        function() {
            // クラス名returnがある場合にはキャッチしたと表示
            if($(this).hasClass('return')) {
                $(this).hide().removeClass('throw return');
                $('#catched').show().delay(2000).fadeOut(function() {
                    $elm.fadeIn('fast');
                });
            }
            // ない場合は奥に向かって飛んでいる状態なのでそのまま初期に戻す
            else {
                $(this).removeClass('throw');
            }
        })

    // アニメーションが始まったときの処理
    .bind('webkitAnimationStart', function() {
        // 1.5秒したらreturnというクラス名を付ける
        // 1.5秒はCSSアニメーションから算出。scale(0)になるタイミング
        // throwというクラス名がない場合は初期に戻されているので何もしない
        setTimeout(function() {
            if($elm.hasClass('throw')) {
                $elm.addClass('return');
            }
        }, 1500);
    })

    // アニメーションが終了したときの処理
    // 終了=キャッチされなかった、なので、#killedを表示したあと、初期状態に
    .bind('webkitAnimationEnd', function() {
        $(this).hide().removeClass('throw return');
        $('#killed').show().delay(2000).fadeOut(function() {
            $elm.fadeIn('fast');
        });
    });

本当はjQueryなしで作ろうとしたんですが、だんだん面倒くさくなってきたので……。
JS部分だけ見るとそんなに難しいことはしてません。
一番大変だったのはCSSアニメーションです。
特に3D Transformsは大変です。

練習のつもりで作ってみましたが、思いもかけず色々と勉強になりました。
フォークしたりされたりの楽しさを初めて実感したような気もします。


2020年1月6日 追記:
『jsdo.it』は2019年に閉鎖されましたので、回収できた自分のコードだけデモページに移行しました。