瀑布流 + 共享效果
- 实现原理 : 展示的元素固定宽度,通过计算容器的宽度判断该内容应该创建多少列
- 应创建的列数 = 包含数组的长度
- 每次添加一个元素都往这个数组最小的一项添加上元素的高度
- 计算时通过获取数组最小一项的下标,计算出left 和 top 值 + gap值就是总体效果实现
- 每次更新窗口变化重新计算
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body,
html {
margin: 0;
padding: 0;
}
.container {
width: 90%;
margin: 0 auto;
padding: 10px;
box-sizing: border-box;
position: relative;
}
.container div {
transition: .5s;
}
.container div {
position: absolute;
/* css3属性,表示过渡效果, 图片的样式变化在0.3秒内完成,而不是瞬间完成 */
transition: 0.3s;
width: 220px;
}
#mask{
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #ccc;
z-index: 1;
opacity: .6;
}
</style>
</head>
<body>
<div id="mask"></div>
<div class="container"></div>
</body>
</html>
<script>
const divContainer = document.querySelector('.container');
const mask = document.querySelector('#mask')
// 计算 margin 固定宽度
const marginGap = 20
let oWidth = 220;
const oHeight = { max: 600, min: 250 }
const ShowItem = 20
const Gap = 1
var timerId = null;
var clonedElement = null;
// 计算当前盒子宽度 / 盒子宽度 + 边距
function createDom(n) {
for (var i = 0; i < n; i++) {
let nDom = document.createElement('div');
nDom.style.width = oWidth + 'px'
nDom.style.height = getRandomNumber() + 'px'
nDom.style.backgroundColor = getRandomColor()
nDom.classList.add('item')
divContainer.appendChild(nDom)
}
SetPosition()
}
createDom(ShowItem)
function SetPosition() {
function cal() {
// 获取容器 宽度
var containerWidth = divContainer.getBoundingClientRect().width
// 计算列的数量
var columns = Math.floor(containerWidth / oWidth);
// 间隙数量
var spaceNumber = columns + 1;
var leftSpace = containerWidth - columns * oWidth; //计算剩余的空间
var space = leftSpace / spaceNumber; //每个间隙的空间
return {
space: space,
columns: columns,
};
}
var info = cal(); //得到列数,和 间隙的空间
var nextTops = new Array(info.columns); //该数组的长度为列数,每一项表示该列的下一个图片的纵坐标
nextTops.fill(0); //将数组的每一项填充为0
for (var i = 0; i < divContainer.children.length; i++) {
var cDom = divContainer.children[i];
var minTop = Math.min.apply(null, nextTops);
cDom.style.top = minTop + 'px';
//重新设置数组这一项的下一个top值
var index = nextTops.indexOf(minTop); //得到使用的是第几列的top值
nextTops[index] += cDom.getBoundingClientRect().height + info.space;
//横坐标
var left = (index + 1) * info.space + index * oWidth;
cDom.style.left = left + 'px';
}
var max = Math.max.apply(null, nextTops); //求最大值
divContainer.style.height = max + 'px'; //3. 设置容器的高度
}
window.addEventListener('resize', resizeHandler, false)
function resizeHandler() {
if (timerId) {
clearTimeout(timerId)
}
timerId = setTimeout(SetPosition, 300)
}
// 配合共享效果
divContainer.addEventListener('click',handlerClick,false)
function handlerClick(e){
if(e.target.classList.contains('item')){
let curDom = e.target;
if(clonedElement) return
clonedElement = curDom.cloneNode(true);
clonedElement.style.zIndex = 3;
clonedElement.classList.add('copyEle')
divContainer.appendChild(clonedElement)
const {left, top, width,height} = clonedElement.getBoundingClientRect()
let saveOption = {
left,
top,
width,
height
}
clonedElement.style.left = '50%'
clonedElement.style.top = (document.documentElement.scrollTop + saveOption.height / 2 + 30) + 'px'
clonedElement.style.zIndex = 2
clonedElement.style.transform = 'translate(-50%, -50%)';
toggleMask()
}
}
function toggleMask(){
const computedStyle = window.getComputedStyle(mask);
let display = computedStyle.getPropertyValue('display')
display == 'none'? mask.style.display = 'block' : mask.style.display = 'none';
}
function toggleClonedElementClose(){
if(clonedElement){
divContainer.removeChild(clonedElement)
clonedElement = null
}
}
mask.addEventListener('click',function(){
toggleMask()
toggleClonedElementClose()
})
// ----------------------------------------
function getRandomNumber(props = oHeight) {
// 生成 0 到 1 之间的随机数
const random = Math.random();
const { max, min } = props
// 将随机数转换为指定范围内的数值
const range = max - min;
const randomNumber = Math.floor(random * range) + min;
return randomNumber;
}
function getRandomColor() {
// 生成红、绿、蓝三个通道的随机值
const red = Math.floor(Math.random() * 256);
const green = Math.floor(Math.random() * 256);
const blue = Math.floor(Math.random() * 256);
// 将通道值拼接成 CSS 颜色字符串
const color = `rgb(${red}, ${green}, ${blue})`;
return color;
}
</script>