こんにちは。LIGフィリピン支社代表のせいと(@seito_horiguchi)です。
最近とある案件で「刀でズバッと切る感じのアニメーションを入れる」ってことになって、実装してみました。ゲームなどでよくある表現ですね。
やってみると、ポイントを押さえれば意外とシンプルに実装できたので、その方法をご紹介したいと思います。
はじめに
今回はこちらの画像を使いたいと思います。
我らが広報ヨシキさんです。
垂直か水平にズバッと斬るアニメーションなら比較的簡単なんですが、このような表現においてよく使うのは斜めにズバッと斬るアニメーションだと思うので、そっちにしてみます。
素材となる画像を用意する
まずはPhotshopで画像をつくります。
ズバッと斬るアニメーションを実装するには、元の画像から3つの画像をつくる必要があります。
上半分の画像
まずは上半分の画像をつくります。
では早速やってみましょう。手順は以下の通りです。
1. 三角形に選択する
選択ツールを使って、ズバッと斬る画像を選択します。
「多角形選択ツール」が使いやすくて良いです。
2. マスクツールで余計な部分を消す
マスクツールで綺麗に画像を切り取りましょう。
このとき、完全に半分のラインで切るのではなく、数px内側にずらすのがポイントです。
下半分の画像
続いて下半分を作成します。上半分画像を作るのと全く同じ要領です。
上下の画像を重ねるとこんな感じになります。
数pxずらしたことで、切れ目ができてると思います。
このラインが、後のズバッと斬るアニメーションの切れる部分になります。
斬れるところの画像
最後に、刀でズバッと斬れる部分を覆う部分を作成したいと思います。
やり方はさっきと同様、選択ツールとマスクを使います。
これがあとあと重要になってきます。
このとき、ちょっと大きめに切っておくのがポイントです。
ぴったりすぎると、画像の切れ目が見えてしまいます。
これでひとまず素材はそろいました。
次はHTML、CSSの実装に入ります。
HTMLとCSSを実装する
続いてHTMLとCSSでコーディングします。
まずは動きをつけず、静的にコーディングします。
HTML
<div class="slash" id="js_slash">
<div class="slash_inner">
<!-- 切れ目画像 -->
<div class="slash_img slash_wrap">
<img src="images/slash_sample3.png" alt="" class="slash_img_inner">
</div>
<!-- 上半分画像 -->
<img src="images/slash_sample1.png" alt="" class="slash_img up">
<!-- 下半分画像 -->
<img src="images/slash_sample2.png" alt="" class="slash_img down">
</div>
</div>
ここでのポイントは、切れ目画像をdivタグで囲っておくことです。
.slash_wrap,.slash_img_innerには、あとでそれぞれ別のアニメーションをつけます。
SASS/CSS
.slash {
overflow: hidden;
padding-top: 50px;
background: #fff;
.slash_inner {
width: 655px;
height: 437px;
overflow: hidden;
margin: 0 auto;
position: relative;
background: #fff;
z-index: 1;
transition: opacity 1s;
opacity: 1;
&.is_hidden {
opacity: 0;
}
}
.slash_img {
display: block;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
&.slash_wrap {
z-index: 4;
}
&.up {
z-index: 3;
}
&.down {
z-index: 2;
}
}
.slash_text{
width: 655px;
height: 437px;
line-height: 437px;
text-align: center;
font-size: 160px;
font-weight: bold;
}
}
.back_text {
width: 100%;
height: 437px;
line-height: 437px;
text-align: center;
font-size: 160px;
font-weight: bold;
position: absolute;
top: 50px;
left: 0;
z-index: 0;
}
CSSでは画像要素3つをpositionで重ね、切れ目、上半分、下半分の順番で並べます。
ここまででできあがったのがこちら。
http://seito2014.github.io/slash/sp/preview/slash_solid.html
今のところは、ただのヨシキさんに見えるはずです。
CSS(keyframe)とjQueryでアニメーションをつける
いよいよアニメーションをつけたいと思います。
CSS
// 斬れ目アニメーション
@keyframes slashSord{
0% {
opacity: 1;
}
20%{
opacity: 0.2;
}
100%{
opacity: 1;
}
}
// 上半分アニメーション
@keyframes slashUp{
0% {
transform: translate3d(0,0,0);
}
100% {
transform: translate3d(-655px,430px,0);
}
}
// 斬れ目アニメーション
.slash_img_inner {
&.is_animating{
animation: slashSord 0.25s ease-out both;
}
}
// 上半分アニメーション
.slash{
&.is_animating {
.slash_wrap,
.up {
animation: slashUp 2s ease both;
}
}
}
JavaScript
(function () {
'use strict';
var $slash =$('#js_slash'),
$slashInner = $slash.find('.slash_img_inner');
$(window).on('load',function(){
//切れ目アニメーション
setTimeout(function() {
$slashInner.addClass('is_animating');
},1000);
// 上半分が斬れるアニメーション
$slashInner.on('webkitAnimationEnd',function(){
setTimeout(function(){
$slash.addClass('is_animating');
},1000);
});
//.slashを丸ごと消す
$slash.find('.up').on('webkitAnimationEnd',function(){
$slash.find('.slash_inner').addClass('is_hidden');
});
});
})();
JavaScriptでは
- ページのロードが完了したら、1秒遅らせてから斬れ目要素(.slash_img_inner)をアニメーションさせる。
- 1のアニメーションが完了したら、上半分要素(.up)と切れ目要素を覆っている要素(.slash_wrap)両方をアニメーションさせる。
ということをやっています。
ロードしてすぐにアニメーションさせると、早すぎて切れ目アニメーションが見えないことがあるため1秒遅らせています。
ちなみに“webkitAnimationEnd”はCSS3のtransitionのアニメーションが完了したタイミングを感知できるイベントです。
動かしてみる
さて、ここまででとりあえず実装したものがこちらです。
ズバッとした感じが表現できているのではないでしょうか。
…しかし、うーん。単調でアニメーションの効果が活きていない気もします。
keyfrmaesの動きをちょっと調整してみましょう。
// 斬れ目アニメーション
@keyframes slashSord{
0% {
opacity: 1;
}
20%{
opacity: 0.2;
}
100%{
opacity: 1;
}
}
// 上半分アニメーション
@keyframes slashUp{
0% {
transform: translate3d(0,0,0);
}
50%{
transform: translate3d(-70px,46px,0);
}
70% {
transform: translate3d(-70px,46px,0);
}
100% {
transform: translate3d(-655px,430px,0);
}
}
@keyframes slashDown{
70% {
transform: translate3d(0,0,0);
}
100% {
transform: translate3d(655px,-430px,0);
}
}
// 斬れ目アニメーション
.slash_img_inner {
&.is_animating{
animation: slashSord 0.25s ease-out both;
}
}
.slash{
&.is_animating {
// 上半分アニメーション
.slash_wrap,
.up {
animation: slashUp 2s ease both;
}
// 下半分アニメーション
.down{
animation: slashDown 2s ease both;
}
}
}
上半分が切れる動きに緩急をつけて、下半分にも動きをつけてみました。
そんでもって、できあがったのがこちら。
うん、より斬られている表現になったと思います。
まとめ
というわけで、以上、刀でズバッと斬るようなアニメーションのチュートリアルでした。けっこう短いコードで実現できたんではないでしょうか。
ただ注意していただきたいのが、今回はアニメーションの動きにのみ絞って解説させていただきましたが、実際にはもうちょいいろいろ気をつけるべきポイントがあります。
ざっとあげるとこんな感じです。
- 画像の読み込みまでに多かれ少なかれ時間がかかるため、そのままだと画像読み込み中に動いてしまうことがあります。その場合はあらかじめ画像をキャッシュさせておく、ロード画面を用意しておく、など工夫をするといいかもしれません。
- こんなバグがあるので、今回のようにtransitionプロパティを多用する際はJSでopacity操作はしないよう注意しましょう。
- 古いAndroid OSだと、要素を重ねる際に意図した配置にならない可能性がけっこうあります。要調整です。
などなど。。。
実務で試す際はお気をつけください。
また、今回使用したデータはGitHubにアップしています。
もしご興味があれば、こちらからダウンロードやらpullやらしてみてください。
【縦横無尽なアニメーション表現】
※ CSS3とjQueryでオリジナル画像のスプライトアニメーションを実装する方法
※ animateとjQuery.Deferredで動きのある「トップへ戻る」ボタンを作ってみよう
※ p5.jsでProcessingのようにリッチなWeb表現を作るチュートリアル
※ ScrollMagicを使ってスクロールに応じたアニメーションをさせてみよう
※ 小さな工夫が光る、テキストリンクのHoverアニメーション参考集
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。