3d 框网格(只有两个面)
Grid of 3d boxes (only two faces)
我有一个只有两个面(正面和底部)的 3d 盒子网格。每个盒子都有自己的视角。悬停时,框旋转;底面朝前。例如:
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: 25%;
height: 250px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s;
transform-style: preserve-3d;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.box .face.front {
transform: translateZ(123.5px);
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateZ(123.5px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg);
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
现在,此设置的问题是框之间的重叠。我可以手动摆脱重叠,为此我需要执行以下操作 changes/calculations:
- 更改
.box-wrapper
的 width
、height
和 margin
(右侧和底部)
- 改变
.face.front
的transform
(translateZ
)和.face.bottom
并且由于一项更改会影响其他更改,因此这是有问题的。
例如,要消除上面设置中的重叠(1000px 容器),需要进行以下更改:
.box-wrapper {
width: calc(25% - 29px); // why 29?
margin-right: 29px;
margin-bottom: 29px;
height: 221px;
}
.box .face.front {
transform: translateZ(110.5px); // half of box's width
}
.box .face.bottom {
transform: rotateX(-90deg) translateZ(110.5px);
}
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: calc(25% - 29px);
margin-right: 29px;
margin-bottom: 29px;
height: 221px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s;
transform-style: preserve-3d;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.box .face.front {
transform: translateZ(110.5px);
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateZ(110.5px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg);
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
我还打算让这个移动设备友好,所以随着 window 宽度的变化,我将更改容器的宽度 (.grid
),并进行上述更改。所以我唯一的变量是容器宽度,它会根据 window 宽度发生变化,并且一个盒子应该占据容器宽度的 25%。我怎样才能自动进行这个计算?由于计算包括透视和变换,我还不能想出任何东西。
即使我手动(试错)计算大屏幕断点的值(宽度,边距,变换),在某些时候我需要用JS自动计算,例如768px以下。
很明显问题出在translateZ
结合透视。你正在通过积极的翻译让你的元素更接近你,并且视角正在创造重叠。
为了避免这种情况,我们需要避免 translateZ
并使用另一个配置来创建类似的效果。这是一个想法:
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: 25%;
height: 250px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s, transform-origin 0.5s;
transform-style: preserve-3d;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
box-sizing:border-box;
}
.box .face.front {
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateY(50%) translateZ(125px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg) translateY(-100%);
transform-origin:top;
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
如您所见,前面的元素不再有 translateZ
,因此最初不再重叠,然后我调整 transform-origin
和平移以补偿应用的 translateZ
到底部元素。
所有使用的值都是使用百分比的相对值,因此您在计算时不会有任何问题。我还添加了 box-sizing:border-box
以在 height/width 计算中包含边框,这样您就可以在 translateZ
.
中使用一半的高度 (250px / 2 = 125px
)
更新
我向 transform-origin
添加了一个过渡,以便以某种方式从中心而不是完全从顶部进行旋转。
更新 2
根据评论中的建议,我们还可以将 transform-orgin
更改为 center center -125px
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: 25%;
height: 250px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s;
transform-style: preserve-3d;
transform-origin:center center -125px;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
box-sizing:border-box;
}
.box .face.front {
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateY(50%) translateZ(125px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg);
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
我有一个只有两个面(正面和底部)的 3d 盒子网格。每个盒子都有自己的视角。悬停时,框旋转;底面朝前。例如:
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: 25%;
height: 250px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s;
transform-style: preserve-3d;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.box .face.front {
transform: translateZ(123.5px);
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateZ(123.5px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg);
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
现在,此设置的问题是框之间的重叠。我可以手动摆脱重叠,为此我需要执行以下操作 changes/calculations:
- 更改
.box-wrapper
的 - 改变
.face.front
的transform
(translateZ
)和.face.bottom
width
、height
和 margin
(右侧和底部)
并且由于一项更改会影响其他更改,因此这是有问题的。
例如,要消除上面设置中的重叠(1000px 容器),需要进行以下更改:
.box-wrapper {
width: calc(25% - 29px); // why 29?
margin-right: 29px;
margin-bottom: 29px;
height: 221px;
}
.box .face.front {
transform: translateZ(110.5px); // half of box's width
}
.box .face.bottom {
transform: rotateX(-90deg) translateZ(110.5px);
}
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: calc(25% - 29px);
margin-right: 29px;
margin-bottom: 29px;
height: 221px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s;
transform-style: preserve-3d;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.box .face.front {
transform: translateZ(110.5px);
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateZ(110.5px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg);
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
我还打算让这个移动设备友好,所以随着 window 宽度的变化,我将更改容器的宽度 (.grid
),并进行上述更改。所以我唯一的变量是容器宽度,它会根据 window 宽度发生变化,并且一个盒子应该占据容器宽度的 25%。我怎样才能自动进行这个计算?由于计算包括透视和变换,我还不能想出任何东西。
即使我手动(试错)计算大屏幕断点的值(宽度,边距,变换),在某些时候我需要用JS自动计算,例如768px以下。
很明显问题出在translateZ
结合透视。你正在通过积极的翻译让你的元素更接近你,并且视角正在创造重叠。
为了避免这种情况,我们需要避免 translateZ
并使用另一个配置来创建类似的效果。这是一个想法:
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: 25%;
height: 250px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s, transform-origin 0.5s;
transform-style: preserve-3d;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
box-sizing:border-box;
}
.box .face.front {
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateY(50%) translateZ(125px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg) translateY(-100%);
transform-origin:top;
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>
如您所见,前面的元素不再有 translateZ
,因此最初不再重叠,然后我调整 transform-origin
和平移以补偿应用的 translateZ
到底部元素。
所有使用的值都是使用百分比的相对值,因此您在计算时不会有任何问题。我还添加了 box-sizing:border-box
以在 height/width 计算中包含边框,这样您就可以在 translateZ
.
250px / 2 = 125px
)
更新
我向 transform-origin
添加了一个过渡,以便以某种方式从中心而不是完全从顶部进行旋转。
更新 2
根据评论中的建议,我们还可以将 transform-orgin
更改为 center center -125px
.grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 1000px;
margin: 50px auto;
}
.box-wrapper {
width: 25%;
height: 250px;
perspective: 1000px;
}
.box {
width: 100%;
height: 100%;
position: relative;
transition: transform .5s;
transform-style: preserve-3d;
transform-origin:center center -125px;
}
.box .face {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
box-sizing:border-box;
}
.box .face.front {
background-color: hsla(0, 100%, 50%, .5);
}
.box .face.bottom {
transform: rotateX(-90deg) translateY(50%) translateZ(125px);
background-color: hsla(120, 100%, 50%, .5);
}
.box:hover {
transform: rotateX(90deg);
}
<div class="grid">
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
<div class="box-wrapper">
<div class="box">
<div class="face front">front face</div>
<div class="face bottom">bottom-face</div>
</div>
</div>
</div>