前言:浏览器上实现 mac docker 效果,实现思路,1. 布局,方框间距用元素代替,因为有放大缩小功能,不用元素的话,不好控制。2. 定义个 css 变量 i,用来代表放大比例。3. 确定每个元素的 i 值,根据鼠标移动,动态生成一个曲线。设计曲线函数。
效果:
代码实现:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="initial-scale=1.0, user-scalable=no, width=device-width"
/>
<title>document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
text-align: justify;
}
body {
background: #000;
color: #fff;
}
.docker-container {
position: fixed;
bottom: 10px;
display: flex;
justify-content: center;
width: 100%;
}
.docker {
box-sizing: content-box;
height: 30px;
display: flex;
justify-content: center;
align-items: end;
padding: 5px 10px;
background: rgba(255, 255, 255, 0.3);
}
.menu {
display: flex;
align-items: end;
}
.menu-item {
border-radius: 5px;
width: calc(var(--i, 1) * 30px);
height: calc(var(--i, 1) * 30px);
margin-bottom: calc(var(--i, 1) * 15px - 15px);
background: #b4433d;
border: 1px solid #ccc;
}
.gap {
width: calc(var(--i, 1) * 10px);
height: 30px;
}
.menu .menu-item:nth-child(3n + 1) {
background: blue;
}
.menu .menu-item:nth-child(3n) {
background: yellow;
}
</style>
</head>
<body>
<div class="docker-container">
<div class="docker">
<div class="menu">
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
<div class="gap"></div>
<div class="menu-item"></div>
</div>
</div>
</div>
<script>
const docker = document.querySelector(".docker");
const items = document.querySelector(".menu").children;
const range = 500;
const maxScale = 1.8;
const layout = (curve) => {
for (const item of items) {
const rect = item.getBoundingClientRect();
const x = rect.x + rect.width / 2;
const scale = curve(x);
item.style.setProperty("--i", scale);
}
};
const baseCure = (x) => {
if (x < 0) return 0;
if (x > 1) return 0;
return Math.sin(x * Math.PI);
};
const createCure = (totalXDis, topX, minY, maxY) => {
return function curve(x) {
const beginX = topX - totalXDis / 2;
const endX = topX + totalXDis / 2;
if (x < beginX) return minY;
if (x > endX) return minY;
const yDis = maxY - minY;
return baseCure((x - beginX) / totalXDis) * yDis + minY;
};
};
docker.onmousemove = (e) => {
const curve = createCure(range, e.clientX, 1, maxScale);
layout(curve);
};
docker.onmouseleave = () => {
layout(() => 1);
};
</script>
</body>
</html>