Winplax
Winplax

Reputation: 1

Keep fixed axes when rotating cube with css and javascript

I have a cube made in html and css, with javascript, I rotate the cube when I press the arrows on the keyboard, the cube in general rotates correctly on the X and Y axes, however, when I locate on the top or bottom faces I try to turn it to the right or left (around the Y axis), it does not rotate correctly, it seems that it does it around the Z axis.

right arrow on top face https://i.sstatic.net/I48cV.png"

left arrow on bottom face https://i.sstatic.net/WSGIL.png"

I would like the cube to turn correctly, regardless of the position it is in and to know if it is possible to keep the axes of rotation fixed or if there is some other alternative solution.

https://jsfiddle.net/Winplax/cxfe2ko3/10/

I have investigated this behavior and everything is due to the fact that each time the cube rotates the axes of rotation also do so, with the exception of the X axis (arrows up and down), which apparently is not affected in the rotation. I have tried to use the rotation around the Z axis in search of a solution but without any results so far.

I have also seen that they offer near solutions using the matrix3d ​​property, but with little clean results and some failures. I have also used the rotate3d property of css, but I have not managed to correctly implement the rotation with that property.

(function () {
  var rotateY = 0, rotateX = 0;
  document.onkeydown = function (e) {
  	// left: 37, up: 38, right: 39, down: 40,
    if (e.keyCode === 37) rotateY -= 90;
    else if (e.keyCode === 38) rotateX += 90;
    else if (e.keyCode === 39) rotateY += 90;
    else if (e.keyCode === 40) rotateX -= 90;
    document.querySelector('.cube').style.transform = 'rotateX('+rotateX+'deg)'+'rotateY('+rotateY+'deg)';
  }
})();
body {
	background-image: url(http://subtlepatterns2015.subtlepatterns.netdna-cdn.com/patterns/blackorchid.png);
}

.container {
	position: relative;
	margin: 20px auto;
  margin-top: 50px;
	width: 200px;
	height: 200px;
	perspective: 800px;
}

.cube {
  width: inherit;
  height: inherit;
	-webkit-transition: -webkit-transform .5s linear;
	-moz-transition: -moz-transform .5s linear;
	transition: transform .5s linear;
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	transform-style: preserve-3d;
	-webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.side {
	position: absolute;
	width: inherit;
	height: inherit;
	border: 8px solid black;
	font: normal 50px Arial;
	text-align: center;
	line-height: 200px;
	color: #000000;
}

.front {transform: translateZ(108px); background-color: #A5F84C;}
.back {transform: rotateY(180deg) translateZ(108px); background-color: #8EF8F2;}
.right {transform: rotateY(90deg) translateZ(108px); background-color: #F7AE3C;}
.left {transform: rotateY(-90deg) translateZ(108px); background-color: #F569F7;}
.top {transform: rotateX(90deg) translateZ(108px); background-color: #FBF977;}
.bottom {transform: rotateX(-90deg) translateZ(108px); background-color: #FF5757;}
<div class="container">
  <div class="cube">
    <div class="side front">front</div>
    <div class="side back">back</div>
    <div class="side right">right</div>
    <div class="side left">left</div>
    <div class="side top">top</div>
    <div class="side bottom">bottom</div>
  </div>
</div>

Upvotes: 0

Views: 390

Answers (1)

Christopher Bennett
Christopher Bennett

Reputation: 801

This might end up being easier than my previous suggestions..... As with my previous comments, this is not an answer in itself, however I think it might be a big step in the right direction. I just had to post this as an "answer" to be able to post my code.

I updated your javascript to include Z-axis controls, using the left and right (4,6) NumPad keys. Code is here:

(function () {
  var rotateY = 0, rotateX = 0; rotateZ = 0;
  document.onkeydown = function (e) {
    // left: 37, up: 38, right: 39, down: 40, Numpad4: 100, Numpad6: 102
    if (e.keyCode === 37) rotateY -= 90;
    else if (e.keyCode === 38) rotateX += 90;
    else if (e.keyCode === 39) rotateY += 90;
    else if (e.keyCode === 40) rotateX -= 90;
    else if (e.keyCode === 100) rotateZ += 90; // Numpad 4 - use when on top or bottom
    else if (e.keyCode === 102) rotateZ -= 90; //Numpad 6 - use when on top or bottom
    document.querySelector('.cube').style.transform = 'rotateX('+rotateX+'deg)'+'rotateY('+rotateY+'deg) '+'rotateZ('+rotateZ+'deg)';
  }
})();

It seems you are correct that when you rotate the cube around the X-axis, the Y-axis and Z-axis rotate along with it, making the Y-axis behave like the Z-axis and vice-versa. Therefore I have added keys to control the Z-axis. When the cube is on the top or bottom side you can see that the Z-axis controls behave like the Y-axis controls do when it is "upright".

The glaring problem with this solution, however, is that it requires separate keys to navigate the cube properly when it is on its top or bottom side. I have attempted several forms of "if statement" and "state-checker" functions to try and "remap" the left and right keys to the Z-axis when the cube's rotateX === 90 || rotateX === -90, but my efforts have gone to no avail. Perhaps it is because I am tired. Maybe your fresh eyes can see a solution I cannot.

I hope somewhere, in all of what i've posted, you can find something useful. I'll keep working on it and if I find something, i'll let you know. However, if you find the solution before me, I would love to know what it looks like.

Good luck

Upvotes: 1

Related Questions