View Cube

three.js +css

by Paul West

HTML

<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div class="scene">
  <div class="cube">
    <div class="cube__face cube__face--front">front</div>
    <div class="cube__face cube__face--back">back</div>
    <div class="cube__face cube__face--right">right</div>
    <div class="cube__face cube__face--left">left</div>
    <div class="cube__face cube__face--top">top</div>
    <div class="cube__face cube__face--bottom">bottom</div>
  </div>
</div>

CSS

body {
  font-family: sans-serif;
  margin: 0px;
  overflow: hidden;
  position: relative;
}

.scene {
  width: 100px;
  height: 100px;
  border: 1px solid #CCC;
  margin: 10px;
  perspective: 400px;
  position: absolute;
}

.cube {
  width: 100px;
  height: 100px;
  position: relative;
  transform-style: preserve-3d;
  transform: translateZ(-300px);

  /* transition: transform 1s; */
}

.cube__face {
  position: absolute;
  width: 100px;
  height: 100px;
  border: 2px solid black;
  line-height: 100px;
  font-size: 20px;
  font-weight: bold;
  color: white;
  text-align: center;
}

.cube__face--front {
  background: rgba(0, 0, 255, 0.7);
}

.cube__face--right {
  background: rgba(255, 0, 0, 0.7);
}

.cube__face--back {
  background: rgba(0, 255, 255, 0.7);
}

.cube__face--left {
  background: rgba(255, 0, 255, 0.7);
}

.cube__face--top {
  background: rgba(0, 255, 0, 0.7);
}

.cube__face--bottom {
  background: rgba(255, 255, 0, 0.7);
}

.cube__face--front {
  transform: rotateY(0deg) rotateX(180deg) translateZ(-50px);
}

.cube__face--right {
  transform: rotateY(90deg) rotateX(180deg) translateZ(-50px);
}

.cube__face--back {
  transform: rotateY(180deg) rotateX(180deg) translateZ(-50px);
}

.cube__face--left {
  transform: rotateY(-90deg) rotateX(180deg) translateZ(-50px);
}

.cube__face--top {
  transform: rotateX(-90deg) rotateX(180deg) translateZ(-50px);
}

.cube__face--bottom {
  transform: rotateX(90deg) rotateX(180deg) translateZ(-50px);
}

JavaScript

var cube = document.querySelector('.cube');

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

scene.add(new THREE.GridHelper(10, 10));
scene.add(new THREE.AxesHelper(5));

var geom = new THREE.BoxBufferGeometry(4, 4, 4);
var mats = [
	new THREE.MeshBasicMaterial({color:0xff0000}),
  new THREE.MeshBasicMaterial({color:0xff00ff}),
  new THREE.MeshBasicMaterial({color:0x00ff00}),
  new THREE.MeshBasicMaterial({color:0xffff00}),
  new THREE.MeshBasicMaterial({color:0x0000ff}),
  new THREE.MeshBasicMaterial({color:0x00ffff})
];

var box = new THREE.Mesh(geom, mats);
scene.add(box);

var mat = new THREE.Matrix4();

renderer.setAnimationLoop(() => {

	mat.extractRotation( camera.matrixWorldInverse );

  cube.style.transform = `translateZ(-300px) ${getCameraCSSMatrix( mat )}`;

  renderer.render(scene, camera);
  
});

function getCameraCSSMatrix(matrix) {

  var elements = matrix.elements;

  return 'matrix3d(' +
    epsilon(elements[0]) + ',' +
    epsilon(-elements[1]) + ',' +
    epsilon(elements[2]) + ',' +
    epsilon(elements[3]) + ',' +
    epsilon(elements[4]) + ',' +
    epsilon(-elements[5]) + ',' +
    epsilon(elements[6]) + ',' +
    epsilon(elements[7]) + ',' +
    epsilon(elements[8]) + ',' +
    epsilon(-elements[9]) + ',' +
    epsilon(elements[10]) + ',' +
    epsilon(elements[11]) + ',' +
    epsilon(elements[12]) + ',' +
    epsilon(-elements[13]) + ',' +
    epsilon(elements[14]) + ',' +
    epsilon(elements[15]) +
    ')';

}

function epsilon( value ) {

  return Math.abs( value ) < 1e-10 ? 0 : value;

}