ウォーターフォールレイアウト+ダイナミックレンダリングの実装

ウォーターフォールレイアウト+ダイナミックレンダリングの実装

典型的なウォーターフォールウェブサイト

華班ドットコム、ドゥイタン

ウォーターフォールフローレイアウトの原則

一般的な考え方

まず、ページレイアウトの特徴は、幅は同じで長さが異なることです。

このことから、この種のレイアウトには絶対的な配置の考え方が必要であることがわかります。

上記の 5 つは通常の順序で並べられており、6 番目以降は追加する最も短いものを見つける必要があります。

最短の列を取得するにはどうすればよいでしょうか?

最初のボックスを見つけるのが最も簡単です。他のボックスの高さをそれぞれ取得し、最も短いボックスを見つけて、その最も短いボックスの位置を見つけることができます。

新しく追加されたボックスの位置は次のとおりです。

  • left: 最短ボックスのインデックス * (ボックスの幅 + 左右の間隔)
  • 上: このボックスの高さ + 上下の間隔

挿入後、この列の高さの変化を記録して新しい高さを生成し、次のラウンドの高さの比較を実行します。等々。

waterfuljqueryをベースにしたコンポーネントです。

具体的なアイデア

最外辺の左右には間隔がないので、 5列の場合は4間隔ができます。したがって、 widthが一定の場合、間隔spaceの幅は次のように計算できます。

間隔

var スペース = (wParent - 5 * 幅) / (col - 1);
// wParent は親ボックスの幅、width は子ボックスの幅、col は列数です

最初の行のボックスの配置:

  • トップ : 0
  • 左: インデックス * (幅 + スペース)

2 行目のボックスの配置:

  • 上: minHeight + スペース
  • 左: インデックス * (幅 + スペース)

したがって、 5列の高さは配列で表され、最も短い要素とその現在のインデックスが見つかります。

プラグインのパッケージ

ウォーターフォールレイアウトは最初の読み込みとn読み込みの両方に必要だからです。したがって、ウォーターフォール フロー レイアウト メソッドをプラグインにカプセル化することで、コードの再利用が可能になります。 まずウォーターフォールフローのhtmlレイアウトを理解する

<!--ページ コンテナー-->
<div クラス = "コンテナ">
      <!-- 上からの距離を持つすべてのアイテムのコレクション -->
      <div クラス = "items">
             <!--それぞれの小さなブロックには画像とテキストが含まれています-->
              <div クラス = "item">
                    <画像ソース = "" />
                    <p>こんにちは</p>
              </div>

              <div クラス = "item">
                    <画像ソース = "" />
                    <p>こんにちは</p>
              </div>
      </div>
</div>
<div class = "btn">読み込み中...</div>

jqueryプラグインをカプセル化しましょう

最初のステップ

jqueryのグローバル変数をローカル変数に変換します。

クロージャを形成することで、グローバル汚染を防ぎ、パフォーマンスを向上させます。クロージャで定義された変数は、外部変数に影響を与えません。

/*自己呼び出しはクロージャを形成します*/
(関数($){
/*jQueryを追加しない場合は、使用される$はグローバル変数であり、追加後はメンバー変数が使用されます*/

})(jQuery);

ステップ2

jquery.fn.extend(オブジェクト)

jqueryfn関数

サードパーティのメソッドのエントリ ポイントを提供し、 jquery要素セット ( $を使用して取得できる要素) を拡張して新しいメソッド (通常はプラグインの作成に使用) を提供します。

/*js/jquery-waterfall.js*/
(関数($){
     $.fn.waterfall = 関数(){
        /*これは現在このメソッドを呼び出している要素セットを参照します (要素セットは jQuery によって取得された疑似配列です)*/
         console.log(これを);
     }
})(jQuery);

ステップ3

最初の行を配置する

(関数($){
    $.fn.waterfall = 関数(){
    // this は現在このメソッドを呼び出している要素セットを参照します // 現在のウォーターフォールの親コンテナー var items = $(this);
        //親コンテナの幅 var wParent = items.width();
        //現在のウォーターフォール サブコンテナ var child = items.children();
        //子コンテナの幅を取得します。var width = child.width();
        //列がいくつあるか想定します var col = 5;
        //間隔を計算します(親要素の幅からすべてのボックスの幅を引いた値 / 4)
        var スペース = (wParent - 列 * 幅) / (列 - 1);

        //各列の高さを記録する配列 var colHeightArr = [];

        //各子要素を走査します$.each(child,function(i,item){
            var $item = $(item);
            var 高さ = $item.height();

            // 位置を設定する // 最初の行の要素はすべて上部にあるため、インデックスは 0 から始まり、5 未満の場合は上部になります if (i < col ) {
                $item.css({
                    上: 0,
                    左:i * (幅 + スペース)  
                });
               //配列に高さを追加します colHeightArr[i] = height;
                //colHeightArr.push(height); も使用できます。
            }
            //その他は最も短い列に従って配置する必要があります});
    }
})(jQuery);

