js 实现图片瀑布流效果,可更改配置参数 带完整版解析代码[waterFall.js]
前言:
本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽。
本篇文章为您分析一下原生JS实现图片瀑布流效果
页面需求
1. 图片之前拥有最小间隙
2. 图片可以根据浏览器窗口的改变而改变
3. 需要用到函数节流与函数防抖的知识
HTML结构
<div class="container"></div>
<script src="../../plugin/helpers.js"></script> <!--函数节流与防抖要引用, 此插件请查看我的第一篇博客JS函数的节流与防抖-->
<script src="../../plugin/waterfall.js"></script> <!--瀑布流代码-->
CSS 样式
无
JS 行为
JS大致思路
1. 根据用户传入的配置信息设置图片信息
2. 配置默认值
3. 设置页面的图片
4. 设置父级元素的定位信息
5. 设置每张图片的left、top值
<1>.计算一行有几张图片
定义一个数组,这个数组用来记录每一列下一张的top值
初始值为[0,0,0,n...]; 数组的每一项为0
<2>. 设置图片位置时
(1).得到数组中最小的值,设置top
(2).更新数组中该项的top值
(3).得到该项是数组中的第几项,用于计算该项的left值
5. 获得水平方向上的距离信息(一行排几张图、最小间隙)
6. 设置图片的left、top值
<script>
// 因为我本地有40张以img开头的所以我直接循环来获得。
var srcs = [];
for (var i =0;i <=40; i++ ){
srcs.push(`img/${i}.jpg`);
}
// 用户可以自行配置参数
myPlugin.createWaterFall({
minGap: 15, // 垂直方向的最小间隙
imgSrcs: srcs, // 图片的路径数组
imgWidth: 220, // 单张图片的宽度
container: document.querySelector(".container") // 需要渲染的容器
});
</script>
/**
* 第一步: 创建一个图片瀑布流
* @param {*} option 参数配置
*/
window.myPlugin.createWaterFall = function (option) {
// option默认值
var defaultOption = {
minGap: 10, // 图片最小间隙
imgSrcs: [], // 图片的路径数组
imgWidth: 220, // 单张图片的宽度
container: document.body // 需要渲染的容器,如果用户没有传,默认为body
}
// 第二步: 对象混合
var option = Object.assign({}, defaultOption, option);
// console.log(option);
var imgs = []; // 存放所有的图片dom对象。
}
createImg();
// setFatherPosition();
/**
* 第三步: 创建图片
*/
function createImg() {
for (var i = 0; i < option.imgSrc.length; i++) {
var img = document.createElement("img"); // 创建图片
img.src = option.imgSrc[i]; // 设置图片路径
img.style.width = option.imgWidth + "px";// 设置每张图片宽度
img.style.position = "absolute"; // 设置图片为绝对定位
imgs.push(img); // 添加到图片数组中
option.container.appendChild(img); // 添加图片到container中
}
}

/**
* 第四步: 处理父元素,因为图片都是绝对定位的,父元素必须是一个定位元素。
*/
function handleParent() {
var style = getComputedStyle(option.container); // 获取到父级的最终定位
if (style.position === "static") { // 如果父级没有定位 (为何要如此定位,因为万一父级有定位的情况下,我们要保证他不被影响)
option.container.style.position = "relative";// 设置父级为相对定位
}
}

那么,我们要知道一行内有多少张图?
还有他们之间的最小间隙
/**
* 第五步: 得到图片水平方向上的信息。
*/
function getHorizontalInfo() {
// 5.1 定义一个对象用来存储数据
var obj = {};
// 5.2 容器的宽度
obj.containerWidth = option.container.clientWidth;
// 5.3 计算一行有多少个图片
obj.number = (obj.containerWidth + option.minGap) / (option.imgWidth + option.minGap);
// 5.4 向下取整, 每行的图片只能少不能多。多了他会放不下
obj.number = Math.floor(obj.number);
// 5.5 重新计算每一个水平空隙
// 总宽度-图片的数量*图片的宽度=剩余空间
obj.gap = (obj.containerWidth - obj.number * option.imgWidth) / (obj.number - 1);
console.log(obj.gap);
return obj; // 返回这个对象
}
我们就来设置他们的top和left值
写一个setImgPosition函数
/**
* 第六步: 设置每一张图片的坐标
*/
function setImgPosition() {
// 6.1 获取水平方向信息保存到info变量中
var info = getHorizontalInfo();
// console.log(info);
// 第七步: 存放每一列下一张图片的top值
// 7.1 创建数组
var arr = new Array(info.number);
// 7.2 填充数组的每一项为0
arr.fill(0);
// 7.3 获取所有的图片
imgs.forEach(function (img) {
// 设置图片的坐标
// 7.4 找到数组里面的最小值
var minTop = Math.min.apply(null, arr);
// 7.5 图片的纵坐标
img.style.top = minTop + "px";
// 7.6 更新数组的top值(最小值拿的是数组的哪一项,找到对应的列编号。再更新)
var index = arr.indexOf(minTop);
// 设置数组当前这一项
// 图片当前的高度 + 垂直方向间隙
arr[index] += img.clientHeight + info.gap;
// 横坐标
img.style.left = index * (option.imgWidth + info.gap) + "px";
});
}
得到效果如下

