jQuery を使って簡単に Lightbox のようなモーダルウィンドウを表示する方法のメモ。
サムネイル画像の HTML
<p class="thumbnail">
<a href="images/photo_Large.jpg">
<img src="images/thumbnail_1.jpg" height="100" width="200" />
</a>
</p>
モーダルウィンドウの HTML。
<div id="bg_layer"> <!--半透明の領域--> <!--/#bg_layer--></div> <div id="over_layer"> <!--拡大画像と「閉じる」ボタンを表示する領域--> <img class="lightboxlike" src="#" alt="" /><!--拡大画像--> <p class="close_button"><img src="images/close-trans.png"/></p> <!--/#over_layer--></div>
CSS
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#bg_layer {
display: none;
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: #000;
opacity: 0.60;
filter: alpha(opacity=60);
z-index: 10;
}
#over_layer {
display: none;
position: fixed;
top: 50%;
left: 50%;
z-index: 15;
}
/*---IE6 対策---*/
* html #bg_layer {
position: absolute;
}
/*---IE6 対策---*/
* html #over_layer {
position: absolute;
}
p.close_button {
display: none;
position: absolute;
top: -10px;
right: -10px;
cursor: pointer;
z-index: 20;
}
</style>
jQuery
var full_size_height = 400; //拡大画像の高さ
var full_size_width = 800; //拡大画像の幅
$('p.thumbnail a').click(function() {
if($('#over_layer').css('display') == 'none') {
$('#bg_layer').show();
$('#over_layer').css({
marginTop: '-' + full_size_height/2 + 'px',
marginLeft: '-' + full_size_width/2 + 'px'
});
$('img.lightboxlike').attr('src', $(this).attr('href'));
$('#over_layer, p.close_button').show();
}
return false;
});
//非表示にする(閉じる)処理
$('#bg_layer, p.close_button').click(function() {
$('#over_layer,#bg_layer ').hide();
});
//IE6 対策
if($.browser.msie && $.browser.version<7) {
$(window).scroll(function() {
$('#bg_layer').get(0).style.setExpression('top', "$(document).scrollTop()+'px'");
$('#over_layer').get(0).style.setExpression('top',"($(document).scrollTop()+$(window).height()/2)+'px'");
});
}
[/code]
<h3>スクロールされた場合元の位置に戻す</h3>
場合によってはモーダルウィンドウを表示中にスクロールをして、モーダルウィンドウを開いた位置から移動してしまい、それが問題になる場合は、以下のようにして元の位置に戻せる。
<ul>
<li>モーダルウィンドウを開いた際に、その時点でのスクロールの値を取得して、data() を使って「#overlayer」にその値を保持。</li>
<li>閉じる際に、その値とその時点での値が異なれば、animate() で元の位置にスクロールする。</li>
<li>animate() でスクロールさせることができる要素が html か body かを判定する。</li>
</ul>
$('p.thumbnail a').click(function() {
//その時点でのスクロールの値を取得
$('#overlayer').data('scroll_top', $(window).scrollTop());
if($('#over_layer').css('display') == 'none') {
$('#bg_layer').show();
$('#over_layer').css({
marginTop: '-' + full_size_height/2 + 'px',
marginLeft: '-' + full_size_width/2 + 'px'
});
$('img.lightboxlike').attr('src', $(this).attr('href'));
$('#over_layer, p.close_button').show();
}
return false;
});
// スクロールさせることができる要素が html か body かを判定
var isHtmlScrollable = (function(){
var html = $('html'), top = html.scrollTop();
var elm = $('<div/>').height(10000).prependTo('body');
html.scrollTop(10000);
var rs = !!html.scrollTop();
html.scrollTop(top);
elm.remove();
return rs;
})();
//非表示にする(閉じる)処理
$('#bg_layer, p.close_button').click(function() {
//値が異なれば、animate() で元の位置に戻す
if($(window).scrollTop() != $('#overlayer').data('scroll_top')){
$(isHtmlScrollable ? 'html' : 'body').animate({
scrollTop: $('#overlayer').data('scroll_top')
}, 500);
}
$('#over_layer,#bg_layer ').hide();
});
以下は、ウィンドウのサイズによって表示する画像の大きさを変える場合。
var full_size_height = 600; //拡大画像の高さ
var full_size_width = 400; //拡大画像の幅
$('p.thumbnail a').click(function() {
if($('#over_layer').css('display') == 'none') {
$('#bg_layer').show();
var wh = $(window).height(); //現在のウィンドウの高さを取得
if(full_size_height - (-30) > wh && wh){ //+30 だと文字列になるので「- (-30)」とする
var fixedHeight = wh * 0.87;
var fixedWidth = full_size_width * (fixedHeight / full_size_height);
$('#over_layer').css({
marginTop: '-' + fixedHeight/2 + 'px',
marginLeft: '-' + fixedWidth/2 + 'px'
});
$('img.lightboxlike').attr({src: $(this).attr('href'), height:fixedHeight, width:fixedWidth});
}else{
$('#over_layer').css({
marginTop: '-' + full_size_height/2 + 'px',
marginLeft: '-' + full_size_width/2 + 'px'
});
//高さと幅が変更されている可能性があるので、元の値に戻す
$('img.lightboxlike').attr({src: $(this).attr('href'), height:full_size_height, width:full_size_width});
}
$('#over_layer, p.close_button').show();
}
return false;
});
//非表示にする(閉じる)処理
$('#bg_layer, p.close_button').click(function() {
$('#over_layer,#bg_layer ').hide();
});
//IE6 対策
if($.browser.msie && $.browser.version<7) {
$(window).scroll(function() {
$('#bg_layer').get(0).style.setExpression('top', "$(document).scrollTop()+'px'");
$('#over_layer').get(0).style.setExpression('top',"($(document).scrollTop()+$(window).height()/2)+'px'");
});
}
[/code]
また、関数にしたほうが使いやすい場合は以下のようにすることも可能。
function show_modal_window(this$, img_width, img_height, my_options) {
//$.extendでパラメータをマージ
var settings = $.extend({
zoom_h: 0.87, //高さの縮小倍率
zoom_w: 0.9, //幅の縮小倍率
extra_h: 30, //高さを比較する際のマージン(ピクセル)
extra_w: 10, //幅を比較する際のマージン(ピクセル)
duration: 700, //アニメーション表示の速さ(ミリ秒)
over_layer: '#over_layer', //画像を表示する領域
background_layer:'#bg_layer', //背景を表示する領域
img_element: 'img.lightboxlike', //表示する画像要素
close_element: 'p.close_button' //閉じるボタンの要素
}, my_options || {});
if($(settings.over_layer).css('display') == 'none') {
var image_width = img_width;
var image_height = img_height;
$(settings.background_layer).show();
var wh = $(window).height();
var ww = $(window).width();
//画像の高さがウィンドウの高さより大きい場合
if(image_height - (-settings.extra_h) > wh && image_width - (-settings.extra_w) <= ww){
var fixedHeight = wh * settings.zoom_h;
var fixedWidth = image_width * (fixedHeight / image_height);
$(settings.over_layer).css({
marginTop: '-' + fixedHeight/2 + 'px',
marginLeft: '-' + fixedWidth/2 + 'px'
});
$(settings.img_element).attr({src: this$.attr('href'), height:fixedHeight, width:fixedWidth});
//画像の幅がウィンドウの幅より大きい場合
}else if(image_width - (-settings.extra_w) > ww && image_height - (-settings.extra_h) <= wh){
fixedWidth = ww * settings.zoom_w;
fixedHeight = image_height * (fixedWidth / image_width);
$(settings.over_layer).css({
marginTop: '-' + fixedHeight/2 + 'px',
marginLeft: '-' + fixedWidth/2 + 'px'
});
$(settings.img_element).attr({src: this$.attr('href'), height:fixedHeight, width:fixedWidth});
//画像の高さと幅がウィンドウの高さと幅より大きい場合
}else if(image_width - (-settings.extra_w) > ww && image_height - (-settings.extra_h) > wh){
if((image_width - (-settings.extra_w)) - ww > (image_height - (-settings.extra_h)) -wh) {
fixedWidth = ww * settings.zoom_w;
fixedHeight = image_height * (fixedWidth / image_width);
$(settings.over_layer).css({
marginTop: '-' + fixedHeight/2 + 'px',
marginLeft: '-' + fixedWidth/2 + 'px'
});
$(settings.img_element).attr({src: this$.attr('href'), height:fixedHeight, width:fixedWidth});
}else{
fixedHeight = wh * settings.zoom_h;
fixedWidth = image_width * (fixedHeight / image_height);
$(settings.over_layer).css({
marginTop: '-' + fixedHeight/2 + 'px',
marginLeft: '-' + fixedWidth/2 + 'px'
});
$(settings.img_element).attr({src: this$.attr('href'), height:fixedHeight, width:fixedWidth});
}
}else{
$(settings.over_layer).css({
marginTop: '-' + image_height/2 + 'px',
marginLeft: '-' + image_width/2 + 'px'
});
$(settings.img_element).attr({src: this$.attr('href'), height:image_height, width:image_width});
}
$(settings.over_layer + ',' + settings.close_element).fadeIn(settings.duration);
}
}
attachment_links$.click(function() {
show_modal_window( $(this), 400, 600, {duration: 500 }) ;
return false;
});
if($.browser.msie && $.browser.version<7) { $(window).scroll(function() { $('#bg_layer').get(0).style.setExpression('top', "$(document).scrollTop()+'px'"); $('#over_layer').get(0).style.setExpression('top',"($(document).scrollTop()+$(window).height()/2)+'px'"); }); } $('#bg_layer, p.close_button, p.close_overLayer').click(function() { $('#over_layer,#bg_layer ').fadeOut(500); }); [/code]