旋转的3d导航栏

时间:2014-11-18 04:52:28

标签: css transform transition perspective

我尝试使用纯CSS创建一个带有变换,过渡和透视的3d导航栏。

这是我的代码:



.navbar-fixed-bottom {
	  background: transparent;
	}
	
	.navbar-perspective {
	  width: 100%;
	  height: 100%;
	  position: relative;
	  -webkit-perspective: 1100px;
	  -moz-perspective: 1100px;
	  perspective: 1100px;
	  -webkit-perspective-origin: 50% 0;
	  -moz-perspective-origin: 50% 0;
	  perspective-origin: 50% 0;
	}
	
	.navbar-perspective > div {
	  margin: 0 auto;
	  position: relative;
	  text-align: justify;
	  -webkit-backface-visibility: hidden;
	  -moz-backface-visibility: hidden;
	  backface-visibility: hidden;
	  -webkit-transition: all 0.5s;
	  -moz-transition: all 0.5s;
	  transition: all 0.5s;
	  height: 50px;
	  font-size:20px;
	}
	
	.navbar-primary {
	  background-color: #cccccc;
	  z-index: 2;
	  -webkit-transform-origin: 0% 100%;
	  -moz-transform-origin: 0% 100%;
	  transform-origin: 0% 100%;
	}
	
	.navbar .navbar-secondary,
	.navbar .navbar-tertiary {
	  background-color: #bfbfbf;
	  width: 100%;
	  -webkit-transform-origin: 0% 0%;
	  -moz-transform-origin: 0% 0%;
	  transform-origin: 0% 0%;
	  z-index: 1;
	  -webkit-transform: rotateX(-90deg);
	  -moz-transform: rotateX(-90deg);
	  transform: rotateX(-90deg);
	  -webkit-transition: top 0.5s;
	  -moz-transition: top 0.5s;
	  transition: top 0.5s;
	  position: absolute;
	  top: 0;
	}
	
	.navbar .navbar-tertiary {
	  background-color: #b3b3b3;
	}
	
	.navbar-rotate-primary {
	  height: 50px;
	}
	
	.navbar-rotate-primary .navbar-primary {
	  -webkit-transform: translateY(0%) rotateX(0deg);
	  -moz-transform: translateY(0%) rotateX(0deg);
	  transform: translateY(0%) rotateX(0deg);
	}
	
	.navbar-rotate-primary .navbar-secondary,
	.navbar-rotate-primary .navbar-tertiary {
	  top: 100%;
	  -webkit-transition: -webkit-transform 0.5s;
	  -moz-transition: -moz-transform 0.5s;
	  transition: transform 0.5s;
	  -webkit-transform: rotateX(-90deg);
	  -moz-transform: rotateX(-90deg);
	  transform: rotateX(-90deg);
	}
	
	.navbar-rotate-secondary,
	.navbar-rotate-tertiary {
	  height: 50px;
	}
	
	.navbar-rotate-secondary .navbar-primary,
	.navbar-rotate-tertiary .navbar-primary {
	  -webkit-transform: translateY(-100%) rotateX(90deg);
	  -moz-transform: translateY(-100%) rotateX(90deg);
	  transform: translateY(-100%) rotateX(90deg);
	}
	
	.navbar-rotate-secondary .navbar-secondary,
	.navbar-rotate-tertiary .navbar-secondary {
	  top: 100%;
	  -webkit-transition: -webkit-transform 0.5s;
	  -moz-transition: -moz-transform 0.5s;
	  transition: transform 0.5s;
	  -webkit-transform: rotateX(0deg) translateY(-100%);
	  -moz-transform: rotateX(0deg) translateY(-100%);
	  transform: rotateX(0deg) translateY(-100%);
	}
	
	.navbar-rotate-secondary-fallback .navbar-primary,
	.navbar-rotate-tertiary-fallback .navbar-primary {
	  display: none;
	}
	
	.navbar-rotate-tertiary .navbar-secondary {
	  -webkit-transform: translateY(-100%) rotateX(90deg);
	  -moz-transform: translateY(-100%) rotateX(90deg);
	  transform: translateY(-100%) rotateX(90deg);
	}
	
	.navbar-rotate-tertiary .navbar-tertiary {
	  top: 100%;
	  -webkit-transition: -webkit-transform 0.5s;
	  -moz-transition: -moz-transform 0.5s;
	  transition: transform 0.5s;
	  -webkit-transform: rotateX(0deg) translateY(-100%);
	  -moz-transform: rotateX(0deg) translateY(-100%);
	  transform: rotateX(0deg) translateY(-100%);
	}

<html>

<head>

	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

</head>

<body>

	<nav id="navigation-bottom" class="navbar navbar-fixed-bottom">
		<div class="navbar-perspective">
			<div class="navbar-primary">
				<a href="javascript:void(0);" onclick="$('#navigation-bottom').attr('class','navbar navbar-fixed-bottom navbar-rotate-secondary')">Rotate To Face 2</a>
			</div>
			<div class="navbar-secondary">
				<a href="javascript:void(0);" onclick="$('#navigation-bottom').attr('class','navbar navbar-fixed-bottom navbar-rotate-tertiary')">Rotate To Face 3</a>
			</div>
			<div class="navbar-tertiary">
				<a href="javascript:void(0);" onclick="$('#navigation-bottom').attr('class','navbar navbar-fixed-bottom navbar-rotate-primary')">Rotate Back To Face 1</a>
			</div>
		</div>
	</nav>

</body>

</html>
&#13;
&#13;
&#13;

我已经使用3D效果正确旋转前两个面,但第三个面看起来并不正确。当你从第二个旋转到第三个时,你会注意到顶部没有正确旋转并且看起来很平。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:7)

Fiddle with a flipping box

