<style>
body{
background:black;
overflow:hidden;
transform-style:preserve-3d;
}
.container{
100px;
height:100px;
position:absolute;
transform-style:preserve-3d;
transform:rotateX(-45deg) rotateY(30deg) translate(-50%,-50%);
top:40%;
left:50%;
}
ul{
list-style:none;
padding-left:0px;
100px;
height:100px;
position:absolute;
transform-style:preserve-3d;
}
ul li{
100px;
height:100px;
position:absolute;
background:gray;
}
ul li:nth-of-type(1) {
transform:translateX(-50px) rotateY(-90deg);
}
ul li:nth-of-type(2) {
transform:translateY(-50px) rotateX(90deg);
}
ul li:nth-of-type(3) {
transform:translateZ(50px) rotateY(0deg);
}
ul li:nth-of-type(4) {
transform:translateZ(-50px) rotateY(180deg);
}
ul li:nth-of-type(5) {
transform:translateY(50px) rotateX(90deg);
}
ul li:nth-of-type(6) {
transform:translateX(50px) rotateY(90deg);
}
/*left face*/
ul[data-x="-1"] li:nth-of-type(1){
background:purple;
}
/*right face*/
ul[data-x="1"] li:nth-of-type(6){
background:red;
}
/*top face*/
ul[data-y="-1"] li:nth-of-type(2){
background:blue;
}
/*bottom face*/
ul[data-y="1"] li:nth-of-type(5){
background:green;
}
/*front face*/
ul[data-z="1"] li:nth-of-type(3){
background:white;
}
/*back face*/
ul[data-z="-1"] li:nth-of-type(4){
background:yellow;
}
ul li span{
color:silver;
font-size:30px;
display:block;
30px;
height:30px;
position:absolute;
text-align:center;
line-height:30px;
display:none;
}
ul li span:nth-of-type(1){
top:35px;
left:10px;
}
ul li span:nth-of-type(2){
top:10px;
left:35px;
}
ul li span:nth-of-type(3){
top:35px;
right:10px;
}
ul li span:nth-of-type(4){
bottom:10px;
left:35px;
}
ul li:hover span{
display:block;
}
ul li:hover span:hover{
cursor:pointer;
}
</style>
<style id="keyframes"></style>
<div class="container"></div>
<script type="text/template" id="template">
<li>
<span data-action="left">⇐</span>
<span data-action="up">⇑</span>
<span data-action="right">⇒</span>
<span data-action="down">⇓</span>
</li>
</script>
<script>
var cube = {
init: function() {
// 生成dom节点
var container = document.querySelector('.container');
var template = document.querySelector('#template');
var indexs = [-1, 0, 1];
var num = 1;
this.blocks = [];
for (var k = 0; k < 3; k++) {
for (var j = 0; j < 3; j++) {
for (var i = 0; i < 3; i++) {
var ul = document.createElement('ul');
var transform = ['translateX(', indexs[i] * 110, 'px)',
'translateY(', indexs[j] * 110, 'px)',
'translateZ(', indexs[k] * 110, 'px)'].join('');
ul.style.setProperty('transform', transform);
ul.setAttribute('data-num', num++);
ul.setAttribute('data-x', indexs[i]);
ul.setAttribute('data-y', indexs[j]);
ul.setAttribute('data-z', indexs[k]);
ul.setAttribute('data-coordinate', [indexs[i], indexs[j], indexs[k]].join(''));
ul.x = indexs[i];
ul.y = indexs[j];
ul.z = indexs[k];
var html = template.innerHTML;
var htmls = [html, html, html, html, html, html];
ul.innerHTML = htmls.join('');
this.blocks.push(ul);
container.appendChild(ul);
}
}
}
this.bindEvent();
},
bindEvent: function() {
var self = this;
document.addEventListener('click', function(e) {
var target = e.target;
if (target.nodeName.toLowerCase() == 'span') {
var action;
(action = target.getAttribute('data-action')) && this.actionDirector(target.parentNode, action);
e.stopPropagation();
}
}.bind(this));
},
actionDirector: function(li, action) {
var ul = li.parentNode;
var index = [].indexOf.call(ul.children, li);
var mapping = ['left', 'top', 'front', 'back', 'bottom', 'right'];
var faceName = mapping[index];
var configs = {
left: {
up: {
axis: 'z',
direction: 1
},
down: {
axis: 'z',
direction: -1
},
left: {
axis: 'y',
direction: -1
},
right: {
axis: 'y',
direction: 1
}
},
right: {
up: {
axis: 'z',
direction: -1
},
down: {
axis: 'z',
direction: 1
},
left: {
axis: 'y',
direction: -1
},
right: {
axis: 'y',
direction: 1
}
},
top: {
up: {
axis: 'x',
direction: 1
},
down: {
axis: 'x',
direction: -1
},
left: {
axis: 'z',
direction: -1
},
right: {
axis: 'z',
direction: 1
}
},
bottom: {
up: {
axis: 'x',
direction: -1
},
down: {
axis: 'x',
direction: 1
},
left: {
axis: 'z',
direction: 1
},
right: {
axis: 'z',
direction: -1
}
},
front: {
up: {
axis: 'x',
direction: 1
},
down: {
axis: 'x',
direction: -1
},
left: {
axis: 'y',
direction: -1
},
right: {
axis: 'y',
direction: 1
}
},
back: {
up: {
axis: 'x',
direction: -1
},
down: {
axis: 'x',
direction: 1
},
left: {
axis: 'y',
direction: -1
},
right: {
axis: 'y',
direction: 1
}
}
};
var config = configs[faceName][action];
this.changeKeyframes(config.axis, ul[config.axis], config.direction);
this.rotateFace(config.axis, ul[config.axis], config.direction).forEach(function(block) {
block.className = 'rotate' + block.getAttribute('data-coordinate');
})
},
changeKeyframes: function(axis, index, direction) {
var face = this.getFace(axis, index);
var style = document.querySelector('#keyframes');
style.innerHTML = "";
for (var i = 0; i < face.length; i++) {
var transform = getComputedStyle(face[i]).getPropertyValue('transform');
var x = face[i].x;
var y = face[i].y;
var z = face[i].z;
var className = "rotate" + face[i].getAttribute('data-coordinate');
var origin = {
x: [(-x) * 110 + 50, (-y) * 110 + 50, (-z) * 110],
}
var origin = origin.x[0] + 'px ' + origin.x[1] + 'px ' + origin.x[2] + 'px ';
style.innerHTML += "." + className + " { animation: " + className + " 1s linear backwards; transform-origin: " + origin + "} @keyframes " + className + "{ to{ transform:" + transform + " rotate" + axis.toUpperCase() + "(" + direction * 90 + "deg); } }"
}
},
// 获取一面 比如x轴第1面 axis = 'x' index = 1
getFace: function(axis, index) {
return this.blocks.filter(function(block) {
return block[axis] == index;
});
},
// 获取一条
getBar: function(axis, index, faceName) {
var face = this.getFace(axis, index);
var configs = {
x: {
front: {
axis: 'z',
index: 1,
sortAxis: 'y',
sortDirection: 1,
faceIndex: 3
},
back: {
axis: 'z',
index: -1,
sortAxis: 'y',
sortDirection: -1,
faceIndex: 4
},
top: {
axis: 'y',
index: -1,
sortAxis: 'z',
sortDirection: 1,
faceIndex: 2
},
bottom: {
axis: 'y',
index: 1,
sortAxis: 'z',
sortDirection: -1,
faceIndex: 5
}
},
y: {
front: {
axis: 'z',
sortAxis: 'x',
sortDirection: 1,
index: 1,
faceIndex: 3
},
back: {
axis: 'z',
sortAxis: 'x',
sortDirection: -1,
index: -1,
faceIndex: 4
},
left: {
axis: 'x',
sortAxis: 'z',
sortDirection: 1,
index: -1,
faceIndex: 1
},
right: {
axis: 'x',
sortAxis: 'z',
sortDirection: -1,
index: 1,
faceIndex: 6
}
},
z: {
top: {
axis: 'y',
sortAxis: 'x',
sortDirection: 1,
index: -1,
faceIndex: 2
},
bottom: {
axis: 'y',
sortAxis: 'x',
sortDirection: -1,
index: 1,
faceIndex: 5
},
left: {
axis: 'x',
sortAxis: 'y',
sortDirection: -1,
index: -1,
faceIndex: 1
},
right: {
axis: 'x',
sortAxis: 'y',
sortDirection: 1,
index: 1,
faceIndex: 6
}
}
};
var config = configs[axis][faceName];
return face.filter(function(block) {
return block[config.axis] == config.index;
}).sort(function(a, b) {
if (a[config.sortAxis] < b[config.sortAxis]) {
return -1 * config.sortDirection;
}
if (a[config.sortAxis] > b[config.sortAxis]) {
return 1 * config.sortDirection;
}
return 0;
}).map(function(block) {
var a, b;
(axis == 'x') && (a = 1, b = 6);
(axis == 'y') && (a = 2, b = 5);
(axis == 'z') && (a = 3, b = 4);
return [block.querySelector('li:nth-of-type(' + config.faceIndex + ')'),
block.querySelector('li:nth-of-type(' + a + ')'),
block.querySelector('li:nth-of-type(' + b + ')')
];
});
},
// axis表示坐标轴 'x'、'y'、'z'
// index-1 0 1 左中右
// direction 1 -1 旋转方向
rotateFace: function(axis, index, direction) {
var results = this.getFace(axis, index);
var self = this;
var length = results.length;
var block = results[length - 1];
block.end && block.removeEventListener('animationend', block.end, false);
block.addEventListener('animationend', block.end = function rotate() {
if (rotate.already) return;
rotate.already = true;
self.changeColor(axis, index, direction);
}, false);
return results;
},
changeColor: function(axis, index, direction) {
var face = this.getFace(axis, index);
var configs = {
x :['front', 'top', 'back', 'bottom', 'front'],
y: ['front', 'right', 'back', 'left', 'front'],
z: ['top', 'right', 'bottom', 'left', 'top']
};
var config = (direction == 1) ? configs[axis] : configs[axis].reverse();
var self = this;
var arr = config.map(function(faceName) {
return self.getBar(axis, index, faceName);
});
var colors = arr.map(function(array) {
return array.map(function(lists) {
return lists.map(function(li) {
return getComputedStyle(li).getPropertyValue('background-color');
})
});
});
arr.forEach(function(array, i) {
array.forEach(function(list, j) {
list.forEach(function(li, k) {
if ((i > 0) ) {
li.style.setProperty('background-color', colors[i - 1][j][k])
}
});
});
});
}
};
cube.init();
</script>
<script>
var flag;
function direction(e) {
var position = direction.position = direction.position || {x: 0, y: 0};
var x = e.x;
var y = e.y;
var r = {};
r.x = Math.abs(y - position.y) < 2 ? 0 : y < position.y ? 1 : -1;
r.y = Math.abs(x - position.x) < 2 ? 0 : x < position.x ? -1 : 1;
direction.position.x = x;
direction.position.y = y;
return r;
}
var container = document.querySelector('.container');
document.addEventListener('mousemove', function(e) {
if (!flag) return;
var transform = getComputedStyle(container).getPropertyValue('transform');
var r = direction(e);
container.style.setProperty('transform', transform + 'rotateX(' + r.x * 2 + 'deg) rotateY(' + r.y * 1.5 + 'deg)');
}, false);
document.addEventListener('mousedown', function(e) {
flag = true;
}, false);
document.addEventListener('mouseup', function(e) {
flag = false;
}, false);
</script>