goo blog サービス終了のお知らせ 

職案人

求職・歴史・仏教などについて掲載するつもりだが、自分の思いつきが多いブログだよ。適当に付き合って下さい。

jQuery入門--ギャラリーページ(高機能)

2025年06月30日 | jQuery

ギャラリーページ(高機能)

【開発環境】
OS:Win11(64ビット)
VSCode1.72.2、VSCodeの拡張機能「Live Server」を搭載している

【各ライブラリ】
・jqueryのCDN:jquery-3.7.1.min.js、 
・jqueryのIUのCDN:jquery-ui.min.js
・モダナイザーのCDN:modernizr.min.js

jquery.ba-throttle-debounce.min.js
jQueryの「スロットル」及び「デバウンス」のプラグイン
スロットル→処理が呼び出されたとき、指定した時間が経過された後に初めて発火します
デバウンス→一定の時間間隔でのみイベントを実行します。最初のイベントが発火してから指定時間内に発生するイベントは実行されません。

・Masonry.pkgd.min.js
Webページ上で「Pinterest」のような縦横サイズの異なるボックスをギャップなく綺麗に並べる

imagesload.pkgd.min.js
画像を読み込み後、何か実行したい場合に用いられる。

【機能】
前回の✘✘.JSONは、すべての画像を読み込んだ後、表示する。そのため、ギャラリーのアイテムが増えれば、処理速度が低下する。更に、アイテムを探すのに時間がかかる。それを、改善するために機能を追加する。

1)一度に、すべてのアイテムを表示せず、「ボタン」をクリックする度に、追加表示される。
2)アイテムをカテゴリによってフィルタリングする機能

【関数の分離】
前回のmain.jsでは、JSONデートの取得、DOM要素の生成、ドキュメントへの挿入、レイアウトまでの一連の処理コードを書いていた。

