如何在CSS透视视图中沿三维坐标轴移动3D立方体元素?
问题描述
我用CSS构建了带橙色3D立方体的透视视图结构,通过JS的setValues()函数实现了动态构建(side是立方体边长,rowsCols是每侧立方体数量)。现在需要将橙色立方体放置到定义好的网格结构中,但不知道如何让它沿**所有三维坐标轴(X/Y/Z)**移动一个单位(即每次移动等于立方体边长的距离),求实现方法。
解决方案
要实现立方体沿三维坐标轴移动,核心是利用CSS的translate3d()变换,结合已有的CSS变量控制偏移量,同时分离旋转动画与移动逻辑避免样式冲突:
- 给
:root新增三个CSS变量,对应X/Y/Z轴的偏移单位:--translateX: 0; --translateY: 0; --translateZ: 0; - 新增父容器
.cube-container负责旋转动画,原.cube元素专注处理移动,避免动画覆盖transform属性:.cube-container { position: absolute; left: 200px; top: 75px; transform-style: preserve3d; animation: spin 15s infinite linear; } - 修改
.cube的transform属性,用translate3d结合变量实现三维移动:.cube { /* 原有样式保留 */ transform: translate3d(calc(var(--translateX) * var(--side)), calc(var(--translateY) * var(--side)), calc(var(--translateZ) * var(--side))); } - 通过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
相关产品推荐
相关产品推荐

