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 ...
随机推荐
- lly的瞬移方块(并查集)
lly的瞬移方块 Description llyllylly最近发明了一个叫瞬移方块的游戏,为啥llyllylly这么闲呢,这得从一只蝙蝠说起..... llyllylly决定给大家也分享一下这个游戏 ...
- HDU 2147kiki's game(巴什博弈变形)
题目链接 思路如下 P : 必胜点,那个人先走到 含P的点,那个这个人一定会输, N:必败点,谁走到这个点谁输! 在这一个题中: 某个点是P还是 N,之与 ⬅️左边第一个点.⬇️下边第一个点.↙️左下 ...
- async和await是如何实现异步编程?
目录 异步编程样例 样例解析 浅谈Promise如何实现异步执行 参考 1.异步编程样例 样例: // 等待执行函数 function sleep(timeout) { return new Prom ...
- es6声明一个类
js语言的传统方式是通过定义构造函数,生成心得对象.是一种基于原型的面向对象系统.在es6中增加了class类的概念,可以使用class关键字来声明一个类.之后用这个类来实例化对象. 构造函数示例 c ...
- 启用SELinux保护
启用SELinux保护 案例1:启用SELinux保护 1.1问题 本例要求为虚拟 ...
- Vulnhub homeless靶机渗透
信息搜集 nmap -sP 192.168.146.6 nmap -A -Pn 192.168.146.151 直接访问web服务. 大概浏览一下没发现什么,直接扫描下目录把dirb+bp. BP具体 ...
- flask-url_for
flask-url_for flask的url_for函数和django的reverse函数类似,都是提供视图反转url的方法 from flask import Flask, url_for app ...
- Java第一天,带你走进编程的世界,我的第一个程序
要想彻底了解Java是什么,我就得首先了解编程语言的发展史.编程语言最初的形势是"0101......"数据编程,也就是机器语言.机器语言可以说是一种几乎没有人能够看懂的编程语言, ...
- Javascript 入门 必备知识点
1.如何得到html的input标签的值: (1). $('#id').val(); (2). $("#id").attr("value"); 2.javasc ...
- OS-DOS/CMD/Windows/各类软件快捷键等使用总结
一.快捷键 很多软件的快捷键使用相通,在不确定的情况下,先试试其他软件的快捷键的使用方法 Windows电脑快捷键 HP惠普笔记本 win+E 打开文件管器 win+D 显示桌面 win+L 锁计算机 ...