如何使用CSS移动透视图中的元素?

问题描述 投票:0回答:1

正如您在 codepen.io 下看到的,我使用 CSS 在 3D 结构中构建了 3D 立方体(橙色)的透视图。

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

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: preserve-3d;
  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 {
  left: 200px;
  top: 75px;
  position: absolute;
  width: calc(var(--side) + 1);
  height: calc(var(--side) + 1);
  transform-style: preserve-3d;
  /*transform: translateZ(var(--side));*/
  animation: spin 15s infinite linear;
}

.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(--mSides));
}

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

我设法使用 JS 函数 setValues() 动态构建它,其中“side”是橙色立方体的边宽度(以 px 为单位),“rowsCols”是每边的立方体数量。 我想将橙色立方体放置在定义的结构中,但我没有找到如何在所有 3D 轴上移动一个单位。 有人知道怎么做吗?

代码演示:

setValues(40, 3)

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`
  }
  //console.log(str)
  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
  }

  //console.log(str)
  document.getElementById("style").innerHTML = str
}
:root {
  --side: 40px;
  --rowCols: 3;
  --wh: 121px;
  --mside: -40px;
  --twoSides: -80px;
}

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: preserve-3d;
  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 {
  left: 200px;
  top: 75px;
  position: absolute;
  width: calc(var(--side) + 1);
  height: calc(var(--side) + 1);
  transform-style: preserve-3d;
  /*transform: translateZ(var(--side));*/
  animation: spin 15s infinite linear;
}

.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(--mSides));
}

@keyframes spin {
  from {
    transform: rotate3d(1, 1, 0, 0deg);
  }
  to {
    transform: rotate3d(1, 1, 0, 360deg);
  }
}
<style id="style"></style>
<div class="canvas">
  <div class="grid" id="grid">
    <div class="face"></div>
  </div>
  <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>

css 3d perspective
1个回答
0
投票

过了一段时间,我找到了让橙色立方体成为网格结构或更好地说类的一部分的方法。我修改了一些 HTML、CSS 和 JS。新版本已在 [codepen.io V2][1] 中提供 HTML:

    <style id="style"></style>
    <div class="canvas">
      <div class="grid" id="grid"></div>
      </div>
    </div>

CSS:


    :root {
      --side: 40px;
      --rowCols: 3;
      --wh: 121px;
      --mside: -40px;
      --twoSides: -80px;
    }
    
    body {
      background-color: blue;
    }
    
    .canvas {
      position: absolute;
      left: 60px;
      top: 60px;
      transform-style: preserve3d;
      perspective: 800px;
    }
    
    .grid {
      position: absolute;
      transform-style: preserve-3d;
      animation: spin 15s infinite linear;
    }
    
    .grid .face {
      position: absolute;
      height: var(--wh);
      width: var(--wh);
      background-image:
        repeating-linear-gradient(#000 0 1px, transparent 1px 100%),
        repeating-linear-gradient(90deg, #000 0 1px, transparent 1px 100%);
      background-size: var(--side) var(--side);
    }
    
    .cube {
      position: absolute;
      width: calc(var(--side) + 1);
      height: calc(var(--side) + 1);
      transform-style: preserve-3d;
    }
    
    .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(2) {
        transform: translateZ(var(--side));
    }
    
    .cube .cface:nth-child(3) {
        transform-origin: center right;
        transform: rotateY(90deg);
    }
    
    .cube .cface:nth-child(4) {
        transform-origin: center left;
        transform: rotateY(-90deg);
    }
    
    .cube .cface:nth-child(5) {
        transform-origin: top center;
        transform: rotateX(90deg);
    }
    
    .cube .cface:nth-child(6) {
        transform-origin: bottom center;
        transform: rotateX(-90deg);
    }
    
    @keyframes spin {
      from {
        transform: rotate3d(1, 1, 1, 0deg);
      }
      to {
        transform: rotate3d(1, 1, 1, 360deg);
      }
    }

setValues(40, 3)
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`
  }
  //console.log(str)
  str = `${str}<div class="cube">\n`
  for (let n = 0; n < 6; n++){
    str = `${str}<div class="cface"></div>\n`
  }
  document.getElementById("grid").innerHTML = str + `</div>`
  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
  }
  //console.log(str)
  document.getElementById("style").innerHTML = str
}


  [1]: https://codepen.io/Philippe-Lagarrigue/pen/yLwjKoR



© www.soinside.com 2019 - 2024. All rights reserved.