先看效果:
这个效果的实现,重点是使用了svg滤镜
完整代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> html,body{ margin: 0; background-color: #e0e0e0; display: flex; align-items: center; justify-content: center; height: 100%; } #box{ width: 320px; height: 640px; background-color: #efefef; position: relative; } .footer{ position: absolute; bottom: 0; left: 0; right: 0; display: flex; justify-content: space-between; background-color: #fff; background-image: linear-gradient(45deg, #ffe8e8, #ffffff, #edf9ff); } .tag{ display: block; height: 60px; display: flex; align-items: center; justify-content: center; text-align: center; flex: 1; position: relative; z-index: 4; cursor: pointer; } .tag span{ position: relative; top: 0; border-radius: 50%; transition: 0.6s; display: flex; width: 60px; height: 60px; align-items: center; justify-content: center; color: #a9b5bf; } .tag.current span{ top: -20px; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.05); background-image: linear-gradient(45deg, #ffe8e8, #ffffff, #edf9ff); } .tag span svg{ width: 24px; fill: #a9b5bf; } .tag.current span svg{ fill: #5b6c7a; } .footer-bg{ position: absolute; left: 0; right: 0; bottom: 60px; height: 60px; background-color: #efefef; z-index: 2; filter: url(#goo); transition: 0.3s; } .dot{ width: 78px; height: 64px; background-color: #efefef; position: absolute; left: 0%; top: 46px; transform: translateX(1px); border-radius: 50%; transition: 0.3s; } .content{ position: absolute; left: 0; top: 0; right: 0; bottom: 60px; z-index: 3; transition: background-color 0.3s; text-align: center; color: #fff; } </style> </head> <body> <div id="box"> <div class="content"> <main> <h1>Text</h1> <p>content position here</p> <p>click & next</p> </main> </div> <div class="footer-bg"> <div class="dot"></div> </div> <footer class="footer"> <div onclick="setCurrent(1)" class="tag tag1 current"><span><svg t="1697425088462" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4895" width="200" height="200"><path d="M900.745478 430.904767l-330.418307-308.008394c-16.679524-19.033077-40.82902-29.982212-66.411112-29.982212-25.172779 0-49.322274 10.846807-65.2855 28.8566L120.491656 430.802438c-15.860897 16.270211-20.465674 39.805736-11.665434 60.783052 8.80024 20.977316 29.163585 34.075347 51.880484 34.075347l28.651944 0 0 314.148096c0 48.708304 38.987109 88.309383 87.695413 88.309383l136.608374 0c17.702808 0 33.461377-14.325972 33.461377-32.02878L447.123813 687.032677c0-8.902568 5.832717-16.781853 14.735285-16.781853l96.393325 0c8.902568 0 15.656241 7.981613 15.656241 16.781853l0 208.954532c0 17.805136 14.837614 32.02878 32.540422 32.02878l136.608374 0c48.708304 0 88.616369-39.498751 88.616369-88.309383l0-314.148096 28.549615 0c22.61457 0 42.977915-13.098031 51.778155-33.973019C921.006495 470.812831 916.504047 447.174978 900.745478 430.904767L900.745478 430.904767 900.745478 430.904767M900.745478 430.904767 900.745478 430.904767z" p-id="4896"></path></svg></span></div> <div onclick="setCurrent(2)" class="tag tag2"><span><svg t="1697425146769" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10385" width="200" height="200"><path d="M697.995 113.419c-70.292-0.023-137.597 28.416-186.521 78.81-48.918-50.405-116.223-78.845-186.521-78.81-143.994 0-261.128 117.81-261.128 262.588 0 60.857 21.186 120.158 61.737 169.399l333.351 342.183a72.81 72.81 0 0 0 52.561 22.307c19.958 0 38.61-7.934 52.602-22.272l335.439-344.606c38.559-47.143 59.62-106.142 59.608-167.011 0-144.779-117.132-262.588-261.128-262.588" p-id="10386"></path></svg></span></div> <div onclick="setCurrent(3)" class="tag tag3"><span><svg t="1697425204633" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17807" width="200" height="200"><path d="M554.6 319c79.3 0 119-39.7 119-119S634 80.9 554.6 80.9c-79.3 0-119 39.7-119 119.1s39.7 119 119 119z m-303.4 0c79.3 0 119-39.7 119-119s-39.7-119.1-119-119.1-119 39.7-119 119.1 39.6 119 119 119zM908 409.4c-29.2-10-71.2 22.5-71.2 22.5l-130.2 110c-34.9-126-139.8-189.1-314.8-189.1C173.3 352.9 64 451.2 64 647.9 64 844.6 173.3 943 391.8 943c171.4 0 275.6-60.6 312.6-181.6l116.7 119.2s54.3 33.9 83.5 24.2c34.7-11.6 55.3-67.1 55.3-67.1V470.8c0.1 0-24.6-52-51.9-61.4z" p-id="17808"></path></svg></span></div> <div onclick="setCurrent(4)" class="tag tag4"><span><svg t="1697425179323" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15873" width="200" height="200"><path d="M849.285816 446.006983c0-216.528522-175.531805-392.065444-392.065444-392.065444-216.528522 0-392.065444 175.536922-392.065444 392.065444 0 212.83848 169.602769 386.054543 381.026016 391.899668l-25.116027 122.098849 264.222777-195.065697-0.019443 0.005117C784.570909 693.817975 849.285816 577.470107 849.285816 446.006983L849.285816 446.006983zM467.13314 689.13635c-4.620227 0-9.250688-0.098237-13.896498-0.294712-86.150102-3.632737-165.779697-40.636512-224.213551-104.208387l17.995863-30.619368c54.015218 58.760289 127.618563 92.971461 207.246111 96.326882 79.639828 3.359514 155.851581-24.548092 214.611869-78.564333l16.542768 32.077579C625.272833 659.136082 548.224016 689.13635 467.13314 689.13635L467.13314 689.13635zM467.13314 689.13635" p-id="15874"></path></svg></span></div> </footer> </div> <svg width="0" height="0"> <defs> <filter id="goo"> <feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur" id="blurFilter"></feGaussianBlur> <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 30 -15" result="goo"></feColorMatrix> <feComposite in="SourceGraphic" in2="goo" operator="atop"></feComposite> </filter> </defs> </svg> <script> function setCurrent(index) { const tags = document.querySelectorAll('.tag') tags.forEach(tag => { tag.classList.remove('current') }) const tag = document.querySelector('.tag' + index) tag.classList.add('current') const dot = document.querySelector('.dot') dot.style.left = 25 * (index-1) + '%' setColor(index) } function setColor(index) { const colors = ['#a9b5bf', '#a9bfb7', '#bcbfa9', '#bfa9a9'] const color = colors[index-1] const bg = document.querySelector('.footer-bg') const dot = document.querySelector('.dot') const content = document.querySelector('.content') const svg = document.querySelector('.tag.current span svg') bg.style.backgroundColor = color dot.style.backgroundColor = color content.style.backgroundColor = color const svgs = document.querySelectorAll('.tag span svg') svgs.forEach(svg => { svg.style.fill = '#a9b5bf' }) svg.style.fill = color } setCurrent(1) </script> </body> </html>
导航的平滑圆角融合实现:
1. SVG滤镜
<svg width="0" height="0"> <defs> <filter id="goo"> <feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur" id="blurFilter"></feGaussianBlur> <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 30 -15" result="goo"></feColorMatrix> <feComposite in="SourceGraphic" in2="goo" operator="atop"></feComposite> </filter> </defs> </svg>
2. 使用滤镜的DOM
<div class="footer-bg"> <div class="dot"></div> </div>
3. 用CSS给DOM添加SVG滤镜
.footer-bg{ filter: url(#goo); }
4. 控制融合效果偏移位置JS
function setCurrent(index) { const tags = document.querySelectorAll('.tag') tags.forEach(tag => { tag.classList.remove('current') }) const tag = document.querySelector('.tag' + index) tag.classList.add('current') const dot = document.querySelector('.dot') dot.style.left = 25 * (index-1) + '%' setColor(index) }
这4点是实现的主要内容。其它代码看完整代码吧。