【jQuery】画像サイズ自由/レスポンシブ対応のLight Boxを作ってみた

64Thumb

ポップアップさせる画像のサイズが自由でレスポンシブ対応したライトボックスをjQueryで自作してみました。

1ページに複数配置する前提で、一枚だけの場合ももちろん可。
拡大画像の配置位置を【上下中央】と【top位置固定】の2パターン作成しました。

スマートじゃない記述もあるかもしれませんが、動作的にはmac/winの主要最新ブラウザ(IEは〜9)、iphon5sで確認済みです。
記事下部でdemoファイルをダウンロードできます。

Demo

仕様はDemoを見てもらったほうが早いかと。

demo①:上下中央配置
demo②:top位置固定配置

両方『拡大画像を見る』ボタンを置いてます。
ボタンに付与してるトリガーの『.btnOpen』を画像の方に付与すれば、画像をクリックしてポップアップされるようになります。

各要素に固有のclass、IDを与えているわけではないので、WordPressでループで出力させた場合も使えます。

違いとしては、
①では拡大画像の表示位置を上下中央、②はブラウザの上部から100pxに指定。

また、『画像サイズ自由』とありますが、①はブラウザの縦幅に収まる位のサイズ(横長)を念頭に置き、拡大画像表示時はPC/SPでスクロールを禁止する指定にしています。

②は縦幅に収まらないサイズの画像(縦長)を念頭に置き、top位置を固定。スクロールもできるようになってます。

コード

htmlとjQueryのコードです。
htmlはdemo①と②共通。

demo①② HTML
<div class="demo_lightbox">
        <h1>demo<br>画像サイズ自由/レスポンシブ対応ライトボックス</h1>
        <p class="text">ー 上下中央配置/スクロール禁止 ー</p>
        
        <div class="container">
            <div class="wrap_img_thumbnail">
                <img src="images/sample-thumbnail01.jpg" alt="" />
            </div>
            <p class="photo_size">画像サイズ:800×530px</p>
            <div class="btnOpen">拡大画像を見る</div>

            <div class="wrap_img_zoom">
                <div class="btnClose"></div>
                <div class="img_zoom">
                    <img src="images/sample-zoom01.jpg" />
                </div>
            </div>
        </div>
    </div>
