先日、jQueryでもモーダルウィンドウの作り方について解説をしました。そもそものモーダルの作り方がわからない方は先にこちらを読んでもらえると理解が早くなります。
今回はモーダルが現れるとき、モーダルを閉じるときにアニメーションをつけていく処理について書いてみます。前回同様、今回も動作サンプルを用意しておくのでご活用ください。
モーダルのアニメーションとは?
前回作ったモーダルはアニメーションがなく表示/非表示がパッと切り替わります。
今回作成したのが以下のサンプルです。コピペ、改造などはご自由にどうぞ。
それぞれに対しての説明なども入れていくので、お好みに加工しながらモーダルウィンドウを使いこなしていきましょう。
なおHTMLに関してはすべて共通なので以下の内容で共通です。bodyの中にボタン部分となるように<p>タグを1つだけ入れてます。
[HTML]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="style.css">
</head>
<body>
<p>スイッチ</p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="modal.js"></script>
</body>
</html>
フェードイン&フェードアウト
フェードイン/アウトではjQuery側でCSSのopacityの値を指定しています。(ディべロッパーツールを開きながら見ると変化がわかりやすいです)
[CSS]
#bg {
height:100%;
width:100%;
top:50%;
left:50%;
position:fixed;
background:rgba(0,0,0,0.4);
transform:translate(-50%,-50%);
}
#modal {
height:80%;
width:90%;
position:fixed;
background:#fff;
top:50%;
left:50%;
transform:translate(-50%,-50%);
overflow-y: scroll;
}
[jQuery]
$(function(){
$('p').click(function(){
$('body').append('<div id="bg">').append('<div id="modal">');
$('#bg, #modal').hide().fadeIn();//生成したあとに一度非表示にしてからフェードインさせる
var num = 0;
$('#modal').append('<ul>');
for(i =0 ; i <50 ; i++){
num += 1;
$('ul').append('<li>'+ num +'</li>');
}
$('#bg').click(function(){
$('#bg,#modal').fadeOut(function(){ //フェードアウトの処理が完了後に背景とモーダル削除
$('#bg,#modal').remove();
});
});
});
});
注意点は2つです。
- 生成した段階ですぐに表示されてしまうのですぐに非表示(hide)にしてからfadeInでゆっくり出現
- 非表示にした後に消す処理は、function内で実行する。(元となるfadeOutの処理が完了したときにfunctionが実行される)
特に2つめがつまずきやすいところです。fadeIn/fadeOutは初期値で400ミリ秒掛かり、以下のように書いてしまうとfadeOutの処理が終わる前に削除されるので実質パッと消えてしまいます。
[ダメな例]
$('#bg,#modal').fadeOut(); //0.4秒掛かる
$('#bg,#modal').remove(); //fadeOutが呼び出されたら即時実行される
また、fadeIn/fadeOutの()内はデフォルトではnormal(400ミリ秒)が設定されており、('slow')('fast')(1000)といった形で引数と設定すれば『ゆっくり』『早く』『1000ミリ秒(1秒)掛けて』といった形でアニメーションの指定が出来ます。
トグルスライド(縦開き)
真ん中から上下に開くタイプのモーダルです。CSSはフェードイン/アウトと一緒です。
[CSS]
#bg {
height:100%;
width:100%;
top:50%;
left:50%;
transform:translate(-50%,-50%);
position:fixed;
background:rgba(0,0,0,0.4);
}
#modal {
height:80%;
width:90%;
position:fixed;
background:#fff;
top:50%;
left:50%;
transform:translate(-50%,-50%);
overflow-y: scroll;
}
[jQuery]
$(function(){
$('p').click(function(){
$('body').append('<div id="bg">').append('<div id="modal">');
$('#bg,#modal').hide().slideToggle();
var num = 0;
$('#modal').append('<ul>');
for(i =0 ; i <50 ; i++){
num += 1;
$('ul').append('<li>'+ num +'</li>');
}
$('#bg').click(function(){
$('#bg,#modal').slideToggle(function(){
$('#bg,#modal').remove();
});
});
});
});
注意点は2つです。
- slideToggleは縦に動く。CSSで初期位置をセンタリングすることで上下に開く/閉じるの動作になる
- 非表示にした後に消す処理は、function内で実行する。(元となるslideToggleの処理が完了したときにfunctionが実行される)
slideToggleは縦に動きます。CSSを以下のようにした場合はシャッターみたいに上から出てくるようにも変更できます。
[CSS]
#bg {
height:100%;
width:100%;
top:0%;
left:0%;
position:fixed;
background:rgba(0,0,0,0.4);
}
#modal {
height:80%;
width:90%;
position:fixed;
background:#fff;
left:50%;
transform:translateX(-50%);
overflow-y: scroll;
}
2つめはフェードイン/アウトでも話した内容ですので割愛します。
また、slideToggleもfadeIn/fadeOutと同様に引数を指定すればアニメーションのスピードの指定ができます。
トグルスライド(横開き)
真ん中から左右に開くモーダルです。
[CSS]
#bg {
height:100%;
top:50%;
left:50%;
transform:translate(-50%,-50%);
position:fixed;
background:rgba(0,0,0,0.4);
}
#modal {
height:80%;
position:fixed;
background:#fff;
top:50%;
left:50%;
transform:translate(-50%,-50%);
overflow-y: scroll;
}
[jQuery]
$(function(){
$('p').click(function(){
$('body').append('<div id="bg">').append('<div id="modal">');
$('#bg,#modal').width(0);
$('#bg').animate({width:100+'%'});
$('#modal').animate({width:90+'%'});
var num = 0;
$('#modal').append('<ul>');
for(i =0 ; i <50 ; i++){
num += 1;
$('ul').append('<li>'+ num +'</li>');
}
$('#bg').click(function(){
$('#bg,#modal').animate({width:'toggle'},function(){
$('#bg,#modal').remove();
});
});
});
});
注意点は3つです。
- slideToggleは縦に動くので不可。
- slideToggleではdisplayプロパティの値を変更していたが、横開きの場合はwidthの値を操作するのでhide()は厳禁
- animate({width:'toggle'})かと思いきや、今回は生成された段階を初期値としているのでいきなり閉じてしまう。なので今回は最初にwidthを0にしてからanimateでそれぞれのwidthに値を振りなおしている/span>
最重要なのはslideToggleは縦の動きなのでwidthを上手く変化させることですね。2つ目の注意点は少しわかりづらいですが、on(表示)/off(非表示)を切り替えるのですが、生成された段階でon(表示)になっていてそこからtoggleの処理が発生するとoffに切り替わってしまうという事です。
以下のようにした場合はスマホなどで使われるいわゆる『ハンバーガーメニュー』みたいに左から出てくるようにも変更できます。その場合はjQueryの6行目の$('#modal').animate({width:90+'%'});の90を好きな割合に変更してください。
[CSS]
#bg {
height:100%;
top:0%;
left:0%;
position:fixed;
background:rgba(0,0,0,0.4);
}
#modal {
height:80%;
position:fixed;
background:#fff;
left:50%;
transform:translateX(-50%);
overflow-y: scroll;
}
他のモーダルと比べて少し難易度が高いかもしれません。
また、 $('#bg').animate({width:100+'%'},1000);と引数を指定すればアニメーションのスピードの指定ができます。(今回は1000ミリ秒)
ズームイン
中心部分から出てきて、大きくなる(表示)/小さくなる(非表示)でズームイン/アウトをします。
[CSS]
#bg {
height:100%;
width:100%;
top:0%;
left:0%;
position:fixed;
background:rgba(0,0,0,0.4);
}
#modal {
height:80%;
width:90%;
position:fixed;
background:#fff;
top:0%;
left:0%;
bottom:0%;
right:0%;
margin:auto;
overflow-y: scroll;
}
.zoomIn {
animation:ZoomIn 0.4s linear;
}
@-webkit-keyframes ZoomIn {
0% {
transform:scale(0);
}
100% {
transform:scale(1);
}
}
@keyframes zoomIn {
0% {
transform:scale(0);
}
100% {
transform:scale(1);
}
}
.zoomOut {
animation:ZoomOut 0.4s linear;
}
@-webkit-keyframes ZoomOut {
0% {
transform:scale(1);
}
100% {
transform:scale(0);
}
}
@keyframes zoomOut {
0% {
transform:scale(1);
}
100% {
transform:scale(0);
}
}
[jQuery]
$(function(){
$('p').click(function(){
$('body').append('<div id="bg">').append('<div id="modal">');
$('#bg,#modal').addClass('zoomIn');
var num = 0;
$('#modal').append('<ul>');
for(i =0 ; i <50 ; i++){
num += 1;
$('ul').append('<li>'+ num +'>/li>');
}
$('#bg').click(function(){
$('#bg,#modal').removeClass('zoomIn');
$('#bg,#modal').addClass('zoomOut');
setTimeout(function(){
$('#bg,#modal').remove();
},350);
});
});
});
注意点は3つです。ズームインとズームアウトに関してはCSSアニメーションの理解が必要です。
- CSS側で予めズームイン/アウト(表示/非表示)用のclassでCSSアニメーションを記入しておく
- addClass/removeClassを使ってモーダルと背景にイベント実行時にclassの付与/除去をする
- setTimeoutを使って、消去のタイミングを別指定
jQuery側でCSS({'transition':アニメーションの内容});でやってもいいのですが、スマホでの閲覧などを考えるとアニメーションはなるべくjQuery側よりCSS側で指定したほうがヌルヌルと動きます。
fadeIn/OutやslideToggleに関してもCSSで書けるならばCSS側のほうがいいです。(今回は処理実行説明用にあえてjQuery側で書いてますが…)
CSSアニメーションについて、詳しくはこちらをご覧ください。
また、setTimeoutでモーダルと背景消すタイミングを今回は別指定しています。
- $('#bg,#modal').addClass('zoomOut',function(){$('#bg,#modal').remove();});にしてしまうとclassが付与された瞬間にモーダルと背景が消去される※CSSアニメーションの終わったタイミングを拾うのではなく、まさにclass付与された瞬間に実行される
- この理由から、$('#bg,#modal').remove();が実行されるタイミングを個別に指定
- setTimeoutの引数を350ミリ秒にしているのは、アニメーションが終わるタイミングより若干早くすることできれいに消せる※CSSアニメーションで指定した時間と同じ時間にすると残像が出る
ズームアウト
ふわっと被さるようになるアニメーションです。
[CSS]
#bg {
height:100%;
width:100%;
top:0%;
left:0%;
position:fixed;
background:rgba(0,0,0,0.4);
}
#modal {
height:80%;
width:90%;
position:fixed;
background:#fff;
top:0%;
left:0%;
bottom:0%;
right:0%;
margin:auto;
overflow-y: scroll;
}
.zoomIn {
animation:ZoomIn 0.4s linear;
}
@-webkit-keyframes ZoomIn {
0% {
transform:scale(1.5);
opacity:0;
}
100% {
transform:scale(1);
opacity:1;
}
}
@keyframes zoomIn {
0% {
transform:scale(1.5);
}
100% {
transform:scale(1);
}
}
.zoomOut {
animation:ZoomOut 0.4s linear;
}
@-webkit-keyframes ZoomOut {
0% {
transform:scale(1);
opacity:1;
}
100% {
transform:scale(1.5);
opacity:0;
}
}
@keyframes zoomOut {
0% {
transform:scale(1);
opacity:1;
}
100% {
transform:scale(1.5);
opacity:0;
}
}
[jQuery]
$(function(){
$('p').click(function(){
$('body').append('<div id="bg">').append('<div id="modal">');
$('#bg,#modal').addClass('zoomIn');
var num = 0;
$('#modal').append('<ul>');
for(i =0 ; i <50 ; i++){
num += 1;
$('ul').append('<li>'+ num +'</li>');
}
$('#bg').click(function(){
$('#bg,#modal').removeClass('zoomIn');
$('#bg,#modal').addClass('zoomOut');
setTimeout(function(){
$('#bg,#modal').remove();
}, 350);
});
});
$('p').dblclick(function(){
$('#bg,#modal').remove();
});
});
注意点は3つです。ズームインとズームアウトに関してはCSSアニメーションの理解が必要です。
- CSS側で予めズームイン/アウト(表示/非表示)用のclassでCSSアニメーションを記入しておく
- addClass/removeClassを使ってモーダルと背景にイベント実行時にclassの付与/除去をする
- setTimeoutを使って、消去のタイミングを別指定
ズームインのモーダル同様、jQuery側でCSS({'transition':アニメーションの内容});でやってもいいのですがスマホでの閲覧などを考えるとアニメーションはなるべくjQuery側よりCSS側で指定したほうがヌルヌルと動きます。
CSSアニメーションについて、詳しくはこちらをご覧ください。
CSSアニメーション側でzoomInの0%{transform:scale(1.5);}とzoomOutの100%{transform:scale(1.5);}の値を弄れば勢いに変化が付けられます。
そもそものアニメーション時間の設定に関してはズームインモーダルの時にsetTimeoutのお話ししたのでそちらを参考にしてください。
前回はモーダルの生成/除去だけの話でしたが、アニメーションを付けるだけでもまた印象が変わります。またモーダルが表示された時の細かい指定についてはまだまだ気にすべき点が残ってますがそれは別の機会に解説していきます。
よくわからなかったという方は、今一度モーダルの基本的な作り方から見てみることをお勧めします。