这与你开始时的情况截然不同,但是让我发布我的CSS并向你展示小提琴,然后我将编辑一个更长的解释,说明其工作原理和原因:

<强> HTML

<section class="container">
    <nav id="nav-box" class="show-front">
        <div class="front">
            <a href="#">Show Bottom</a>
        </div>
        <div class="bottom">
            <a href="#">Show Back</a></div>
        <div class="back">
            <a href="#">Show Top</a></div>
        <div class="top">
            <a href="#">Show Front</a></div>
    </nav>
</section>

<强> CSS

.container {
  position: relative;
  perspective: 1000px;
  transform: scale(0.95);
}

#nav-box {
  width: 100%;
  height: 50px;
  position: absolute;
  transform-origin: center center;
  transform-style: preserve-3d;
  transition: transform 0.5s;
}

#nav-box div {
  width: 100%;
  height: 50px;
  display: block;
  position: absolute;
  transition: background-color 0.5s;
}

#nav-box .front  { transform: rotateX(   0deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .back   { transform: rotateX( 180deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .top    { transform: rotateX(  90deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .bottom { transform: rotateX( -90deg ) translateZ( 25px ); background-color: #ccc; }

#nav-box.show-front  { transform: rotateY(    0deg ); }
#nav-box.show-front .bottom { background-color: #a0a0a0; }
#nav-box.show-front .top { background-color: #e0e0e0; }
#nav-box.show-back   { transform: rotateX( -180deg ); }
#nav-box.show-back .bottom { background-color: #e0e0e0; }
#nav-box.show-back .top { background-color: #a0a0a0; }
#nav-box.show-top    { transform: rotateX(  -90deg ); }
#nav-box.show-top .front { background-color: #a0a0a0; }
#nav-box.show-top .back { background-color: #e0e0e0; }
#nav-box.show-bottom { transform: rotateX(   90deg ); }
#nav-box.show-bottom .front { background-color: #e0e0e0; }
#nav-box.show-bottom .back { background-color: #a0a0a0; }

HTML / CSS

的说明

设置我们的方框

你开始考虑错误的方式,我讨厌说。你接近这个“我如何将这四个方面视为一个盒子”而不是“如何在CSS中创建一个盒子?”

让我们学习如何制作一个盒子。

首先,我们建立一个box容器。由于这是一个导航框,我们称之为nav-box。我们应用的所有变换(除了阴影,我们将在稍后得到)将在我们的nav-box上完成。

我们nav-box上的规则将决定它作为一个对象的行为方式。我们来讨论两个:transform-origintransform-style

transform-origin默认为中心,但我想在这里打电话给它。这基本上是告诉我们的方框:嘿,我们需要你围绕你的绝对中心。如果我们将其设置为transform-origin: center bottom' it would look like the box is spinning around its bottom edge.中心顶部`,它会围绕其顶部边缘旋转。不过,我认为这不是你想要的。

transform-style需要设置为preserve-3d。这样做是指示浏览器不要对其下面有transform的元素大惊小怪。其他选项包括flat,它告诉浏览器忽略它下面的旋转。我们想在preserve-3d nav-box设置transforms的原因是为了确保当我们transform父母时保留我们应用于框边的nav-box。干净的东西,嗯?

设置我们的方面

我们将我们作为rotateX的孩子,并按照他们应该使用0的顺序进行定位:

    前面的
  • 180deg轮换
  • 后面的
  • -90deg
  • 90deg底部
  • .left { transform: rotateY(-90deg); } .right { rotateY(90deg); }为顶部

我们现在也可以使用Y设置左侧和右侧。请注意,我们在这两个示例中使用了translateZ轴。

其次,我们设置了25px 25px的值。那到底是怎么回事?它告诉我们的方框他们需要从父母的中心相对于他们各自的旋转移动25px。我们为什么选择show-front?因为它正好是我们每个盒子高度的一半。这意味着它可以很好地与两边的边缘齐平。

然后是有趣的部分:

我们根据盒子的位置和面向屏幕的方式对盒子进行着色。背景颜色相对于我们用show-backpreserve-3d等显示的框的哪一侧。底部的侧面变暗,顶部的侧面变浅。我只是喜欢它 - 完全没有必要完成这项任务,但让它看起来更加真实。

希望有所帮助!


IE的更新

<强> Fiddle Example

所以,一旦我们为IE修复它,就没有太多相关的了,但现在就是这样。所有preserve-3d正在做的是在我们旋转容器时为您应用变换,而不是展平它们。如果我们无法使用.rewind,我们必须根据总轮换量进行计算。

这个解决方案就是这样做的。我不会深入讨论这个问题,而是强调这需要多少JavaScript,并突出显示#nav-box.rewind div { backface-visibility: hidden; } 类:

backface-visibility

因为我们必须手动回放此解决方案,所以我们必须防止在错误的时间应用z-index重新排序。这就是{{1}}的用武之地。

<强> Example showing depth in IE

<强> Another example without the need for the rewind class

希望能为您解决 IE

答案 1 :(得分:-1)

首先,感谢所有评论并回答这个问题的人,特别是Josh!

Josh,您的示例适用于支持preserve-3d的浏览器。您在没有保存-3d的情况下发布的更新在IE上显得平淡,因此对于所有浏览器来说仍然没有完善。

经过三天的头痛,我意识到了这个问题。双方的起源没有正确设置。侧面需要围绕Z轴中间的一个点旋转。

我将原点更新为:

transform-origin: 25px 25px -25px;

一旦这是正确的,你真正需要做的就是更新对象的旋转。无需使用X,Y,Z坐标的任何变换。

这是3D导航栏的小提琴和解决方案,可以旋转并适用于所有浏览器,包括IE10 +。

http://jsfiddle.net/tx0emcxe/