Parlons du principe général, commençons par la photo :
Description de la fonction :
Plan de mise en œuvre technique :
Commençons par trier le processus, du chargement à l'affichage :
1. Charger les données
2. Épissez le HTML et écrivez-le sur la page
3. Vérifiez si tous les img du HTML qui viennent d'être écrits ont été chargés. Si c'est le cas, passez à 5, sinon passez à 4
.
4. Attendez que l'image se charge
5. Calculez la position de chaque élément
Le plus gros casse-tête au début était de savoir comment le positionner. Plus tard, après les conseils d'un ami, je l'ai finalement résolu : calculer le nombre total de colonnes d'images et mettre la hauteur de chaque colonne dans un tableau. Chaque fois qu'une image est chargée, recherchez la plus petite valeur du tableau et définissez le haut de l'image actuelle sur cette valeur. Une fois terminé, ajoutez la hauteur de l'image à la plus petite valeur du tableau et renvoyez-la au tableau. en séquence.
PS : Comme il y a trop de codes pour cette fonction, nous ne pouvons faire qu'une simple décomposition basique du code :
// 创建用于记录每列高度的数组 _getLowestCol: function() { t._cols = new Array(5),min = 0; // 初始化为0 for (var i = 0; i < t._cols.length; i++) { if (cols[i] < cols[min]) { min = i; } return min; } }, _reposition: function() { t._grids.each(function(i, grid) { //先显示出来 grid = $(grid).show(); var height = grid.outerHeight(), min = t._getLowestCol(); // 定位 grid.animate({ left: (t._colWidth + t._colSpacing) * min, top: t._cols[min], opacity: 1 },1000); // 记录高度 t._cols[min] += height; }); }
La deuxième difficulté rencontrée lors du processus de développement est la suivante : comme le montre l'image ci-dessus, déplacer la souris vers la barre de menu nécessite de changer de liste d'images, et un flux en cascade est nécessaire pour charger différents types de données. Par conséquent, nous devons déterminer comment exécuter l'interface de demande de code une seule fois pour chaque page lors du changement de page, au lieu de redemander l'interface de données à chaque fois que la page est changée, et effectuer uniquement l'opération de changement d'affichage de l'image. liste.
Étant donné que chaque menu a un attribut personnalisé, ce problème est facilement résolu : créez un objet pour enregistrer si le menu actuel a exécuté du code, et sinon, exécutez les données de la requête.
var isLoad = {};//是否载入过 labelType.mouseover(function() { var i = $(this).index(); var api = _this.attr('api');//接口标识 if(! isLoad[ api ]){ isLoad[ api ] = i; loadData(wrapper, api); } });
Ce qui suit est le code complet :
html :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <style type="text/css"> *{margin:0;padding:0;} ul,li{ list-style-type:none;} li img{width:100%;list-style:none;} </style> </head> <body> <div class="photo_box"> <ul id="container" style="border:1px solid #000;width:80%;height:600px;overflow:hidden;margin:0 auto;position: relative;"> </ul> <div id="loading" class="loading" style="text-align: center;margin-top: 20px;font-size: 1.2em;">加载中...</div> <div id="more" class="more"style="text-align: center;margin-top: 20px;font-size: 1.2em;"><input type="button" value="更 多" id="clear" /></div> </div> <script type="text/javascript" src="../../lib/seajs/sea.js"></script> <script type="text/javascript" src="../../lib/base/1.0.x/base.js"></script> <script type="text/javascript"> seajs.use(['lib/jquery/1.11.x/index.js', '_example/waterFall_1.1/waterfall.js'], function($, waterFall) { waterFall.init({ container: $('#container'), dataURL: 'http://www.woxiu.com/index.php?action=Index/Main&do=ApiZhuboGrade', dataType: 'jsonp', template: '<% for (var i = 0; i < data.length; i++) { %>' + '<li style="display: none;">' + '<img src=" <%-data[i].room_img%> ">' + '</li>' + '<% } %>', colWidth: 200, colSpacing: 10, rowSpacing: 15, page: 1, pageEnd: 8, }); // 限制同时展示的页数 var loadCounter = 1; function pageNum(){ if (loadCounter >= 3) { $('#more').show(); $('#loading').hide(); return true; } else { loadCounter++; $('#more').hide(); $('#loading').show(); } return false; } $('#clear').click(function() { loadCounter = 1; waterFall._loadNext(); }); }); </script> </body>
js :
/** * 瀑布流布局组件类 * @param {Object} options 组件设置 * @param {NodeList} options.container 瀑布流容器 * @param {String} options.dataURL 数据地址 * @param {String} [options.dataType='jsonp'] 数据类型,json或jsonp * @param {String} options.template 模板编辑 * @param {Number} [options.colWidth] 图片大小。 * @param {Number} [options.colSpacing] 列间隔。 * @param {Number} [options.rowSpacing] 行间隔。 * @param {Number} [options.page=1] 数据开始页码 * @param {Number} [options.pageEnd] 数据末尾页码 * @pageNum() 函数,如果不需要现在加载也是,需要把函数里面的判断去掉。 从加载到显示的流程 1. 加载数据 2. 拼接HTML写入到页面 3. 检查刚刚写入的HTML中的img是否全部加载完成,如果是,进入5、否则进入4 4. 等待图片加载完成 5. 计算每个元素的位置 */ define(function(require, exports, module) { 'use strict'; var Tmpl = require('lib/tmpl/2.1.x/index.js'), $ = require('lib/jquery/1.11.x/index.js'); var waterFall = { init: function(options) { var t = this; t._container = options.container; t._template = options.template; t._colWidth = options.colWidth; t._colSpacing = options.colSpacing; t._rowSpacing = options.rowSpacing; t.dataURL = options.dataURL; t.dataType = options.dataType; t.page = options.page; t.pageEnd = options.pageEnd; t._switch = false; //计算有几列 总宽度 / (列宽 + 列间隔) t._totalCols = parseInt(t._container.width() / (t._colWidth + t._colSpacing)); // 创建用于记录每列高度的数组 t._cols = new Array(t._totalCols); // 初始化为0 for (var i = 0; i < t._cols.length; i++) { t._cols[i] = 0; } t._loadingPage = options.page || 0; t._loadNext(options); //下拉滚动条加载 var lastTime = new Date().getTime(); $(window).scroll(function() { if ( !t._switch ) { //判断是否滚动过快,在ie下 var thisTime = new Date().getTime(); if (thisTime - lastTime < 50) { console.log(thisTime - lastTime); lastTime = thisTime; return; } if ($(window).scrollTop() + $(window).height() >= document.documentElement.scrollHeight) { lastTime = thisTime; t._loadNext(); } } }); }, //加载器 _loadNext: function(t) { var t = this; t._switch = true; //请求数据 if (!t.trigger) { $.ajax({ url: t.dataURL, data: { page: ++t._loadingPage }, dataType:t.dataType, success: function(response){ t.trigger = t._completeLoading(response); }, error:function(){console.log('Error! 请求有误');} }); } return false; }, //加载完数据调用此函数 _completeLoading: function(result) { var t = this; if (t._loadingPage >= t.pageEnd) { $('#more').hide(); $('#loading').html('<p>已是最后一页了喔 ^_^ ^_^</p>'); return true; } else { //if (!pageNum()) { t._add(result); //}; } return false; }, //添加格子 _add: function(result) { var t = this, grids = ''; //调用模板 var content = Tmpl.render(t._template, {data:result.data}); //原始定位 t._grids = $(content).css({ position: 'absolute', left: t._container.width(), top: t._container.height(), width: t._colWidth, opacity: 0 }); //把Html添加到容器 t._container.append(t._grids); // 执行一次_reposition,如果所有图片都加载完成,该方法返回true,否则返回false if ( !t._reposition() ) { // 有图片未加载完,监听onload和onerror t._grids.find('img').bind('load error', function() { this.loaded = true; // 有图片加载完成,再次执行_reposition if (t._grids) { t._reposition(); } }); } }, // 此方法用于获取高度最低的列 _getLowestCol: function() { var cols = this._cols, min = 0; for (var i = 1; i < cols.length; i++) { if (cols[i] < cols[min]) { min = i; } } return min; }, //定位 _reposition: function() { var t = this, allImgsLoaded = true; // 检测图片是否全部加载完成 t._grids.find('img').each(function(i, img) { if (!img.loaded && !img.complete) { allImgsLoaded = false; } return allImgsLoaded; }); if (allImgsLoaded) { t._grids.each(function(i, grid) { //先显示出来 grid = $(grid).show(); var height = grid.outerHeight(), min = t._getLowestCol(); // 非第一行的时候,要加上行间隔 if (t._cols[min]) { t._cols[min] += t._rowSpacing; } // 定位 grid.animate({ left: (t._colWidth + t._colSpacing) * min, top: t._cols[min], opacity: 1 },1000); // 记录高度 t._cols[min] += height; }); // 重设外层容器高度为最高列高度 t._container.css( 'height', Math.max.apply(Math, t._cols) ); t._switch = false; delete t._grids; } return allImgsLoaded; }, } return waterFall; });
Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à tout le monde dans l'apprentissage de la programmation javascript.