如何使用 CSS 和 JavaScript 创建粘性、内聚的形状到形状(容器)变形?

问题描述 投票:0回答:1

我正在尝试创建一种效果,其中两个矩形形状(带有圆角末端),每个都包含文本,相互移动,当我向下滚动页面时合并/变形为单个圆角矩形,当我向上滚动时再次分离。滚动期间形状需要保持粘在视口位置。 enter image description here

我尝试过的:

  • 应用 CSS 平移和转换以及边框半径属性的 JS 调整。
  • 合并剪辑路径,但我最终得到了省略号。
  • 使用 HTML 形状,但我需要它们作为容器。

我得到的最接近的结果只是让形状彼此靠近并稍微重叠。其他尝试导致了椭圆形、不自然的边界半径或两个元素之间缺乏凝聚力。

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 以实现上图所示的变形效果,同时保持圆形外边缘并在两个容器之间建立凝聚力?我感谢对我当前方法的任何建议或更正。谢谢你。

javascript html css animation css-animations
1个回答
0
投票

一种常见的方法是使用 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
,从而产生粘糊糊的效果。

© www.soinside.com 2019 - 2024. All rights reserved.