</body>
demo① jQuery
$(function () {
    $("body").append("<div id='glayLayer'></div>");

    $(".btnOpen").click(function () {

        //表示コンテンツの幅がwindow幅より小さかった場合のコンテンツ幅を指定
        var windowWidth = $(window).width();
        var imgWidth = $(this).parents(".container").children(".wrap_img_zoom").outerWidth();
        var imgHeight = $(this).parents(".container").children(".wrap_img_zoom").outerHeight();
        var bodyPaddingLR = 20;
        var totalWidth = imgWidth + bodyPaddingLR;

        //『if (windowWidth < totalWidth) { }』のcssを削除
        $('.wrap_img_zoom').css({
            "-webkit-transform": "",
            "-moz-transform": "",
            "transform": ""
        });

        //画像の位置指定
        var top = $(document).scrollTop() + $(window).height() / 2 - imgHeight / 2;
        var left = ($(window).width() / 2) - imgWidth / 2;
        $('.wrap_img_zoom').css({
            "top": top,
            "left": left
        });

        if (windowWidth < totalWidth) {
            var top = $(document).scrollTop() + $(window).height() / 2;
            var left = $(window).width() - $(window).width() * 0.95 - 10;

            $('.wrap_img_zoom').css({
                "width": "90%",
                "top": top,
                "left": left,
                "-webkit-transform": "translate(0, -50%)",
                "-moz-transform": "translate(0, -50%)",
                "transform": "translate(0, -50%)"
            });
            $('.wrap_img_zoom img').css({
                "width": "100%"
            });
        }

        //オーバーレイとコンテンツを表示
        $("#glayLayer").fadeIn(750);
        $(this).parents(".container").children(".wrap_img_zoom").fadeIn(750);

        //scroll禁止
        //PC
        var scroll_event = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';
        $(document).on(scroll_event, function (e) {
            e.preventDefault();
        });
        //SP
        $(document).on('touchmove.noScroll', function (e) {
            e.preventDefault();
        });
    });

    //window幅をリサイズした際の挙動
    $(window).on('load resize', function () {

        //画像本来のサイズを取得
        var element = $(".wrap_img_zoom:visible img");
        var img = new Image();
        img.src = element.attr('src');
        var imgOriginallyWidth = img.width;
        var imgOriginallyHeight = img.height;
        var bodyPaddingLR = 20;
        var contentsPaddingLR = 20;
        var totalWidth = imgOriginallyWidth + bodyPaddingLR + contentsPaddingLR;
        var windowWidth = $(window).width();

        //画像の位置を指定
        var imgWidth = $(".wrap_img_zoom:visible").outerWidth();
        var imgHeight = $(".wrap_img_zoom:visible").outerHeight();
        var top = $(document).scrollTop() + $(window).height() / 2 - imgHeight / 2;
        var left = ($(window).width() / 2) - imgWidth / 2;

        $('.wrap_img_zoom:visible').css({
            "top": top,
            "left": left
        });

        //totalWidth(画像本来のサイズ+白枠とbodyの余白) < window幅 の場合
        if (totalWidth < windowWidth) {
            $('.wrap_img_zoom').css({
                "width": imgOriginallyWidth
            });
        }
        //totalWidth > window幅 の場合
        if (windowWidth < totalWidth) {
            $('.wrap_img_zoom').css({
                "width": "90%"
            });
            $('.wrap_img_zoom img').css({
                "width": "100%",
                "height": "auto"
            });
        }

        //『if (windowWidth < totalWidth) { }』のcssを削除
        $('.wrap_img_zoom').css({
            "-webkit-transform": "",
            "-moz-transform": "",
            "transform": ""
        });

        //リサイズした際に取得した数値を削除
        $(".wrap_img_zoom:hidden").css({
            "width": "",
            "top": "",
            "left": ""
        });
        $(".wrap_img_zoom:hidden img").css({
            "width": ""
        });
    });

    $("#glayLayer, .btnClose").click(function () {
        $("#glayLayer").fadeOut(350)
        $(".wrap_img_zoom").fadeOut(350);

        //リサイズした際に取得した数値を削除
        $(".wrap_img_zoom:hidden").css({
            "width": "",
            "top": "",
            "left": ""
        });
        $(".wrap_img_zoom:hidden img").css({
            "width": ""
        });

        //scroll禁止解除
        //PC用
        var scroll_event = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';
        $(document).off(scroll_event);
        //SP用
        $(document).off('.noScroll');
    });
});
demo② jQuery
$(function () {
    $("body").append("<div id='glayLayer'></div>");

    $(".btnOpen").click(function () {
        //表示するコンテンツのtopの位置
        var bodyHeight = $(window).scrollTop();
        var mt = 100;
        var top = bodyHeight + mt;
        $(".wrap_img_zoom").css({
            "top": top
        });

        //表示コンテンツの幅がwindow幅より小さかった場合のコンテンツ幅を指定
        var windowWidth = $(window).width();
        var imgWidth = $(this).parents(".container").children(".wrap_img_zoom").outerWidth();
        var bodyPaddingLR = 20;
        var totalWidth = imgWidth + bodyPaddingLR;

        if (windowWidth < totalWidth) {
            $('.wrap_img_zoom').css({
                "width": "90%"
            });
            $('.wrap_img_zoom img').css({
                "width": "100%"
            });
        }

        //オーバーレイとコンテンツを表示
        $("#glayLayer").fadeIn(750);
        $(this).parents(".container").children(".wrap_img_zoom").fadeIn(750);
    });

    //window幅をリサイズした際の挙動
    $(window).on('load resize', function () {

        //画像本来のサイズを取得
        var element = $(".wrap_img_zoom:visible img");
        var img = new Image();
        img.src = element.attr('src');
        var imgOriginallyWidth = img.width;
        var imgOriginallyHeight = img.height;
        var bodyPaddingLR = 20;
        var contentsPaddingLR = 20;
        var totalWidth = imgOriginallyWidth + bodyPaddingLR + contentsPaddingLR;
        var windowWidth = $(window).width();

        //totalWidth(画像本来のサイズ+白枠とbodyの余白) < window幅 の場合
        if (totalWidth < windowWidth) {
            $('.wrap_img_zoom').css({
                "width": imgOriginallyWidth
            });
        }
        //totalWidth > window幅 の場合
        if (windowWidth < totalWidth) {
            $('.wrap_img_zoom').css({
                "width": "90%"
            });
            $('.wrap_img_zoom img').css({
                "width": "100%",
                "height": "auto"
            });
        }

        //リサイズした際に取得した数値を削除
        $(".wrap_img_zoom:hidden").css({
            "width": ""
        });
        $(".wrap_img_zoom:hidden img").css({
            "width": ""
        });
    });

    $("#glayLayer, .btnClose").click(function () {
        $("#glayLayer").fadeOut(350)
        $(".wrap_img_zoom").fadeOut(350);

        //リサイズした際に取得した数値を削除
        $(".wrap_img_zoom:hidden").css({
            "width": ""
        });
        $(".wrap_img_zoom:hidden img").css({
            "width": ""
        });
    });
});

アレンジする際の補足

作ってるうちに記述が予想以上のボリュームになったため、簡単にアレンジする際の補足を2点だけします。
(他はメモを参照下さい。メモだけだと不十分かと思いますが…)

1. demo①② 拡大画像の白枠の幅を調整

これは①②共通です。
↓のように拡大画像の周りに『padding:10px』分の白枠を指定しています。

64-01

白枠の幅を変えると配置指定に影響するので、その部分の変更について。
画像の白枠は『.wrap_img_zoom』で指定しているので、まずそのpadingの数値を任意の数値に変更(ここでは5pxに)。

jQuery部分はdemo①②それぞれ2箇所変更します。
1つ目は下記コードの最後の『10』を変更した数値『5』に。

var left = $(window).width() - $(window).width() * 0.95 - 10;

2つ目は下記コードの『20』を変更した数値の倍に変更。ここでは5pxにしたので倍の『10』にします。

var contentsPaddingLR = 20;

これで枠の幅を変更しても、左右中央の配置が保たれます。

2. demo②のtop位置変更

②の場合の拡大画像を表示させるtopの位置の変更についてです。

これも一箇所数値を変えるだけなので簡単。
『var mt = 』の数値を任意のものに変えるだけです。

var mt = 100;

さいごに

説明が足らなくて申し訳ないですが。
不備、不明点等ありましたらご連絡ください。

↓からdemoファイルをダウンロードできます。