Orientation Cube

Sample Project using the Orientation API to rotate a cube

See the full list of sample projects.

These sample HTML and CSS files generate a page with a cube that rotates in the device frame to stand still in the world frame.

Here's the HTML:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <title>gravitational-cube</title>
  <link href="orientation-cube.css" rel="stylesheet" type="text/css">
</head>
<body>

  <div class="cube-container">
    <section id="cube">
      <div class="top face"><p>TOP</p></div>
      <div class="bottom face"><p>BOTTOM</p></div>
      <div class="left face"><p>LEFT</p></div>
      <div class="right face"><p>RIGHT</p></div>
      <div class="front face"><p>FRONT</p></div>
      <div class="back face"><p>BACK</p></div>
    </section>
  </div>

  <script src="../lib/motionstack-vlatest.js"></script>

  <script>
    // motion controls
    var angle, x, y, z;
    function tracking(e) {
      var q = e.quaternion;
      var factor = 1 / Math.max(1E-5, Math.sqrt(q.x * q.x + q.y * q.y + q.z * q.z));

      angle = 2.0 * Math.acos(q.w) || 0;
      x = q.x * factor;
      y = -q.y * factor;
      z = q.z * factor;
    }

    var motionOrientation = new MotionStack.Orientation();
    motionOrientation.start(tracking);

    // animation loop
    var $ = document.querySelectorAll.bind(document);
    var cube = $("#cube")[0];
    function rotateCube() {
      cube.style.webkitTransform = "rotate3d("+ x +", "+ y +", "+ z +", "+ angle +"rad) rotateX(-90deg) translateZ(0)";
      cube.style.transform = cube.style.webkitTransform;
    }

    var rotateThisCube = rotateCube.bind(this);
    window.requestAnimationFrame(function loop() {
      if(angle !== undefined) {
        rotateThisCube();
      }

      window.requestAnimationFrame(loop);
    });
  </script>
</body>
</html>

And here's the CSS:

* {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

p {
  font-family: sans-serif;
  color: white;
  font-size: 1.2rem;
}

.cube-container {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-perspective: 1000;
  perspective: 1000;
  -webkit-perspective-origin: 50% 50%;
  perspective-origin: 50% 50%;
}

#cube {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7rem;
  min-height: 7rem;
  max-height: 7rem;
  margin-top: -3.5rem;
  margin-left: -3.5rem;
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
}

.face {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  text-align: center;
}
.face p {
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}
.face.top {
  background-color: #FF0000;
  -webkit-transform: translateY(-50%) rotateX(90deg);
  transform: translateY(-50%) rotateX(90deg);
}
.face.bottom {
  background-color: #FF0000;
  -webkit-transform: translateY(50%) rotateX(-90deg);
  transform: translateY(50%) rotateX(-90deg);
}
.face.left {
  background-color: #00CC00;
  -webkit-transform: translateX(-50%) rotateY(-90deg);
  transform: translateX(-50%) rotateY(-90deg);
}
.face.right {
  background-color: #00CC00;
  -webkit-transform: translateX(50%) rotateY(90deg);
  transform: translateX(50%) rotateY(90deg);
}
.face.front {
  background-color: #0000FF;
  -webkit-transform: rotateY(90deg) translateX(-50%) rotateY(-90deg);
  transform: rotateY(90deg) translateX(-50%) rotateY(-90deg);
}
.face.back {
  background-color: #0000FF;
  -webkit-transform: rotateY(90deg) translateX(50%) rotateY(90deg);
  transform: rotateY(90deg) translateX(50%) rotateY(90deg);
}