草庐IT

javascript - 3d 框网格(只有两个面)

coder 2025-01-05 原文

我有一个只有两个面(正面和底部)的 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>

现在,此设置的问题是框之间的重叠。我可以手动去除重叠,为此我需要进行以下更改/计算:

  • 更改 .box-wrapperwidthheightmargin(右侧和底部) >
  • 更改.face.front.face.bottomtransform (translateZ)

并且由于一项更改会影响其他更改,因此这是有问题的。

例如,要消除上面设置中的重叠(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>

我还打算让这个移动友好,所以随着窗口宽度的变化,我会改变容器(.grid)的宽度,并进行上述更改。所以我唯一的变量是容器宽度,它会随着窗口宽度而变化,并且一个盒子应该占据容器宽度的 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 以在高度/宽度计算中包含边框,这样您就可以使用一半的高度(250px/2 = 125px)在 translateZ 中。

更新

我向 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>

关于javascript - 3d 框网格(只有两个面),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51533887/

有关javascript - 3d 框网格(只有两个面)的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  3. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  4. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  5. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  6. [Vuforia]二.3D物体识别 - 2

    之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶

  7. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  8. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  9. ruby-on-rails - 只有当不是 nil 时才执行映射? - 2

    如果names为nil,则以下中断。我怎样才能让这个map只有在它不是nil时才执行?self.topics=names.split(",").mapdo|n|Topic.where(name:n.strip).first_or_create!end 最佳答案 其他几个选项:选项1(在其上执行map时检查split的结果):names_list=names.try(:split,",")self.topics=names_list.mapdo|n|Topic.where(name:n.strip).first_or_create!e

  10. arrays - 如何在下面的示例中将两个值数组分组为 n 个值数组? - 2

    我已经有很多两个值数组,例如下面的例子ary=[[1,2],[2,3],[1,3],[4,5],[5,6],[4,7],[7,8],[4,8]]我想把它们分组到[1,2,3],[4,5],[5,6],[4,7,8]因为意思是1和2有关系,2和3有关系,1和3有关系,所以1,2,3都有关系我如何通过ruby​​库或任何算法来做到这一点? 最佳答案 这是基本Bron–Kerboschalgorithm的Ruby实现:classGraphdefinitialize(edges)@edges=edgesenddeffind_maximum_

随机推荐