これで効果を確認できます ( 13ボックスがシミュレートされたため、残りのボックスは積み重ねられました)

今回は次の高さの配列を出力します。

最初の5の高さが配列に格納されていることがわかります。配列内の最小の数字は289であり、 289に対応する配列のインデックスがその列のインデックスであることが分かります。

ステップ4

残りの行を配置します。最も小さいものを見つけて追加し、この列の高さを増やします。等々。 最大のitems最大の高さに等しくなります。これにより、次の読み込みを一番下に移動できるようになります。

(関数($){
    $.fn.waterfall = 関数(){
    // this は現在このメソッドを呼び出している要素セットを参照します // 現在のウォーターフォールの親コンテナー var items = $(this);
        //親コンテナの幅 var wParent = items.width();
        //現在のウォーターフォール サブコンテナ var child = items.children();
        //子コンテナの幅を取得します。var width = child.width();
        //列がいくつあるか想定します var col = 5;
        //間隔を計算します var space = (wParent - col * width) / (col - 1);

        //各列の高さを記録する配列 var colHeightArr = [];

        //各子要素を走査します$.each(child,function(i,item){
            var $item = $(item);
            var 高さ = $item.height();

            // 配置 // 最初の行の要素はすべて上部にあります // インデックスは 0 から始まり、5 未満の場合はすべて上部にあります if (i < col ) {
                $item.css({
                    上: 0,
                    左:i * (幅 + スペース)
                });

                //colHeightArr[i] = 高さ;
                colHeightArr.push(高さ);
   
             //その他は最短の列に従って並べます}else{    
                // 並べ替える最短の列を見つける// インデックス var index = 0;
                // 最小の高さは最初のインデックスに対応する高さであると仮定します var minHeight = colHeightArr[index];
                //配列を走査して最小値と最小値に対応するインデックスを見つけます //k はインデックス、v は値です $.each(colHeightArr,function(k,v){
                    最小高さがvより大きい場合
                        インデックス = k;
                        最小高さ = v;
                    }
                });

                //$item.css({ を検索します
                    上:最小高さ + スペース、
                    左:インデックス * (幅 + スペース)
                })

                //現在の配列の最小の高さを新しい高さに更新します。colHeightArr[index] = minHeight + space + height;
            }
            //console.log(列の高さArr);
        });

        //親コンテナの高さを設定します。var maxHeight = colHeightArr[0];
        $.each(colHeightArr,function(k,v){
            最大高さ<vの場合{
                最大高さ = v;
            }
        });
        //親コンテナの最大の高さを設定します items.height(maxHeight);
    }
})(jQuery);

効果画像:

ステップ5

htmlで呼び出されます(上記のエフェクト画像が呼び出されています)

$(".items").滝();

ただし、画像がある場合、ネットワークが遅いときにこのような呼び出しを行うと問題が発生します。画像を読み込む前に配置しておくと、中央の画像が読み込まれたときにボックスが重なり合ってしまいます。

解決:

/*ページ上のすべてのリソースが読み込まれた後、レイアウトが実行されます。そうしないと、画像のサイズを取得できず、ボックスの高さを拡張できません*/
window.onload = 関数(){
  $(".items").滝();
}

// なぜ jQuery を使わないのでしょうか? このメソッドは DOM 要素がダウンロードされた後に読み込まれるためです。配置する前に、すべてのリソースが読み込まれるまで待つ必要があります。/*   
$(関数(){
	//console.log('dom がロードされました');
});    
*/

ダイナミックレンダリング

データ量が多いため、バッチでレンダリングされます。

概略図:

インターフェースドキュメント:

インターフェースの説明: ウォーターフォール ページング データ

インターフェースアドレス: data.php

リクエストメソッド: get

インターフェースパラメータ: ページ 現在のページ

pageSize 現在のページに表示する項目の数