所以应该是每一张图片加载完就给他重新设置高度
因此setImgPosition函数不能在外面调用,他应该在图片的事件中调用
img.onload = function () {
setImgPosition();
};

调用setImgPosition函数调用的就太频繁了
因此我们要使用函数防抖来限制他的频繁调用
在createImg函数中引用下面代码:

因此给container添加一个监听事件
// 窗口尺寸变化事件
var debounce = myPlugin.debounce(setImgPosition, 300, false);
window.onresize = function () {
debounce();
}
JS 行为
if (!window.myPlugin) {
window.myPlugin = {};
}
/**
* 第一步: 创建一个图片瀑布流
* @param {*} option 参数配置
*/
window.myPlugin.createWaterFall = function (option) {
// option默认值
var defaultOption = {
minGap: 10, // 图片最小间隙
imgSrcs: [], // 图片的路径数组
imgWidth: 220, // 单张图片的宽度
container: document.body // 需要渲染的容器
}
// 第二步: 对象混合
var option = Object.assign({}, defaultOption, option);
// console.log(option);
var imgs = []; // 存放所有的图片dom对象
// 处理父元素
handleParent();
// 3.1 创建图片
createImgs();
// 窗口尺寸变化事件
var debounce = myPlugin.debounce(setImgPosition, 300, false);
window.onresize = function () {
debounce();
}
/**
* 第五步: 设置每一张图片的坐标
*/
function setImgPosition() {
// 第七步: 获取水平方向信息
var info = getHorizontalInfo();
// console.log(info);
// 7.1 存放每一列下一张图片的top值
var arr = new Array(info.number);
// 7.2
arr.fill(0);
// console.log(arr);
// 7.3 获取所有的图片
imgs.forEach(function (img) {
// 设置图片的坐标
// 7.4 找到数组里面的最小值
var minTop = Math.min.apply(null, arr);
// 7.5 图片的坐标
img.style.top = minTop + "px";
// 7.6 更新数组的top值(最小值拿的是数组的哪一项,找到对应的列编号。再更新)
var index = arr.indexOf(minTop);
// 设置数组当前这一项
// 图片当前的高度 + 垂直方向间隙
arr[index] += img.clientHeight + info.gap;
// 横坐标
img.style.left = index * (option.imgWidth + info.gap) + "px";
});
// 设置容器的高度
var maxTop = Math.max.apply(null, arr);
option.container.style.height = maxTop - info.gap + "px";
}
/**
* 第六步: 得到图片水平方向上的信息。
*/
function getHorizontalInfo() {
// 6.1
var obj = {};
// 6.2 容器的宽度
obj.containerWidth = option.container.clientWidth;
// 6.3 计算一行有多少个图片
obj.number = (obj.containerWidth + option.minGap) / (option.imgWidth + option.minGap);
// 6.4 向下取整, 每行的图片只能少不能多。
obj.number = Math.floor(obj.number);
// 6.5 重新计算每一个水平空隙
// 总宽度-图片的数量*图片的宽度=剩余空间
obj.gap = (obj.containerWidth - obj.number * option.imgWidth) / (obj.number - 1);
console.log(obj.gap);
return obj;
}
/**
* 第三步: 创建图片
*/
function createImgs() {
// 函数节流
var debounce = myPlugin.debounce(setImgPosition, 50, false);
// 循环图片路径数组
for (var i = 0; i < option.imgSrcs.length; i++) {
var img = document.createElement("img");
img.src = option.imgSrcs[i];
img.style.width = option.imgWidth + "px";
img.style.position = "absolute";
img.style.transition = ".5s";
imgs.push(img);
img.onload = function () {
// 设置图片元素的坐标
debounce();
}
option.container.appendChild(img);
}
}
/**
* 第四步: 处理父元素,因为图片都是绝对定位的,父元素必须是一个定位元素。
*/
function handleParent() {
// 如果父元素不是定位元素,则将其变为相对定位元素
var style = getComputedStyle(option.container);
// console.log(style.position);
if (style.position === "static") {
option.container.style.position = "relative";
}
}
}
结语
整完!!!
js 实现图片瀑布流效果,可更改配置参数 带完整版解析代码[waterFall.js]的更多相关文章
- js 实现淘宝无缝轮播图效果,可更改配置参数 带完整版解析代码[slider.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 需求分析: ...
- js 实现淘宝放大镜功能,可更改配置参数 带完整版解析代码[magnifier.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写淘宝放大镜效果 基本功能: 运 ...
- js 实现文字滚动功能,可更改配置参数 带完整版解析代码。
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写文字滚动效果 需求分析: 需要 ...
- js 实现对象的混合与克隆效果,带完整版解析代码[helpers.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 对象混合 ...
- js图片瀑布流效果
要实现图片瀑布流效果,首先得准备几张图片. html的部分比较简单就是将图片加载到浏览器就可以了 代码如下(注意放的图片多一点要不然之后无法滑动鼠标就无法达到瀑布流效果): <!DOCTYPE ...
- 利用LruCache载入网络图片实现图片瀑布流效果(改进版)
PS: 2015年1月20日21:37:27 关于LoadImageAsyncTask和checkAllImageViewVisibility可能有点小bug 改动后的代码请參见升级版本号的代码 ht ...
- js 图片瀑布流效果实现
/** * Created by wwtliu on 14/9/5. */$(document).ready(function(){ $(window).on("load",fun ...
- JS实现动态瀑布流及放大切换图片效果(js案例)
整理了一下当时学js写的一些案例,再次体验了一把用原生JS实现动态瀑布流效果的乐趣,现在把它整理出来,需要的小伙伴可以参考一下. 该案例主要是用HTML+CSS控制样式,通过JS实现全局瀑布流以及点击 ...
- 纯 css column 布局实现瀑布流效果
原理 CSS property: columns.CSS属性 columns 用来设置元素的列宽和列数. 兼容性 chrome 50+ IE 10+ android browser 2.1+ with ...
随机推荐
- HDU-1421-搬寝室(01背包改编版)
搬寝室是很累的,xhd深有体会.时间追述2006年7月9号,那天xhd迫于无奈要从27号楼搬到3号楼,因为10号要封楼了.看着寝室里的n件物品,xhd开始发呆,因为n是一个小于2000的整数,实在是太 ...
- python class类的属性应用及init初始化实践 ---勇者斗恶龙
最近在熟悉python的基础语法,刚好老师布置了个课后作业感觉挺有意思的,就记录下来了学习过程. 题目如下: 刚拿到题目就想到了init 初始化属性,还列了下思路:(ps:notepad++写的比较糙 ...
- node.js代码二
var express = require('express'); var app = express(); var server = require('http').Server(app); var ...
- Android Visibility控件显示和隐藏
Android控件显示和隐藏 visibility 可见(visible) XML文件:android:visibility="visible" Java代码:view.setVi ...
- python 函数--装饰器
一.装饰器 1.为什么要用装饰器? 装饰器的功能:在不修改原函数以及调用方式的情况下对原函数功能进行扩展. 二.开放和封闭原则 1.对扩展是开放的 2.对修改是封闭的 三.装饰器的固有结构 impor ...
- Struts2-学习笔记系列(14)-拦截器
6.1对action 的拦截 自定义拦截器: public class MyInterceptor extends AbstractInterceptor { private String name; ...
- 【Java】FlowControl 流程控制
FlowControl 流程控制 什么是流程控制? 控制流程(也称为流程控制)是计算机运算领域的用语,意指在程序运行时,个别的指令(或是陈述.子程序)运行或求值的顺序. 不论是在声明式编程语言或是函数 ...
- python高级特性之封包与解包
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:kwsy PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...
- L8梯度消失、梯度爆炸
houseprices数据下载: 链接:https://pan.baidu.com/s/1-szkkAALzzJJmCLlJ1aXGQ 提取码:9n9k 梯度消失.梯度爆炸以及Kaggle房价预测 代 ...
- stand up meeting 11/26/2015
part 组员 今日工作 工作耗时/h 明日计划 工作耗时/h UI 冯晓云 完成UI简易界面布局设计:在UI部分实现释义数据格式转换的实现和测试,使得其与外界接口均标准化为string,具体实现见 ...