仅使用CSS创建盒子翻盖效果

11

我尝试使用过渡效果来创建这个效果。它应该看起来像你正在打开一个盒子。

存在两个问题:

  1. 关闭盒子的顺序与打开的顺序相同。有没有办法以与其打开相反的顺序关闭盒子,使得盒子在关闭时回到与关闭前相同的状态?
  2. 由于红色和蓝色瓣片的关系,绿色和黄色瓣片的末端在转换期间被隐藏了,因此它看起来不是3D的。有没有一种方法可以以3D方式显示所有瓣片?

如果可能的话,请使用纯CSS解决方案,不要使用JavaScript。

#box {
  position: relative;
  top: 170px;
  left: 170px;
  width: 300px;
  height: 300px;
  border: 1px solid black;
  perspective: 800px;
} 
#flap1, #flap2, #flap3, #flap4 {
  position: absolute;
}
#flap1 {
  background-color: red;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform-origin: 0 0;
  transition: transform 1s;
}
#flap2 {
  left: 150px;
  background-color: blue;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform-origin: 100% 0;
  transition: transform 1s ease 0.3s;
}
#flap3 {
  background-color: green;
  width: 300px;
  height: 150px;
  transform-origin: 0 0;
  transition: transform 1s ease 0.6s;
}
#flap4 {
  background-color: yellow;
  top: 150px;
  width: 300px;
  height: 150px;
  transform-origin: 0 100%;
  transition: transform 1s ease 0.9s;
}
#box:hover #flap1{
  transform: rotateY(-170deg);
}
#box:hover #flap2{
  transform: rotateY(170deg);
}
#box:hover #flap3{
  transform: rotateX(170deg);
}
#box:hover #flap4{
  transform: rotateX(-170deg);
}
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div id="box">
      <div id="flap1"></div>
      <div id="flap2"></div>
      <div id="flap3"></div>
      <div id="flap4"></div>
    </div>
  </body>
</html>


  1. 我认为你做不到。只需添加另一个类或其他内容。
  2. 你可以使用CSS3 perspective
- Mosh Feu
1个回答

8

对于问题1:

如果你在:hover选择器中按顺序设置延迟,并在默认选择器中按相反顺序设置延迟,就可以实现完全相反的动画效果。

对于问题2:

解决方法和说明如下:

  • 在部分过渡时间内,绿色和黄色方块看起来没有3D效果,因为有几个元素具有更高的z-index,被放置在上面。这阻止了拉伸区域(由于透视旋转)的显示,因此它看起来只有2D效果(但实际上不是)。为了解决这个问题,我们需要指示浏览器保留变换的3D效果。这可以通过使用transform-style:preserve-3d来完成。
  • 当我们执行上述操作时,所有的翼板都将以3D效果打开,但在动画开始和结束时,蓝色翼板实际上会出现闪烁。看起来好像是因为z-index在使用3D变换时失去了效果,在失去z-index效果和开始preserve-3D效果之间有很小的时间差,在这段时间内,蓝色翼板暂时会被放在后面。为了解决这个问题,需要添加translateZ(1px)的3D等效于z-index:1。Z轴上的平移将元素向你的眼睛靠近1像素,并使其保持在黄色和绿色翼板之上。
  • 最后,尽管进行了以上所有操作,但在悬停动画结束时,仍然存在一个小故障,绿色翼板会从蓝色翼板中显示出来。为了解决这个问题,我稍微改变了延迟时间。

与我最初提到的相反,translateZ(0px)不是必需的,可以删除。

#box {
  position: relative;
  top: 170px;
  left: 170px;
  width: 300px;
  height: 300px;
  border: 1px solid black;
  perspective: 800px;
  transform-style: preserve-3d;
}
#flap1, #flap2, #flap3, #flap4 {
  position: absolute;
}
#flap1 {
  background-color: red;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform: translateZ(1px);
  transform-origin: 0 0;
  transition: transform 1s 1.5s;
}
#flap2 {
  left: 150px;
  background-color: blue;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform: translateZ(1px);
  transform-origin: 100% 0;
  transition: transform 1s ease 1s;
}
#flap3 {
  background-color: green;
  width: 300px;
  height: 150px;
  transform-origin: 0 0;
  transition: transform 1s ease 0.5s;
}
#flap4 {
  background-color: yellow;
  top: 150px;
  width: 300px;
  height: 150px;
  transform-origin: 0 100%;
  transition: transform 1s ease;
}
#box:hover #flap1 {
  transform: rotateY(-170deg) translateZ(1px);
  transition: transform 1s ease;
}
#box:hover #flap2 {
  transform: rotateY(170deg) translateZ(1px);
  transition: transform 1s ease 0.5s;
}
#box:hover #flap3 {
  transform: rotateX(170deg);
  transition: transform 1s ease 1s;
}
#box:hover #flap4 {
  transform: rotateX(-170deg);
  transition: transform 1s ease 1.5s;
}
<div id="box">
  <div id="flap1"></div>
  <div id="flap2"></div>
  <div id="flap3"></div>
  <div id="flap4"></div>
</div>


第一个问题的解决方案很好,虽然第二个解决方案有效,但我不明白 z-index 是如何解决问题的... 如果红色和蓝色翼片的 z-index 是1px,比绿色和黄色框更高,那么第二个问题不应该仍然存在,因为绿色和黄色框仍然位于红色和蓝色框下方吗?@Harry - Dhruv Chadha
@DhruvChadha:translateZ()在3D场景中几乎与z-index执行相同的功能。您对绿色和黄色仍然位于蓝色和红色下方的观点是正确的,但添加3D变换会导致图层创建(这是复杂渲染过程的一部分),从而影响行为。很难在评论中解释清楚,我会尽力在答案中详细说明。请给我一些时间。 - Harry
1
@DhruvChadha:我添加了一些额外的解释(并且还纠正了原始答案中的一个错误:D)。看看它是否有帮助 :) - Harry
我必须说,我从未见过像这样好的解释,但是关于您在translateZ的第二点上的最后一件事,即使没有translateZ甚至没有z-index,我也没有看到任何闪烁(我从代码中删除了两者),它工作得很好。我认为preserve-3d本身就可以胜任这项工作。我只是在HTML中将红色和蓝色的div放在绿色和黄色的div之后。以防您想检查-https://jsfiddle.net/nt4me6ep/ - Dhruv Chadha
1
哦,我以为你不想改变顺序,所以才添加了z-index。如果可以改变顺序,那么是的,z-index或translateZ就不需要了,因为DOM中下面的元素将覆盖在前面的元素上方,因此无需额外设置来使它们保持在上方 :) - Harry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接