戻り値の型: json

返されるデータ:

{ ページ:2、アイテム:[{パス:"./images/1.jpg",テキスト:'''},...] }

page 次のページのページ番号(ページ番号に応じて次のページのデータを取得します)

itemsは現在のページのデータを返します

パス画像アドレス

文章

次はシェルを準備します

<div class="コンテナ">
    <div class="items">
        <!--TODO データをレンダリングする必要がある場所-->
    </div>
    <div class="btn loading">読み込み中...</div>
</div>

需要分析

最初のページを読み込むとき

1. 最初のページのデータをロードするajax
2. ボタンは「さらに読み込む」として表示される必要があります
3. 読み込みが完了し、artTemplateページにレンダリングされます。
4. ウォーターフォールレイアウトに初期化する

次のページを読み込むとき

1. データの読み込み

  • 手動読み込み: ボタンをクリックして次のページのデータを読み込みます
  • 自動読み込み: 一番下までスクロールすると次のページが自動的に読み込まれます

2. ボタンには“正在加載中...”と表示され、重複送信を防ぐためクリックできないようにする必要があります。
3. 読み込みが完了し、ページにレンダリングされます
4. ウォーターフォールレイアウトに初期化する
5. ボタンは読み込み中として表示される必要があります。データがない場合は、ボタンを無効にして“沒有更多數據了”と表示します。

最初のページのデータをレンダリングする

リクエストを送信

ページの読み込み時には、データの読み込み、ページのレンダリング、ウォーターフォール フローの初期化がすべて必要なので、これら 3 つの関数を 1 つの関数にカプセル化し、最初の関数を最初に実装します。

$(関数(){
        // 動的なウォーターフォールレンダリングを実現する // レンダリング var render = function(){
            // ページのウォーターフォールレイアウトをレンダリングするためにデータを読み込みます $.ajax({
                タイプ: 'get',
                url:'data.php',
                データ:{
                    //最初のページ page:1,
                    //1ページあたり10項目 pageSize:10
                },
                データ型: 'json',
                成功:関数(データ){
                    コンソールにログ出力します。
                }
            });
        }

        与える();
    });

得られたデータは図の通りです。

ページのレンダリング

テンプレートを準備する

<script type="text/template" id="テンプレート">
    <% for(var i=0; i<items.length; i++){ %>
        <div class="item">
            <img src="<%=items[i].path%>" alt="">
            <p><%=items[i].text%></p>
        </div>
    <% } %>
</スクリプト>

<スクリプト>
  $(関数(){
    //操作する必要があるDOMを取得します
    var $items = $(".items");
    var $btn = $(".btn");
    // レンダリング var render = function(){
        // ページウォーターフォールレイアウトをレンダリングするためにデータを読み込みます $.ajax({
            タイプ: 'get',
            url:'data.php',
            データ:{
                ページ:1,
                ページサイズ:10
            },
            データ型: 'json',
            成功:関数(データ){
                コンソールにログ出力します。
                $items.append(テンプレート('テンプレート',データ));
                //ウォーターフォールレイアウト $items.waterfall();
                //ボタンを変更 $btn.removeClass('loading').html('さらに読み込む');
            }
        });
    }
    
    与える();
  });
</スクリプト>

2ページ目のレンダリング(手動読み込み)

2 ページ目で変更する必要がある点:

  • ボタンクリック イベントを追加し、ボタンをクリックした後にレンダリングします。
  • ボタンをクリックして読み込むときは、ボタンをロックする必要があります。ロックしないと、ボタンが読み込み状態にあるかどうかを判断するために複数の Ajax リクエストが送信されるためです。読み込み状態にある場合、データはレンダリングされません。
  • レンダリング関数では、ボタンの状態が変化すると、カスタム プロパティを使用して次のページで取得するページ数を記録します。 data() を使用し、その中にページを渡し、その中に data.page を配置します。したがって、データを取得するときは、ボタンのデータからページ値を取得する必要があります。最初は空なので、デフォルト値を1に設定します。
  • レンダリング関数では、データが正常に読み込まれる前はボタンはまだ読み込み中の状態なので、読み込み中の状態を含む beforeSend 関数を追加します。
  • レンダリング関数では、レンダリング時にデータがないかどうかを判断します。これは、返された配列の長さがゼロかどうかで判断します。ゼロの場合は、それ以上データがないことを意味します。
 $(関数(){
    //操作する必要があるDOMを取得します
    var $items = $(".items");
    var $btn = $(".btn");

    // レンダリング var render = function(){
        // ページウォーターフォールレイアウトをレンダリングするためにデータを読み込みます $.ajax({
            タイプ: 'get',
            url:'data.php',
            データ:{
                //次のページのページ番号を取得します。ページ番号がない場合、デフォルトは 1 です。
                ページ:$btn.data("ページ")||1,
                //1ページあたり10項目 pageSize:10
            },
            beforeSend:関数(){
                $btn.addClass("loading").html('読み込み中...');
            },
            データ型: 'json',
            成功:関数(データ){
                コンソールにログ出力します。
                //テンプレートを準備する//追加なのでhtmlは使えません。appendを使う必要があります
                        //データを直接使用する理由は、データが元々配列ではなく、多くの属性を持つオブジェクトだからです。データには長さという 1 つの属性しかないため、配列ではこれは不可能です。$items.append(template('template',data));
                //ウォーターフォールレイアウト $items.waterfall();

                if (データ項目の長さ) {
                    //変更ボタン//データはカスタム属性であり、データから送信されたページはカスタム属性に保存されます。
                    $btn.data("page",data.page).removeClass('loading').html('さらに読み込む');
                }それ以外{
                    //これ以上データはありません//データがなくなったことを確認するには、items 配列の長さがゼロである最後のオブジェクトを開きます$btn.addClass("loading").html("これ以上データはありません");
                }
            }
        });
    }

    //ボタンの読み込み $btn.on('click',function(){
        //複数のAjaxリクエストの送信を避け、判断のみを行い、読み込み状態であれば終了し、
        if($btn.hasClass("ロード中")){
            false を返します。
        }
        与える();
    })

    与える();
});

2ページ目のレンダリング(スクロール読み込み)

スクロールレンダリングの場合、レンダリングされたページがブラウザの下部から一定の距離にあるときに次のリクエストを行う必要があるため、判断が必要になります。

概略図:

bottom < 200px ajaxリクエストを作成します。

bottomを計算するには?

下部 = アイテムの高さ + 上部からのアイテムの距離 - 上向きのカールの高さ - ブラウザ全体の高さ

 $(関数(){
    //動的なウォーターフォールレンダリングを実現する//操作が必要なDOMを取得する
    var $items = $(".items");
    var $btn = $(".btn");

    // レンダリング var render = function(){
        // ページのウォーターフォールレイアウトをレンダリングするためにデータを読み込みます $.ajax({
            タイプ: 'get',
            url:'data.php',
            データ:{
                ページ:$btn.data("ページ")||1,   
                ページサイズ:10
            },
            beforeSend:関数(){
                $btn.addClass("loading").html('読み込み中...');
            },
            データ型: 'json',
            成功:関数(データ){
                コンソールにログ出力します。
                $items.append(テンプレート('テンプレート',データ));
                //ウォーターフォールレイアウト $items.waterfall();

                //配列にデータがあるかどうかを判断します if(data.items.length){
                 $btn.data("page",data.page).removeClass("loading").html('さらに読み込む');
                }それ以外{
                    $btn.addClass("loading").html("これ以上データはありません");
                }
            }
        });
    }

    //スクロール読み込み $(window).on('scroll',function(){
        // ドキュメントを読み込むには、下端から 200 ピクセル未満である必要があります // 読み込みが完了したら読み込みを続行できます // 項目の高さ var itemsHeight = $items.height();
        // 上からのアイテムのオフセット var itemsTop = $items.offset().top;
        // カール上部からページ全体の距離 var scrollTop = $(document).scrollTop();
        // ブラウザの高さ var winHeight = $(window).height();
        // ブラウザの下部と項目の下部の間の距離 var bottom = itemsHeight + itemsTop - scrollTop -winHeight;
        // ボタンが読み込み状態にあるかどうかを判断します var loading = $btn.hasClass("loading");

        //ボタンが200未満で読み込み状態でない場合は、読み込みを開始します。if(bottom < 200 && !loading){
            与える();
        }
    })

    与える();
});

特別な注意が必要な問題

以前は、ページを静的に読み込むときにwindow.onloadを使用して、ページ上のすべてのリソースが読み込まれた後にページをレンダリングしていました。そうしないと、ページの重複が発生します。

ページを動的に読み込むときは、まず背景データを取得し、それをhtmlに変換してページに追加してから、 imgイメージの読み込みを開始します。ここでも以前と同じ問題が発生しました。

後でwindow.onloadが使用されなかった理由は、元の画像がすでに特定の幅と高さに設定されているためです。一部のimg250pxに設定されており、一部は450pxに設定されています。 しかし、一部の画像が変形してしまうため、これは合理的ではありません。

この問題の解決策は次のとおりです。

  1. ページをレンダリングする前にすべての画像が読み込まれるまで待機しますが、これには長い時間がかかり、不合理です。
  2. 参照花びら

花びらの幅と高さも写真を読み込むときに設定されますが、サイズは元の写真のサイズに合わせて拡大縮小する必要があります。

元のサイズは608で、現在の幅は200なので、現在の高さは変換されます。

現在の高さ = 200 / 806 * 782

widthは現在の幅です

//テンプレートエンジンに記述 <img height = "<%=items[i].width * items[i].height / width%>" src = "<%=items[i].path%>" />
/*  
同様に、Ajaxの成功では、$items.append(
    テンプレート('テンプレート',{
        データ:データ、
        幅:幅
    })
);
この方法では幅変数を使用できます。
*/

これでウォーターフォールフローが完成します。

ウォーターフォールレイアウト+ダイナミックレンダリングの実装に関するこの記事はこれで終わりです。ウォーターフォールレイアウトに関するより関連性の高いコンテンツについては、123WORDPRESS.COMの過去の記事を検索するか、以下の関連記事を引き続き閲覧してください。今後とも123WORDPRESS.COMをよろしくお願いいたします。

<<:  js を使用して過去 1 週間、1 か月、3 か月の時間を取得する簡単な例

>>:  CentOS7 で ethereum/Ethereum を最初からインストールする

推薦する

ユニアプリとミニプログラム(画像とテキスト)を下請けする方法を教えます

目次1. ミニプログラム下請け2. Uniapp 下請けアプレット下請けの手順: 1. manife...

TomcatはXMLを解析し、リフレクションを通じてオブジェクトを作成します。

次のサンプル コードでは、Tomcat が XML を解析し、リフレクションを通じてオブジェクトを作...

Tomcat パイプライン モードのパイプラインとバルブの詳細な説明

序文比較的複雑な大規模システムでは、複雑なロジックで処理する必要があるオブジェクトまたはデータ フロ...

Vueデータ監視の原理の詳細な説明

<本文> <div id="ルート"> <h1&...

TypescriptとAxiosに基づくインターフェースリクエスト管理の詳細な説明

目次アイデア傍受を要求するレスポンスインターセプションhttpClient.tsを使用してリクエスト...

nginxリバースプロキシを介したデバッグコードの実装

背景現在、会社のプロジェクトは、フロントエンドとバックエンドが分離された方法で開発されています。新し...

MySQL 2級コンピュータ試験共通テストポイント 8つのMySQLデータベース設計最適化方法

MySQLデータベース設計の8つの最適化方法の詳細は次のとおりです。 1. 最も適切なフィールド属性...

JavaScriptタイマーの詳細な説明

目次簡単な紹介間隔の設定説明するパラメータ戻り値使用法タイムアウトの設定説明するパラメータ使用法:タ...

VueはElementUIのフォームサンプルコードを模倣する

実装要件ElementUI を模倣したフォームは、インデックス コンポーネント、Form フォーム ...

Vueルーティングコンポーネントでパラメータを渡す8つの方法の詳細な説明

シングルページアプリケーションを開発する場合、特定のルートを入力し、パラメータに基づいてサーバーから...

CSS における zoom:1 属性の定義と機能

今日、CSS の zoom 属性は何のために使用されるのかと尋ねられました。この属性は、フローティン...

アニメーションとトランジションの違い

CSS3アニメーションとJSアニメーションの違いJSはフレームアニメーションを実装しますCSS3はト...

Vant+postcss-pxtoremはブラウザ適応機能を実装します

Remレイアウトの適応Vant のスタイルでは、デフォルトで px を単位として使用します。rem ...

NextCloud プライベート クラウド ストレージ ネットワーク ディスクの構築に関する詳細なチュートリアル

Nextcloud は、オープンソースで無料のプライベート クラウド ストレージ ネットワーク ディ...

Linux 上の MariaDB は root ユーザーで起動します (推奨)

最近、セキュリティ製品をテストする必要があったため、mariadb の起動ユーザーを root に調...