JSFiddle - React, Tailwind, and code Playground
by Julian
HTML
<div id="container">
<ul class="nav">
<li><a data-face="icloud" href="#">iCloud</a></li>
<li><a data-face="phone" href="#">Phone</a></li>
<li><a data-face="logo-l" href="#">Logo-l</a></li>
<li><a data-face="logo-r" href="#">Logo-r</a></li>
<li><a data-face="apple" href="#">Apple</a></li>
<li><a data-face="base" href="#">Base</a></li>
</ul>
<div class="cube">
<div class="face icloud" data-face="icloud">
<section>
<img src="//placehold.it/300x300/ccc&text=icloud">
</section>
<div class="face phone" data-face="phone">
<section>
<img src="//placehold.it/300x300/555&text=phone">
</section>
</div>
<div class="face logo-l" data-face="logo-l">
<section>
<img src="//placehold.it/300x300/666&text=logo-l">
</section>
</div>
<div class="face logo-r" data-face="logo-r">
<section>
<img src="//placehold.it/300x300/333&text=logo-r">
</section>
<div class="face apple" data-face="apple">
<section>
<img src="//placehold.it/300x300/222&text=apple">
</section>
</div>
</div>
<div class="face base" data-face="base">
<section>
<img src="//placehold.it/300x300/000&text=base">
</section>
</div>
</div>
</div>
</div>
SCSS
section {
display: block;
}
$width: 300px;
$height: 300px;
* {
margin: 0;
padding: 0;
}
html, body, #container {
height: 100%;
overflow: hidden;
}
#container {
-webkit-perspective: 1000px;
}
.cube {
width: $width;
height: $height;
position: absolute;
top: 20%;
left: 20%;
margin-left: 0-$width/2;
margin-top: 0-$height/2;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-webkit-transform-origin: $width/2 $height/2 $width/2*-1;
-webkit-transform: rotateY(0);
-webkit-transition: -webkit-transform 0.3s ease;
-webkit-transition-duration: 0.3s;
.face {
position: absolute;
width: $width;
height: $height;
-webkit-transform-origin: 0px 0px;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
background: rgba(0,0,0,0.1);
> section {
position: absolute;
width: $width;
height: $height;
outline: 1px solid #000;
}
}
.icloud {
.phone {
top: 0 - $height;
-webkit-transform-origin: 0 300px;
-webkit-transform: rotateX(90deg);
}
.logo-l {
-webkit-transform: rotateY(-90deg);
-webkit-transform-origin: 300px 0;
left: 0 - $width;
}
.logo-r {
-webkit-transform: rotateY(90deg);
left: $width;
.apple {
left: $width;
-webkit-transform: rotateY(90deg);
}
}
.base {
top: $height;
-webkit-transform: rotateX(-90deg);
}
}
}
JavaScript
/*global $:false */
/*global WebKitCSSMatrix:false */
(function(w,d,undefined) {
/**
* Vector
* (Helper class)
*/
var Vector = function(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
// http://blog.joelambert.co.uk/2011/05/10/handling-3d-geometry-with-3d-css3-transforms/
WebKitCSSMatrix.prototype.transformVector = function(v) {
var xOut = this.m11*v.x + this.m12*v.y + this.m13*v.z;
var yOut = this.m21*v.x + this.m22*v.y + this.m23*v.z;
var zOut = this.m31*v.x + this.m32*v.y + this.m33*v.z;
return new Vector(xOut, yOut, zOut);
};
var facingDirection = function(matrix3dString) {
var values = matrix3dString.match(/\(([\-0-9,.\ ]+)\)/)[1].split(", ");
if (values[0] != 0)
return values[0] == -1 ? "-x" : "x";
if (values[4] != 0)
return values[4] == -1 ? "y" : "y";
if (values[8] != 0)
return values[8] == -1 ? "z" : "z";
}
/**
* Cube
*/
var Cube = function(options) {
var that = this;
this.$ = options.$;
this.$faces = options.$faces;
this.$currentFace = null;
this.moving = false;
this.directions = {
'up': {key: 40},
'right': {key: 37},
'down': {key: 38},
'left': {key: 39}
};
// Absolute positions
// (Used for clicking directly to an element)
this.positions = {
'icloud': {x: 0, y: 0},
'phone': {x: 270, y: 0},
'logo-l': {x: 0, y: 90},
'logo-r': {x: 0, y: 270},
'base': {x: 90, y: 0},
'apple': {x: 0, y: 180}
};
// Move the cube using a vector
// (rather than a relative angle)
$(window).keyup(function(e) {
var direction;
if(that.moving === true) {
return false;
}
$.each(that.directions, function(direction) {
if(e.which === this.key) {
that[direction].call(that);
}
});
});
// Go to an...