You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CSS透视视图中沿三维坐标轴移动3D立方体元素?

问题描述

我用CSS构建了带橙色3D立方体的透视视图结构,通过JS的setValues()函数实现了动态构建(side是立方体边长,rowsCols是每侧立方体数量)。现在需要将橙色立方体放置到定义好的网格结构中,但不知道如何让它沿**所有三维坐标轴(X/Y/Z)**移动一个单位(即每次移动等于立方体边长的距离),求实现方法。

解决方案

要实现立方体沿三维坐标轴移动,核心是利用CSS的translate3d()变换,结合已有的CSS变量控制偏移量,同时分离旋转动画与移动逻辑避免样式冲突:

  1. 给:root新增三个CSS变量,对应X/Y/Z轴的偏移单位:
    --translateX: 0;
    --translateY: 0;
    --translateZ: 0;
    
  2. 新增父容器.cube-container负责旋转动画,原.cube元素专注处理移动,避免动画覆盖transform属性:
    .cube-container {
      position: absolute;
      left: 200px;
      top: 75px;
      transform-style: preserve3d;
      animation: spin 15s infinite linear;
    }
    
  3. 修改.cube的transform属性,用translate3d结合变量实现三维移动:
    .cube {
      /* 原有样式保留 */
      transform: translate3d(calc(var(--translateX) * var(--side)), calc(var(--translateY) * var(--side)), calc(var(--translateZ) * var(--side)));
    }
    
  4. 通过JS动态设置变量值即可控制移动,比如--translateX: 1代表沿X轴正方向移动1个边长单位:
    function setCubePosition(x, y, z) {
      const root = document.querySelector(':root')
      root.style.setProperty('--translateX', x)
      root.style.setProperty('--translateY', y)
      root.style.setProperty('--translateZ', z)
    }
    
修改后的完整代码演示

HTML

<style id="style"></style>
<div class="canvas">
  <div class="grid" id="grid">
    <div class="face"></div>
  </div>
  <div class="cube-container">
    <div class="cube">
      <div class="cface"></div>
      <div class="cface"></div>
      <div class="cface"></div>
      <div class="cface"></div>
      <div class="cface"></div>
      <div class="cface"></div>
    </div>
  </div>
</div>

CSS

:root {
  --side: 40px;
  --rowCols: 3;
  --wh: 121px;
  --mside: -40px;
  --twoSides: -80px;
  --translateX: 0;
  --translateY: 0;
  --translateZ: 0;
}

body {
  background-color: blue;
}

.canvas {
  position: absolute;
  left: 0px;
  top: 10px;
  transform-style: preserve3d;
  perspective: 850px;
}

.grid {
  position: absolute;
  left: 200px;
  top: 75px;
  transform-style: preserve3d;
  animation: spin 15s infinite linear;
}

.grid .face {
  position: absolute;
  height: var(--wh);
  width: var(--wh);
  margin: 0;
  background-image: repeating-linear-gradient(#ccc 0 1px, transparent 1px 100%), repeating-linear-gradient(90deg, #ccc 0 1px, transparent 1px 100%);
  background-size: var(--side) var(--side);
}

.cube-container {
  position: absolute;
  left: 200px;
  top: 75px;
  transform-style: preserve3d;
  animation: spin 15s infinite linear;
}

.cube {
  width: calc(var(--side) + 1);
  height: calc(var(--side) + 1);
  transform-style: preserve3d;
  transform: translate3d(calc(var(--translateX) * var(--side)), calc(var(--translateY) * var(--side)), calc(var(--translateZ) * var(--side)));
}

.cube .cface {
  width: var(--side);
  height: var(--side);
  position: absolute;
  border: 1px solid black;
  display: flex;
  background-color: rgb(238, 141, 14);
}

.cube .cface:nth-child(1) {
  transform: translateZ(var(--side));
}

.cube .cface:nth-child(2) {
  transform-origin: center right;
  transform: rotateY(90deg);
}

.cube .cface:nth-child(3) {
  transform-origin: center left;
  transform: rotateY(-90deg);
}

.cube .cface:nth-child(4) {
  transform-origin: top center;
  transform: rotateX(90deg);
}

.cube .cface:nth-child(5) {
  transform-origin: top center;
  transform: rotateX(90deg) translateZ(var(--mside));
}

.cube .cface:nth-child(6) {
  transform: translateZ(calc(var(--side) * -1));
}

@keyframes spin {
  from {
    transform: rotate3d(1, 1, 0, 0deg);
  }
  to {
    transform: rotate3d(1, 1, 0, 360deg);
  }
}

JavaScript

setValues(40, 3)
// 示例:初始化将立方体移动到(1,1,1)位置
setCubePosition(1, 1, 1)

function setValues(side, rowsCols) {
  let r = document.querySelector(':root')
  r.style.setProperty('--side', `${side}px`)
  r.style.setProperty('--rowCols', `${rowsCols}`)
  r.style.setProperty('--wh', `${side * rowsCols + 1}px`)
  r.style.setProperty('--mside', `-${side}px`)
  r.style.setProperty('--twoSides', `-${side * 2}px`)
  let str = ""
  let max = (rowsCols + 1) * 2
  for (let n = 0; n < max; n++) {
    str = `${str}<div class="face"></div>\n`
  }
  document.getElementById("grid").innerHTML = str

  str = ""
  let pix = side
  let f = 1
  for (; f <= rowsCols; f++) {
    str = `${str}.grid .face:nth-child(${f}){transform: translateZ(${pix}px);}\n`
    pix += side
  }
  pix = 0
  for (; f < max; f++) {
    str = `${str}.grid .face:nth-child(${f}){transform-origin: center right; transform: rotateY(90deg) translateZ(${pix}px);}\n`
    pix -= side
  }

  document.getElementById("style").innerHTML = str
}

function setCubePosition(x, y, z) {
  const root = document.querySelector(':root')
  root.style.setProperty('--translateX', x)
  root.style.setProperty('--translateY', y)
  root.style.setProperty('--translateZ', z)
}

内容的提问来源于stack exchange,提问作者Swiftiti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:57:08