しかし、アイテムの追加表示やフィルタリング機能をユーザーのタイミングでやる必要があるので、関数にまとめた。

 $.getJSON('./data/content.json', function (data) {



}
// JSON を取得し、initGallery 関数を実行
        $.getJSON('./data/content.json', initGallery);

        // ギャラリーを初期化する
        function initGallery (data) {
  ・
  ・
  ・
  }
 //アイテムを生成し、ドキュメントに挿入する
    function addItems (filter){
  ・
 }
 //アイテムをフィルタリングする
 function filterItems (){

 }
【Webデザイン】

「Load more」ボタンを押すと、更にサムネスを読み込む
【main.html】
ヘッダー部はJQUERYのプラグインを設定している
form要素はギャラリーのサムネイルの種類を選ぶためのラジオボタンを使う為に用いた。
spany要素は、要素を横に表示させるため
ボタン要素は、ギャラリーを更新するため

【CSS】
main.cssファイルにコード
@charset "UTF-8";

/* Base */
html {
    /*フォント種類の指定*/
     "Helvetica Neue", "Arial", "Hiragino Kaku Gothic ProN",
      "Meiryo", sans-serif;
       font-size: 14px;
       line-height: 1.5;
    }
body {
     background-color: rgb(245, 245, 245);
      color: rgb(0, 0, 0);
     }
h1 {
     font-size: 100%;
      margin: 0;
    }
img {
     vertical-align: middle;/*画像や文章などの縦の位置決め*/
    }
/*疑似クラス*/
.clearfix:before, .clearfix:after {
     content: " "; display: table;
    }
.clearfix:after {
     clear: both;
    }


/* Page header */
.page-header {
    background-color: rgb(255, 255, 255);
    border-bottom: 1px solid rgb(230, 230, 230);
    padding: 32px 0;
    position: fixed;/*固定したい時*/
    width: 100%;
    z-index: 10;/*重なりの順番*/
}
.page-header > .inner {
    width: 950px;
    padding: 8px 10px;
    margin: auto;
}
site-logo {
    float: left;
    line-height: 1;
}

/* Page main */
.page-main {
    margin: auto;
    padding: 103px 10px;
    width: 950px;
}


/*!
 * Gallery
 */

.gallery {
    margin: 0;
    padding: 0;
}

.gallery-item {
    list-style: none;
    margin-top: 10px;
}
.gallery-item.is-loading {
    opacity: 0;
}
.gallery-item a {
    display: block;
}
.gallery-item .caption {
    display: none;
}

/* フィルター */
.filter-form {
    float: right;
}
.filter-form label {
    cursor: pointer;
    display: inline-block;
    font-weight: bold;
    margin-left: 1em;
    padding: 0 0.25em;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    /*要素の内容を範囲選択できないようにします*/
        user-select: none;
}
.filter-form label.ui-state-focus {
    /*境界線を1ピクセルの点線にする*/
    outline: 5px dotted #4c0be2;
}
.filter-form label .ui-icon {
    background: url(../img/sprites.png) no-repeat 0 0;
    display: inline-block;
    height: 17px;
    margin-right: 0.5em;
    margin-top: 2px;
    width: 17px;
    vertical-align: top;
}
.filter-form label.ui-state-active .ui-icon {
    background-position: -20px 0;
}

/* 追加読み込みボタン */
.load-more {
    background-color: rgb(255, 255, 255);
    border: 1px solid rgb(230, 230, 230);
    display: block;
    padding: 1em 0;
    width: 100%;
    margin-top: 10px;
}

/* jQuery UI helper */
.ui-helper-hidden-accessible {
    border: 0;
/*要素の切り抜き領域を指定するプロパティ
    clip:要素を切り抜いて可視化する範囲を指定する*/
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
/*要素のボックスからはみ出た部分を隠したり、スクロールできる状態する役割を担う便利なプロパティ*/
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}

【dataフォルダー】
content.jsonファイルにコードを書く
[
  {
    "title": "February Stars",
    "category": "animals",
    "images": {
      "thumb": "img/thumb-2-8.jpg",
      "large": "img/large-2-8.jpg"
    },
    "date": "2012-01-01"
  },
  {
    "title": "Sweet Baby James",
    "category": "animals",
    "images": {
      "thumb": "img/thumb-2-4.jpg",
      "large": "img/large-2-4.jpg"
    },
    "date": "2012-01-02"
  },
省略
・・・・
 {
    "title": "Diamond",
    "category": "architects",
    "images": {
      "thumb": "img/thumb-5-18.jpg",
      "large": "img/large-5-18.jpg"
    },
    "date": "2012-04-07"
  }
]
【CSSフォルダー】
・main.cssファイルにコードを書く
@charset "UTF-8";

/* Base */
html {
     "Helvetica Neue", "Arial", "Hiragino Kagu Gothic ProN", "Meiryo",
      sans-serif;
      font-size: 14px;
      line-height: 1.5;
     }
body {
     background-color: rgb(245, 245, 245);
     color: rgb(0, 0, 0);
    }
h1 { font-size: 100%; margin: 0; }
img { vertical-align: middle; }
.clearfix:before, .clearfix:after { content: " "; display: table; }
.clearfix:after { clear: both; }


/* Page header */
.page-header {
    background-color: rgb(255, 255, 255);
    border-bottom: 1px solid rgb(230, 230, 230);
    padding: 32px 0;
    position: fixed;
    width: 100%;
    z-index: 10;
}
.page-header > .inner {
    width: 950px;
    padding: 8px 10px;
    margin: auto;
}
site-logo {
    float: left;
    line-height: 1;
}

/* Page main */
.page-main {
    margin: auto;
    padding: 103px 10px;
    width: 950px;
}


/*!
 * Gallery
 */

.gallery {
    margin: 0;
    padding: 0;
}

.gallery-item {
    list-style: none;
    margin-top: 10px;
}
.gallery-item.is-loading {
    opacity: 0;
}
.gallery-item a {
    display: block;
}
.gallery-item .caption {
    display: none;
}

/* フィルター */
.filter-form {
    float: right;
}
.filter-form label {
    cursor: pointer;
    display: inline-block;
    font-weight: bold;
    margin-left: 1em;
    padding: 0 0.25em;
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
}
.filter-form label.ui-state-focus {
    outline: 1px dotted;
}
.filter-form label .ui-icon {
    background: url(../img/sprites.png) no-repeat 0 0;
    display: inline-block;
    height: 17px;
    margin-right: 0.5em;
    margin-top: 2px;
    width: 17px;
    vertical-align: top;
}
.filter-form label.ui-state-active .ui-icon {
    background-position: -20px 0;
}

/* 追加読み込みボタン */
.load-more {
    background-color: rgb(255, 255, 255);
    border: 1px solid rgb(230, 230, 230);
    display: block;
    padding: 1em 0;
    width: 100%;
    margin-top: 10px;
}

/* jQuery UI helper */
.ui-helper-hidden-accessible {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}
【JSフォルダ】
main.jsファイルにコードを書く
$(function () {

    /*
     * ギャラリー
     */
    $('#gallery').each(function () {

        var $container = $(this),
            $loadMoreButton = $('#load-more'), // 追加ボタン
            $filter = $('#gallery-filter'),    // フィルタリングのフォーム
            addItemCount = 16,                 // 一度に表示するアイテム数
            added = 0,                        // 表示済みのアイテム数
            allData = [],                      // すべての JSON データ
            filteredData = [];                 // フィルタリングされた JSON データ

        $container.masonry({
            columnWidth: 230,
            gutter: 10,
            itemSelector: '.gallery-item'
        });

        // JSON を取得し、initGallery 関数を実行
        $.getJSON('./data/content.json', initGallery);

        // ギャラリーを初期化する
        function initGallery (data) {

            // 取得した JSON データを格納
            allData = data;

            // 最初の状態ではフィルタリングせず、そのまま全データを渡す
            filteredData = allData;

            // 最初のアイテムを表示
            addItems();

            // 追加ボタンがクリックされたら追加で表示
            $loadMoreButton.on('click', addItems);

            // フィルターのラジオボタンが変更されたらフィルタリングを実行
            $filter.on('change', 'input[type="radio"]', filterItems);
        }

        // アイテムを生成しドキュメントに挿入する
        function addItems (filter) {

            var elements = [],
                // 追加するデータの配列
                slicedData = filteredData.slice(added, added + addItemCount);

            // slicedData の要素ごとに DOM 要素を生成
            $.each(slicedData, function (i, item) {
                var itemHTML =
                        '
                            '' +
                                '' +
                                '' +
                                    '' +
                                        '' + item.title + '' +
                                        '
                                            item.date.replace(/-0?/g, '/') +
                                        '' +
                                    '' +
                                '' +
                            '' +
                        '';
                elements.push($(itemHTML).get(0));
            });

            // DOM 要素の配列をコンテナーに挿入し、Masonry レイアウトを実行
            $container
                .append(elements)
                .imagesLoaded(function () {
                    $(elements).removeClass('is-loading');
                    $container.masonry('appended', elements);

                    // フィルタリング時は再配置
                    if (filter) {
                        $container.masonry();
                    }
                });

            // 追加済みアイテム数の更新
            added += slicedData.length;

            // JSON データがすべて追加し終わっていたら追加ボタンを消す
            if (added < filteredData.length) {
                $loadMoreButton.show();
            } else {
                $loadMoreButton.hide();
            }
        }

        // アイテムをフィルタリングする
        function filterItems () {
            var key = $(this).val(), // チェックされたラジオボタンの value

                // 追加済みの Masonry アイテム
                masonryItems = $container.masonry('getItemElements');

            // Masonry アイテムを削除
            $container.masonry('remove', masonryItems);

            // フィルタリング済みアイテムのデータをリセットと
            // 追加済みアイテム数をリセット
            filteredData = [];
            added = 0;

            if (key === 'all') {
                // all がクリックされた場合、すべての JSON データを格納
                filteredData = allData;
            } else {
                // all 以外の場合、キーと一致するデータを抽出
                filteredData = $.grep(allData, function (item) {
                    return item.category === key;
                });
            }

            // アイテムを追加
            addItems(true);
        }
    });

    // jQuery UI Button
    $('.filter-form input[type="radio"]').button({
        icons: {
            primary: 'icon-radio'
        }
    });

    // Resize page header
    $('.page-header').each(function () {
        var $header = $(this),
            headerHeight = $header.outerHeight(),
            headerPaddingTop = parseInt($header.css('paddingTop'), 10),
            headerPaddingBottom = parseInt($header.css('paddingBottom'), 10);
        $(window).on('scroll', $.throttle(1000 / 60, function () {
            var scroll = $(this).scrollTop(),
                styles = {};
            if (scroll > 0) {
                if (scroll < headerHeight) {
                    styles = {
                        paddingTop: headerPaddingTop - scroll / 2,
                        paddingBottom: headerPaddingBottom - scroll / 2
                    };
                } else {
                    styles = {
                        paddingTop: 0,
                        paddingBottom: 0
                    };
                }
            } else {
                styles = {
                    paddingTop: '',
                    paddingBottom: ''
                }
            }
            $header.css(styles);
        }));
    });

});
【imgフォルダ】
一部を表示


こんなもん、詳しくは
jQuery 最高の教科書で




 









 

 


コメント (1)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« jQuery----ギャラリーページ... | トップ | jQuery入門--選択画面の拡大... »
最新の画像もっと見る

1 コメント(10/1 コメント投稿終了予定)

コメント日が  古い順  |   新しい順
Unknown (みゆきん)
2025-06-25 16:38:56
ハテナにするつもりで練習してます
でもバナーがなかなか貼れなくて(涙)
教えて~
返信する

コメントを投稿

サービス終了に伴い、10月1日にコメント投稿機能を終了させていただく予定です。

jQuery」カテゴリの最新記事