平滑收缩动画

Smooth shrinking animation

我希望能够缩小 HTML 标签使其消失,并让剩余的项目顺利消失(这样它们就不会跳到标签原来所在的位置)

const div = document.querySelector('.toGo');

div.addEventListener('click', event => {
  div.className += ' animate';
  // Simulate Angular's DOM modification
  setTimeout(() => div.style.display = 'none', 1100);
  setTimeout(() => div.style.display = 'block', 1200);
  setTimeout(() => div.className = 'toGo', 1300);
});
.toGo, .toStay {
  height: 50px;
  width: 100%;
  background: coral;
  transition: all 1000ms ease-in-out;
  overflow: hidden;
}

.toStay {
  margin: 12px 0;
}

.animate {
  height: 0;
  width: 0;
  opacity: 0;
}
<div class="toGo">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam tristique sed nisi id aliquet. Etiam mauris diam, commodo in nisl ac, porttitor auctor mi. Nunc et blandit lacus. Donec facilisis dolor in arcu convallis, eu molestie magna placerat. Etiam blandit diam vitae nibh sollicitudin, ac gravida risus convallis. Nunc aliquet, turpis ac dignissim mollis, nulla nisi cursus leo, quis viverra nisi augue eget leo. Curabitur porta faucibus vestibulum.
</div>
<div class="toStay">Lorem Ipsum</div>

<p>Click on the first div</p>

现在,如您所见,文本正在移动,因为 space 正在缩小。

起初,我尝试使用 transform 属性,但是第二个 div 跳到了第一个的位置(因为我使用的是 Angular一旦动画完成,框架就会从 DOM 中删除第一个 div)。

const div = document.querySelector('.toGo');

div.addEventListener('click', event => {
  div.className += ' animate';
  // Simulate Angular's DOM modification
  setTimeout(() => div.style.display = 'none', 1100);
  setTimeout(() => div.style.display = 'block', 2100);
  setTimeout(() => div.className = 'toGo', 2200);
});
.toGo, .toStay {
  height: 50px;
  width: 100%;
  background: coral;
  transition: all 1000ms ease-in-out;
  overflow: hidden;
}

.toStay {
  margin: 12px 0;
}

.animate {
  transform: scale(0);
  opacity: 0;
}
<div class="toGo">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam tristique sed nisi id aliquet. Etiam mauris diam, commodo in nisl ac, porttitor auctor mi. Nunc et blandit lacus. Donec facilisis dolor in arcu convallis, eu molestie magna placerat. Etiam blandit diam vitae nibh sollicitudin, ac gravida risus convallis. Nunc aliquet, turpis ac dignissim mollis, nulla nisi cursus leo, quis viverra nisi augue eget leo. Curabitur porta faucibus vestibulum.
</div>
<div class="toStay">Lorem Ipsum</div>

<p>Click on the first div</p>

然后我用 width/height 尝试了这个解决方案,但文本在移动。然后我终于尝试在其中放置一个容器,但它没有改变任何东西(除非我为该内部容器设置了固定大小)。

有没有办法做到这一点,无需将固定 width/height 设置到内部容器

编辑 人们实际上要求关闭我的问题,因为它是 "unclear"。如果这不是很明显,我希望第一个片段停止移动文本,第二个片段平滑地移动第二个 div 代替第一个(不跳转)。

类似这样,内部容器没有使用固定尺寸

const div = document.querySelector('.toGo');

div.addEventListener('click', event => {
  div.className += ' animate';
  // Simulate Angular's DOM modification
  setTimeout(() => div.style.display = 'none', 1100);
  setTimeout(() => div.style.display = 'block', 1200);
  setTimeout(() => div.className = 'toGo', 1300);
});
.toGo, .toStay {
  height: 50px;
  width: 100%;
  background: coral;
  transition: all 1000ms ease-in-out;
  overflow: hidden;
}

.container {
  height: 50px;
  width: 100vw;
}

