需求:官网首页从上到下分为3个模块,第二个模块是由四个同心圆组成的(位于屏幕中间)。从第一个模块滑动到第二个模块的时候,首先出现最外面的圆,再接着滑动时候,依次出现剩余的三个圆,同时首先出现的圆在逐渐变大(位置不变)直到占满屏幕后由后面的圆替换掉前一个圆,当最后一个圆占满屏幕时,变成圆角为50px的矩形。接着下滑则进入第三个模块,结束。如果我是从第三个模块向上滑进入第二个模块,效果则反过来。各位怎么实现啊,示例网站: https://salesmore.pl/。 谷歌浏览器打开下滑就能看到几个同心圆的部分,那个就是我想要的交互效果。
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
overflow: hidden;
}
.container {
position: relative;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.circle {
position: absolute;
background: #3498db;
border-radius: 50%;
transform: scale(0);
transition:
transform 1s ease-in-out,
border-radius 0.6s ease 0.4s; /* 添加圆角过渡 */
}
/* 不同尺寸的圆圈 */
.circle:nth-child(1) { width: 100px; height: 100px; background: red;}
.circle:nth-child(2) { width: 200px; height: 200px; background: blue;}
.circle:nth-child(3) { width: 300px; height: 300px; background: yellowgreen;}
.circle:nth-child(4) {
width: 400px;
background: green;
height: 400px;
transition:
transform 1.2s ease-in-out,
width 1s ease 1s,
height 1s ease 1s,
border-radius 0.6s ease 1.2s; /* 分阶段过渡 */
}
</style>
</head>
<body>
<div class="container">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
<script>
const circles = document.querySelectorAll('.circle');
let isAnimating = false;
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
document.addEventListener('wheel', handleScroll, { passive: false });
function handleScroll(e) {
e.preventDefault();
if (isAnimating) return;
if (e.deltaY > 0) { // 向下滚动
startExpandAnimation();
}
}
async function startExpandAnimation() {
isAnimating = true;
// 依次放大前三个圆圈
for (let i = 0; i < circles.length - 1; i++) {
await animateCircle(circles[i], 1);
}
// 处理最后一个圆圈
const lastCircle = circles[circles.length - 1];
await animateCircle(lastCircle, 1);
// 变形为长方形
lastCircle.style.borderRadius = '10px';
lastCircle.style.width = `${viewportWidth}px`;
lastCircle.style.height = `${viewportHeight}px`;
// 等待最终变形完成
await new Promise(resolve => {
lastCircle.addEventListener('transitionend', resolve, { once: true });
});
isAnimating = false;
}
function animateCircle(circle, scale) {
return new Promise(resolve => {
circle.style.transform = `scale(${scale})`;
circle.addEventListener('transitionend', () => {
resolve();
}, { once: true });
});
}
</script>
</body>
</html>