前言:浏览器上实现 mac docker 效果,实现思路,1. 布局,方框间距用元素代替,因为有放大缩小功能,不用元素的话,不好控制。2. 定义个 css 变量 i,用来代表放大比例。3. 确定每个元素的 i 值,根据鼠标移动,动态生成一个曲线。设计曲线函数。
效果:
代码实现:
<!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>