.toStay {
  margin: 12px 0;
}

.animate {
  height: 0;
  width: 0;
  opacity: 0;
}
<div class="toGo">
  <div class="container">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam tristique sed nisi id aliquet. Etiam mauris diam, commodo in nisl ac, porttitor auctor mi. Nunc et blandit lacus. Donec facilisis dolor in arcu convallis, eu molestie magna placerat. Etiam blandit diam vitae nibh sollicitudin, ac gravida risus convallis. Nunc aliquet, turpis ac dignissim mollis, nulla nisi cursus leo, quis viverra nisi augue eget leo. Curabitur porta faucibus vestibulum.
  </div>
</div>
<div class="toStay">Lorem Ipsum</div>

<p>Click on the first div</p>

第一个代码段中的主要问题与创建跳跃效果的边距折叠有关。考虑使用 flexbox 容器来避免边距折叠:

然后你可以考虑结合高度动画的剪辑路径动画(不要设置宽度动画以避免收缩效果)

const div = document.querySelector('.toGo');

div.addEventListener('click', event => {
  div.className += ' animate';
  
  // Simulate Angular's DOM modification
  setTimeout(() => div.style.display = 'none', 1100);
  setTimeout(() => div.style.display = 'block', 1200);
  setTimeout(() => div.className = 'toGo', 1300);
});
body {
  display:flex;
  flex-direction:column;
}

.toGo, .toStay {
  height: 50px;
  width: 100%;
  background: coral;
  transition: all 1000ms ease-in-out;
  overflow: hidden;
  clip-path:polygon(0 0,100% 0,100% 100%, 0 100%);
}

.toStay {
  margin: 12px 0;
}

.animate {
  height: 0;
  opacity: 0;
  clip-path:polygon(0 0,0% 0,0% 100%, 0 100%);
}
<div class="toGo">
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam tristique sed nisi id aliquet. Etiam mauris diam, commodo in nisl ac, porttitor auctor mi. Nunc et blandit lacus. Donec facilisis dolor in arcu convallis, eu molestie magna placerat. Etiam blandit diam vitae nibh sollicitudin, ac gravida risus convallis. Nunc aliquet, turpis ac dignissim mollis, nulla nisi cursus leo, quis viverra nisi augue eget leo. Curabitur porta faucibus vestibulum.
</div>
<div class="toStay">Lorem Ipsum</div>

<p>Click on the first div</p>

您可以调整剪辑路径来控制动画的制作方式。

const div = document.querySelector('.toGo');

div.addEventListener('click', event => {
  div.className += ' animate';
  
  // Simulate Angular's DOM modification
  setTimeout(() => div.style.display = 'none', 1100);
  setTimeout(() => div.style.display = 'block', 1200);
  setTimeout(() => div.className = 'toGo', 1300);
});
body {
  display:flex;
  flex-direction:column;
}

.toGo, .toStay {
  height: 50px;
  width: 100%;
  background: coral;
  transition: all 1000ms ease-in-out;
  overflow: hidden;
  clip-path:polygon(0 0,100% 0,100% 100%, 0 100%);
}

.toStay {
  margin: 12px 0;
}

.animate {
  height: 0;
  opacity: 0;
  clip-path:polygon(50% 0,50% 0,50% 100%, 50% 100%);
}
<div class="toGo">
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam tristique sed nisi id aliquet. Etiam mauris diam, commodo in nisl ac, porttitor auctor mi. Nunc et blandit lacus. Donec facilisis dolor in arcu convallis, eu molestie magna placerat. Etiam blandit diam vitae nibh sollicitudin, ac gravida risus convallis. Nunc aliquet, turpis ac dignissim mollis, nulla nisi cursus leo, quis viverra nisi augue eget leo. Curabitur porta faucibus vestibulum.
</div>
<div class="toStay">Lorem Ipsum</div>

<p>Click on the first div</p>