斜めのシャッターが左右に降りてくるjQueryアニメーション
案件ネタです。
依頼されたのは、とある旅行代理店のランディングページで、左右二択のツアーをクリックして移動するページなのですが、これを画面いっぱいに画像を表示し、左右それぞれにマウスオーバーすると、逆側にシャッターを下ろす、というもの。
これだけ聞けば割と簡単なのですが、厄介なのは画像が斜めであるという点でした。先ずはサンプルを見て貰った方が早いと思います。
https://studio-key.com/Sample2/jquery/Slanting/sample1.html
中央の斜めのラインで分けられたそれぞれの側を覆うようにシャッターさせています。元々このようなアニメーションはFlashで他社に依頼していたようですが、現在のWEBはよほど必要性が無い限り、Flashは使わない方向にシフトしています。今回の案件はPC専用なのでiPhoneやAndroid端末などは考慮しなくて良かったのですが、これらの端末は基本的にFlash非対応です。
どう動かそうか色々と考えました。例えばボックスをcss3で斜めにして移動させるとか、html5でどうにか出来る方法は無いか?とか。
でも、そういうブラウザやバージョン依存なものをランディングページに使うのは宜しく有りません。
色々考えた結果、以下のような構成にしました。
中央のライン、左写真、右写真の順にpositionを絶対で配置し、間にシャッター色(ここでは解りやすく赤)を背景色にしたボックスを挟む感じです。緑色の部分は全体の背景だと思って下さい。
こうすることで、赤い背景をスライドさせると、斜めの裏側になるので綺麗にシャッターするはず。
CSS
#animation{ position: relative; height: 100%; } #full_cover{ background-color: #f4c652; height: 100%; width: 100%; position: absolute; z-index: 1000; } /*-------------------------------------- * センター画像 *--------------------------------------*/ #center_img{ overflow: hidden; height: 100%; position: absolute; top: 0; left: 50%; z-index: 90; } #center_img img{ height: 100%; width: auto; } /*-------------------------------------- * 左画像 *--------------------------------------*/ #left_img{ width: 50%; overflow: hidden; height: 100%; position: absolute; top: 0; left: 0; z-index: 80; } #left_img img{ position: absolute; right: 0; height: 100%; width: auto; } /*-------------------------------------- * 右画像 *--------------------------------------*/ #right_img{ width: 50%; overflow: hidden; height: 100%; position: absolute; top: 0; right: 0; z-index: 70; text-align: right; } #right_img img{ position: absolute; left: 0; height: 100%; width: auto; } /*-------------------------------------- * スライド枠 *--------------------------------------*/ #slide_left{ position: absolute; top : -2000px; height: 100%; width: 100%; background-color: #FDCA8A; z-index: 75; } #slide_right{ position: absolute; top : -2000px; height: 100%; width: 100%; background-color: #FDCA8A; z-index: 75; } /*-------------------------------------- * 全体を覆う枠 *--------------------------------------*/ #FreezePaneOn{ position: absolute; top: 0px; left: 0px; visibility: visible; display: none; width: 100%; height: 100%; z-index: 9999; }
CSSは割と単純で、それぞれ絶対値で配置し、枠内の画像は縦を100%とし、横はオートで可変させます。
Javascript
$(function() { $('body').prepend( '<div id="full_cover"></div><div id="loader" style="position: absolute; z-index:1001;top:10px;left:48%"><img src="loader.gif" /></div>' ); }); $(window).load(function () { $("#loader").hide(); $("#full_cover").fadeOut(); var pos_L = false; var pos_R = false; /* * 画面上にマウスオンしていると、いきなりスライドが * 始まるので、ディレイを入れる */ $("#FreezePaneOn").show(); setTimeout(function(){ $("#FreezePaneOn").hide(); },3000); //ウインドロード時、サイズ変更時に処理 _changeWin(); $(window).resize(function(){ _changeWin(); }); /* * マウスオーバー時にバインドする */ $("#left_img").bind("mouseover", move_R); $("#slide_right").bind("mouseover", out_R); $("#right_img").bind("mouseover", move_L); $("#slide_left").bind("mouseover", out_L); $("#center_img img").bind("mouseover", _outpos); /* * 右をオープン */ function move_R(){ pos_R = true; $("#left_img").css({'z-index':'80'}); $("#right_img").css({'z-index':'70'}); $('#slide_right').animate({top: '0px'}, 'slow','easeOutQuart',function(){ }); } /* * 左をオープン */ function move_L(){ pos_L = true; $("#left_img").css({'z-index':'70'}); $("#right_img").css({'z-index':'80'}); $('#slide_left').animate({top: '0px'}, 'slow','easeOutQuart',function(){ }); } /* * 右を閉じる */ function out_R(){ pos_R = false; $("#FreezePaneOn").show(); $('#slide_right').animate({top: -$(window).height()}, 'slow','easeOutQuart' ,function(){ $("#FreezePaneOn").hide(); }); } /* * 左を閉じる */ function out_L(){ pos_L = false; $("#FreezePaneOn").show(); $('#slide_left').animate({top: -$(window).height()}, 'slow','easeOutQuart',function(){ $("#FreezePaneOn").hide(); }); } /* * 現在閉じている(スライドしてる)枠をスライドアップ */ function _outpos(){ if(pos_L === true) out_L(); if(pos_R === true) out_R(); } /* * ウインドロード時、サイズ変更時に色々変更 */ function _changeWin(){ /* * スライドする枠は下端を上部ピッタリに移動 */ var widow_height = $(window).height(); $("#slide_left").css({'top':-widow_height}); $("#slide_right").css({'top':-widow_height}); /* * 中央画像 * 画像の半分だけ左に寄せる事でセンタリング */ var cnter_margin = $("#center_img img").width() / 2; $("#center_img").css({'margin-left':-cnter_margin}); /* * 左右画像 * 中央画像の半分だけ余白を入れる事でセンターに寄せる * -10 しているのは誤差修正 */ $("#left_img").css({'padding-left':cnter_margin -10}); $("#right_img").css({'padding-right':cnter_margin-10}); } });
これも割と単純で、マウスオーバーした時の挙動を書くだけです。
ウインドサイズが変わる度に画像サイズが変わるので、ウインドサイズから画像を中央に寄るように調整します。厳密には左右二枚の画像は中央で重なる事でぴったりくっつける事になるので、その分のマージンを左右に取る計算をしています。
気をつけたい点として、全画面の左右にマウスオーバーする事でアニメーションが始まるので、ページをロードした時にマウスがブラウザ内に有るケースが多いため、ディレイを入れています。
/* * 画面上にマウスオンしていると、いきなりスライドが * 始まるので、ディレイを入れる */ $("#FreezePaneOn").show(); setTimeout(function(){ $("#FreezePaneOn").hide(); },3000);
FreezePaneOnは全てのボックスの最前面に全画面で表示されるボックスで、これを表示・非表示する事でマウスオーバー時のアニメーションを制御しています。ページ読み込み後はこれを全面に表示し(実際は透明)、3秒後までマウスオーバー効果が機能しないようにしています。
ちなみに、このFreezePaneOnは左右スライド時にも展開され、スライドが終わるまで、次のアニメーションが走らないようにします。
/* * 左を閉じる */ function out_L(){ pos_L = false; $("#FreezePaneOn").show(); $('#slide_left').animate({top: -$(window).height()}, 'slow','easeOutQuart',function(){ $("#FreezePaneOn").hide(); }); }
実際の案件はもっとアイテムも多く複雑ですが、ここまで出来れば、後はスライドした上に文字や画像をアニメーションで移動させてくるなど装飾を加えるのは簡単です。
画像(ページ)が読み終わるまでローディング画像を表示する
今回のアニメーションとは直接の関係は有りませんが、全画面+透明PNGなので、画像は酷く重たいです。また、ブラウザを左右にある程度伸ばしても画像が画面いっぱいに出るように、横幅をかなり長くしています。これを表示するまで、回線が遅いと結構時間が掛かってしまうので、ローディングを入れます。
それがこれ
$(function() { $('body').prepend( '<div id="full_cover"></div><div id="loader" style="position: absolute; z-index:1001;top:10px;left:48%"><img src="loader.gif" /></div>' ); });
full_coverは背景色と同じ色の全画面ボックスで、その上にローディング画像を乗せます。
$(function(){ ~
ページを表示した際に実行します。なので、最初はローディングが表示されます。
次に、画像なんかの処理は以下を使います。
$(window).load(function () { ~
これはページ内のアイテムを全て読み込んだ後に実行されます。
$(window).load(function () { $("#loader").hide(); $("#full_cover").fadeOut();
つまり、最初はローディングをすぐ表示しますが、メインの処理は画像を読み込み終わった際に実行されるように書いていますので、その先頭に full_coverとローディング画像を非表示にする処理を書く事で、ローディングアニメーションのように見せています。
これ、色んな方法が有りますし、プラグインも有ります。待機時間が長いと離脱率が上がるので、テキストなんかはすぐ見せて、画像のみをローディングさせるって手も有ります。ローディングは割と手間が掛かるものが多いですが、今回のような単純な方法でも実現出来ますので、用途に合わせて何を利用するか考えると良いと思います。