我正在尝试创建一种效果,其中两个矩形形状(带有圆角末端),每个都包含文本,相互移动,当我向下滚动页面时合并/变形为单个圆角矩形,当我向上滚动时再次分离。滚动期间形状需要保持粘在视口位置。
我尝试过的:
我得到的最接近的结果只是让形状彼此靠近并稍微重叠。其他尝试导致了椭圆形、不自然的边界半径或两个元素之间缺乏凝聚力。
document.addEventListener('scroll', () => {
const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight);
const movement = (window.innerWidth / 2 - 115) * scrollPercent;
const shape1 = document.querySelector('.shape:nth-child(1)');
const shape2 = document.querySelector('.shape:nth-child(2)');
shape1.style.transform = `translateX(${movement}px)`;
shape2.style.transform = `translateX(-${movement}px)`;
});
body {
width: 90%;
margin: 0 auto;
padding: 20px;
height: 2000px;
}
.container {
position: sticky;
top: 20px;
display: flex;
justify-content: space-between;
}
.shape {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 30px;
border-radius: 15px;
background-color: #000;
color: #fff;
transition: transform 0.3s ease-out;
transform: translateX(0%);
}
<body>
<div class="container">
<div class="shape" id="shape1">Shape 1</div>
<div class="shape" id="shape2">Shape 2</div>
</div>
</body>
问题: 我觉得我错过了一些带有剪辑路径的东西,这就是我需要采取的路线。如何改进 CSS 并调整 JavaScript 以实现上图所示的变形效果,同时保持圆形外边缘并在两个容器之间建立凝聚力?我感谢对我当前方法的任何建议或更正。谢谢你。
一种常见的方法是使用 SVG 滤镜:
<svg class="goo-filter" viewbox="0 0 0 0">
<filter id="goo">
<feGaussianBlur in="SourceGrapgic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 64 -32" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</svg>
.container {
filter: url(#goo);
}
document.addEventListener('scroll', () => {
const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight);
const movement = (window.innerWidth / 2 - 115) * scrollPercent;
const shape1 = document.querySelector('.shape:nth-child(1)');
const shape2 = document.querySelector('.shape:nth-child(2)');
shape1.style.transform = `translateX(${movement}px)`;
shape2.style.transform = `translateX(-${movement}px)`;
});
body {
width: 90%;
margin: 0 auto;
padding: 20px;
height: 2000px;
}
.container {
position: sticky;
top: 20px;
display: flex;
justify-content: space-between;
filter: url(#goo);
}
.shape {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 30px;
border-radius: 15px;
background-color: #000;
color: #fff;
transition: transform 0.3s ease-out;
transform: translateX(0%);
}
<body>
<div class="container">
<div class="shape" id="shape1">Shape 1</div>
<div class="shape" id="shape2">Shape 2</div>
</div>
<svg class="goo-filter" viewbox="0 0 0 0">
<filter id="goo">
<feGaussianBlur in="SourceGrapgic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 64 -32" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</svg>
</body>
首先,它使用
<feGaussianBlur />
来模糊两个框。与 filter: blur(12px)
非常相似,它使源图像变得模糊,尺寸比其原始形状更大,并将输出图像存储在通道 blur
中。
<feGaussianBlur in="SourceGrapgic" stdDeviation="10" result="blur" />
然后使用
<feColorMatrix />
,在不触及源图像的RGB通道的情况下,仅“锐化”图像的具有相对较大值的alpha通道(64 -32
),它使小于0.5
的alpha通道不可见,大于的alpha通道不可见0.5
完全可见(Alpha 通道值从 0
到 1
)。然后将输出存储在通道goo
中。
<feColorMatrix in="blur" mode="matrix" values="
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 64 -32" result="goo" />
最后,它将这些通道与
<feBlend />
混合,当两个盒子几乎接触时,它们重叠的模糊边界的alpha通道大于0.5
,从而产生粘糊糊的效果。