Tranform rotate with degrees in the same rotation - css

I am trying to rotate a cube with keyframes so it keeps rotating in the same direction with no rotation backwards and keeps rotating horizontally in one direction without reverse on infinite.
<div class="cube">
<div class="cube-face front"></div>
<div class="cube-face back"></div>
<div class="cube-face right"></div>
<div class="cube-face left"></div>
<div class="cube-face top"></div>
<div class="cube-face bottom"></div>
</div>
CSS degrees run over 360 and don't seem to stop... As you can see with the current keyframes the cube will rotate backwards, is there a solution to keep it going with CSS?
.cube {
width: 250px;
height: 250px;
position: relative;
transform-style: preserve-3d;
transform: rotateX(315deg) rotateY(-45deg);
animation: rotate-cube 5s infinite;
margin-bottom: 50px;
cursor: pointer;
}
.cube-face {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 250px;
height: 250px;
border: 2px solid black;
font-size: 90px !important;
font-weight: bold;
color: #000;
}
.cube .front {
background: #f15d2a;
transform: rotateY(0deg) translateZ(125px);
}
.cube .right {
background: #0063a6;
transform: rotateY(90deg) translateZ(125px);
}
.cube .back {
background: #ed1652;
transform: rotate(0deg) rotateY(180deg) translateZ(125px);
}
.cube .left {
background: #12b259;
transform: rotateX(0) rotateY(-90deg) translateZ(125px);
}
.cube .top {
background: #fff;
transform: rotateY(0deg) rotateX(90deg) translateZ(125px);
}
.cube .bottom {
background: #ffd54c;
transform: rotatey(90deg) rotateX(-90deg) translateZ(125px);
}
#keyframes rotate-cube {
0% {
transform: rotateX(315deg) rotateY(-45deg);
}
33.33% {
transform: rotateX(315deg) rotateY(-135deg);
}
66.66% {
transform: rotateX(315deg) rotateY(-225deg);
}
100% {
transform: rotateX(315deg) rotateY(-45deg);
}
}
See example on codepen

Assuming you want the end and start to have the same rotation, you can set the final rotation to -405deg (360 + 45).
This should make sure the animation continues in the correct direction.
0% {
transform: rotateX(315deg) rotateY(-45deg);
}
33.33% {
transform: rotateX(315deg) rotateY(-135deg);
}
66.66% {
transform: rotateX(315deg) rotateY(-225deg);
}
100% {
transform: rotateX(315deg) rotateY(-405deg);
}

Related

CSS Animation with an infinitely rotating cube

I am trying to make an animation of a rotating cube in 3D but the problem is i want the animation to not have any delay between rotations and i just cant get it to work, right now the cube rotates but it stops for a second before it starts the next rotating animation.
(apparently i need more explanation to post this so ignore the following part)
//
I am trying to make an animation of a rotating cube in 3D but the problem is i want the animation to not have any delay between rotations and i just cant get it to work, right now the cube rotates but it stops for a second before it starts the next rotating animation
//
*,
*::before,
*::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
background-color: #eee;
min-height: 100vh;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
}
.container {
width: 400px;
height: 400px;
border: 2px solid white;
border-radius: 4px;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
-webkit-perspective: 800px;
perspective: 800px;
-webkit-perspective-origin: top left;
perspective-origin: top left;
}
.cube {
position: relative;
width: 200px;
height: 200px;
animation-name: rotation;
animation-duration: 4s;
animation-delay: 7s;
animation-iteration-count: infinite;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
#keyframes rotation {
from {
transform: rotateZ(0deg)
}
/*
50% {
transform: rotateZ(360deg);
} */
to {
transform: rotateZ(360deg)
}
}
.side {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.9;
border: 2px solid white;
}
.front {
background-color: #d50000;
-webkit-transform: translateZ(100px);
transform: translateZ(100px);
}
.back {
background-color: #aa00ff;
-webkit-transform: translateZ(-100px);
transform: translateZ(-100px);
}
.left {
background-color: #304ffe;
-webkit-transform: rotateY(90deg) translateZ(100px);
transform: rotateY(90deg) translateZ(100px);
}
.right {
background-color: #0091ea;
-webkit-transform: rotateY(-90deg) translateZ(100px);
transform: rotateY(-90deg) translateZ(100px);
}
.top {
background-color: #00bfa5;
-webkit-transform: rotateX(90deg) translateZ(100px);
transform: rotateX(90deg) translateZ(100px);
}
.bottom {
background-color: #64dd17;
-webkit-transform: rotateX(-90deg) translateZ(100px);
transform: rotateX(-90deg) translateZ(100px);
}
.
<body>
<div class="container">
<div class="cube">
<div class="side front"></div>
<div class="side left"></div>
<div class="side right"></div>
<div class="side back"></div>
<div class="side top"></div>
<div class="side bottom"></div>
</div>
</div>
</body
Rotation stops because of the default animation-timing-function which by default is ease.
So it starts and ends very slowly.
Try to use another value linear.
As the word suggests Linear starts and ends linearly.
For more explanation see this
Code snippet
*,
*::before,
*::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
background-color: #eee;
min-height: 100vh;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
}
.container {
width: 400px;
height: 400px;
border: 2px solid white;
border-radius: 4px;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
-webkit-perspective: 800px;
perspective: 800px;
-webkit-perspective-origin: top left;
perspective-origin: top left;
}
.cube {
position: relative;
width: 200px;
height: 200px;
animation-name: rotation;
animation-duration: 4s;/*SPEED*/
animation-delay: 7s;/*REMOVE IF NEEDED*/
animation-iteration-count: infinite;
animation-timing-function: linear;/*EDITED HERE*/
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
#keyframes rotation {
from {
transform: rotateZ(0deg)
}
/*
50% {
transform: rotateZ(360deg);
} */
to {
transform: rotateZ(360deg)
}
}
.side {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.9;
border: 2px solid white;
}
.front {
background-color: #d50000;
-webkit-transform: translateZ(100px);
transform: translateZ(100px);
}
.back {
background-color: #aa00ff;
-webkit-transform: translateZ(-100px);
transform: translateZ(-100px);
}
.left {
background-color: #304ffe;
-webkit-transform: rotateY(90deg) translateZ(100px);
transform: rotateY(90deg) translateZ(100px);
}
.right {
background-color: #0091ea;
-webkit-transform: rotateY(-90deg) translateZ(100px);
transform: rotateY(-90deg) translateZ(100px);
}
.top {
background-color: #00bfa5;
-webkit-transform: rotateX(90deg) translateZ(100px);
transform: rotateX(90deg) translateZ(100px);
}
.bottom {
background-color: #64dd17;
-webkit-transform: rotateX(-90deg) translateZ(100px);
transform: rotateX(-90deg) translateZ(100px);
}
<div class="container">
<div class="cube">
<div class="side front"></div>
<div class="side left"></div>
<div class="side right"></div>
<div class="side back"></div>
<div class="side top"></div>
<div class="side bottom"></div>
</div>
</div>
Add animation-timing-function: linear; to the .cube code.

How to center the rotation of a 3d css object

I'm trying to get my head around transforms and 3d animation perspectives for css. I have created a piece of code that displays an 8 sided die and then rotates it for the viewer.
However, the die seems to rotate around an invisible center object,
rather than the center of the die being the center point for the rotation animation.
I realize that I must not be grasping something about the code I have written through trial and error.
Here is a fiddle to show what I mean about the way the shape seems to rotate around an invisible center: https://jsfiddle.net/4qbLct3b/
Instead, I want the center of the 3 dimensional object to be the center point of the rotation animation.
HTML
body {
perspective: 9000px;
padding-top: 10%;
}
.d8 {
height: 64px;
width: 64px;
margin: auto;
}
.tetra {
position: relative;
height: 86.6%;
width: 100%;
margin: 0 auto;
transform-style: preserve-3d;
transform: rotatex(0deg) rotateY(0deg) rotatez(0deg);
animation: rotate 10s linear infinite;
}
.tetra div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
-webkit-clip-path: polygon(50% -2.5%, 102.5% 102.5%, -2.5% 102.5%);
clip-path: polygon(50% -2.5%, 102.5% 102.5%, -2.5% 102.5%);
-webkit-clip-path: border-box;
clip-path: border-box;
background: teal;
transform-origin: 0% 100%;
transform: rotatex(35deg);
transform-style: preserve-3d;
}
.tetra .face2 {
transform-origin: 0% 100%;
transform: rotatey(90deg) rotatex(-35deg);
background: gold;
}
.tetra .face3 {
transform-origin: 0% 100%;
left: 100%;
transform: rotatey(90deg) rotatex(35deg);
background: red;
}
.tetra .face4 {
transform-origin: 0% 100%;
transform: rotateY(-90deg) translateX(-100%) rotateY(90deg) rotatex(-35deg);
background: black;
}
.tetra .face5 {
transform-origin: 0% 100%;
transform: rotateY(-90deg) translateX(-100%) rotateY(90deg) rotatex(-145deg);
background: orange;
}
.tetra .face6 {
transform-origin: 0% 100%;
left: 100%;
transform: rotatey(90deg) rotatex(145deg);
background: green;
}
.tetra .face7 {
transform-origin: 0% 100%;
transform: rotatey(90deg) rotatex(-145deg);
background: brown;
}
.tetra .face8 {
background: grey;
transform-origin: 0% 100%;
transform: rotatex(145deg);
}
#keyframes rotate {
50% {
transform: rotatex(180deg) rotateY(180deg) rotatez(180deg);
}
100% {
transform: rotatex(360deg) rotateY(360deg) rotatez(360deg);
}
}
<div class="d8">
<div class="tetra">
<div class="face1"></div>
<div class="face2"></div>
<div class="face3"></div>
<div class="face4"></div>
<div class="face5"></div>
<div class="face6"></div>
<div class="face7"></div>
<div class="face8"></div>
</div>
</div>

Creating a cube opening animation

I have the following HTML and CSS code to draw the top of a cube. So it moves down and I want it to animate as if it is opening up. I am unable to figure out how to transform the top so that it appears to open up.
I have included the entire code for the cube. With respect to this, I want the top to open up.
.pers500 {
perspective: 500px;
-webkit-perspective: 500px;
-moz-perspective: 500px;
}
/* Define the container div, the cube div, and a generic face */
.container {
width: 25%;
margin: 0 auto;
margin-top: 2em;
border: none;
animation-name: moveDown;
animation-duration: 2s;
animation-timing-function: linear;
transform: translate(0px, 110px);
}
.cube {
width: 70%;
height: 70%;
backface-visibility: visible;
perspective-origin: 150% 150%;
transform-style: preserve-3d;
-webkit-backface-visibility: visible;
-webkit-perspective-origin: 150% 150%;
-webkit-transform-style: preserve-3d;
}
.face {
display: block;
position: absolute;
border: none;
line-height: 100px;
font-family: sans-serif;
font-size: 60px;
color: white;
text-align: center;
}
/* Define each face based on direction */
.front {
width: 3.64em;
height: 3.43em;
background-color: rgba(0, 255, 0, 0.7);
transform: translateZ(50px) translateX(171px) translateY(222px);
-webkit-transform: translateZ(50px) translateX(171px) translateY(222px);
-moz-transform: translateZ(50px) translateX(171px) translateY(222px);
}
.left {
width: 2em;
height: 3.4em;
background-color: rgba(0, 0, 255, 0.7);
margin: 70px;
transform: skewY(40deg) translateZ(50px);
-webkit-transform: skewY(40deg) translateZ(50px) translateY(65px) translateX(-20px);
-moz-transform: skewY(40deg) translateZ(50px) translateY(62px) translateX(-20px);
}
.top {
width: 3.65em;
height: 1.7em;
background-color: rgba(255, 0, 0, 0.7);
margin: 100px;
transform: skewX(50deg) translateZ(50px) translateX(-14px) translateY(20px);
-webkit-transform: skewX(50deg) translateZ(50px) translateX(-14px) translateY(20px);
;
-moz-transform: skewX(50deg) translateZ(50px) translateX(-14px) translateY(20px);
;
animation-name: openTop;
animation-duration: 2s;
animation-timing-function: linear;
}
#-webkit-keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes openTop {
/*0% {transform:rotateX(30deg);}
50% {transform:rotateX(30deg);}
100% {transform:rotateX(30deg);} commented code here doesn't work*/
}
<div class="container">
<div class="cube pers500">
<div class="face front"></div>
<div class="face top"></div>
<br>
<br>
<br>
<div class="face left"></div>
</div>
</div>
To make the cube open up, you first need to set the transform-origin property (as mentioned in the other answer) to top. This setting would make the top side of the .face.top remain fixed when the rotation is being performed. Then you need to add the rotation using rotateX(). This would rotate the top face to produce the opening effect. Note that the transform property should contain the entire list of transforms for it to open correctly. You cannot just add the rotateX() alone within the animation.
.pers500 {
perspective: 500px;
}
/* Define the container div, the cube div, and a generic face */
.container {
width: 25%;
margin: 0 auto;
margin-top: 2em;
border: none;
animation-name: moveDown;
animation-duration: 2s;
animation-timing-function: linear;
transform: translate(0px, 110px);
}
.cube {
width: 70%;
height: 70%;
backface-visibility: visible;
perspective-origin: 150% 150%;
transform-style: preserve-3d;
}
.face {
display: block;
position: absolute;
border: none;
line-height: 100px;
font-family: sans-serif;
font-size: 60px;
color: white;
text-align: center;
border: 1px solid brown; /* just for testing */
}
/* Define each face based on direction */
.front {
width: 3.64em;
height: 3.43em;
background-color: rgba(0, 255, 0, 0.7);
transform: translateZ(50px) translateX(171px) translateY(222px);
}
.left {
width: 2em;
height: 3.43em;
background-color: rgba(0, 0, 255, 0.7);
margin: 70px;
transform: skewY(40deg) translateZ(50px) translateY(64px) translateX(-20px);
}
.top {
width: 3.65em;
height: 1.69em;
background-color: rgba(255, 0, 0, 0.7);
margin: 100px;
transform: skewX(50deg) translateZ(50px) translateX(-74px) translateY(20px) rotateX(0deg);
transform-origin: top;
animation-name: openTop;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
#-webkit-keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes openTop {
0% {
transform: skewX(50deg) translateZ(50px) translateX(-74px) translateY(20px) rotateX(0deg);
}
100% {
transform: skewX(50deg) translateZ(50px) translateX(-74px) translateY(20px) rotateX(200deg);
}
}
<div class="container">
<div class="cube pers500">
<div class="face front"></div>
<div class="face top"></div>
<br>
<br>
<br>
<div class="face left"></div>
</div>
</div>
Note:
Setting a transform-origin will affect the position of the top face in the demo and so the values that you've used for translateX() and translateY() on the top face need to be modified a bit like in the above demo.
The vendor prefixed versions of properties should always be added before the standard property in order to be future proof.
I have removed the vendor prefixed versions in the above snippet just to keep it simple.
Set the transform origin to tbe edge of the cube with
transform-origin: 0 50% 0;
Then rotate it around the z axis:
transform: rotateZ(90deg);
I hope this works for you, I didn't have the chance to test it.

Rotate a cube around it's diagonal

I have this cube that I rotate it so I would look trough it's diagonal. How could I rotate this cube around this particular diagonal? I tried different rotations but nothing seems to fit me.
I am looking for CSS only solution/explenation.
.container {
width: 200px;
height: 200px;
position: absolute;
perspective: 10000px;
left: 50vw;
top: 50vh;
transform: translateX(-50%) translateY(-50%);
}
.cube {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
}
.cube figure {
margin: 0;
width: 100%;
height: 100%;
display: block;
position: absolute;
border: 2px solid black;
box-sizing: border-box;
}
.cube .front {
transform: rotateY(0deg) translateZ(100px);
}
.cube .back {
transform: rotateX(180deg) translateZ(100px);
}
.cube .right {
transform: rotateY(90deg) translateZ(100px);
}
.cube .left {
transform: rotateY(-90deg) translateZ(100px);
}
.cube .top {
transform: rotateX(90deg) translateZ(100px);
}
.cube .bottom {
transform: rotateX(-90deg) translateZ(100px);
}
.cube {
transform: rotateY(35deg) rotateX(45deg);
}
.cube:hover {
transition: all 1s;
transform: rotateY(35deg) rotateX(45deg);
}
<section class="container">
<div class="cube">
<figure class="front"></figure>
<figure class="back"></figure>
<figure class="right"></figure>
<figure class="left"></figure>
<figure class="top"></figure>
<figure class="bottom"></figure>
</div>
</section>
Found it - this solved my problem (hover over cube).
Explanation: the transform stack is evaluated from right to left. So, if we want to rotate an element that is transformed around the z axis, we need to set this transform the first one.
If the original is
transform: translateX(-50%) translateY(-50%);
then
transform: rotateZ(value) translateX(-50%) translateY(-50%);
will rotate the element around the viewer z axis (the desired effect)
transform: translateX(-50%) translateY(-50%) rotateZ(value);
would rotate the element around its Z axis
.container {
width: 200px;
height: 200px;
position: absolute;
perspective: 10000px;
left: 50vw;
top: 50vh;
transform: translateX(-50%) translateY(-50%);
}
.cube {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
}
.cube figure {
margin: 0;
width: 100%;
height: 100%;
display: block;
position: absolute;
border: 2px solid black;
box-sizing: border-box;
}
.cube .front { transform: rotateY( 0deg ) translateZ( 100px ); }
.cube .back { transform: rotateX( 180deg ) translateZ( 100px ); }
.cube .right { transform: rotateY( 90deg ) translateZ( 100px ); }
.cube .left { transform: rotateY( -90deg ) translateZ( 100px ); }
.cube .top { transform: rotateX( 90deg ) translateZ( 100px ); }
.cube .bottom { transform: rotateX( -90deg ) translateZ( 100px ); }
.cube {
transform: rotateY(35deg) rotateX(45deg);
}
.cube:hover {
transition: all 1s;
transform:rotateZ(60deg) rotateY(35deg) rotateX(45deg);
}
<section class="container">
<div class="cube">
<figure class="front"></figure>
<figure class="back"></figure>
<figure class="right"></figure>
<figure class="left"></figure>
<figure class="top"></figure>
<figure class="bottom"></figure>
</div>
</section>

Extrude effect with scaleZ

Is it possible to use scaleZ() to effectively create a 3D box?
Here's what I've tried, but obviously it didn't scaleZ at all:
.box {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: scaleZ(10);
-moz-transform: scaleZ(10);
-ms-transform: scaleZ(10);
-o-transform: scaleZ(10);
transform: scaleZ(10);
width: 100px;
height: 100px;
display: block;
background:red;
}
Is there another way I can tackle this? Even if I have to use Javascript?
DEMO: http://jsfiddle.net/3r1gus9f/
ScaleZ() doesn't "extrude", it would required elements to have a thickness which they don't.
ScaleZ is particular in the way that in most cases it won't have any visible effect (as in your example) and requires other 3d transforms to be visible, example :
.w{
display:inline-block;
perspective:500px;
border:1px solid red;
}
.b{
width:150px;
height:150px;
transform-origin:0 0;
transform: rotatey(45deg);
background:pink;
}
.b2{
transform: scaleZ(10) rotatey(45deg);
}
<div class="w">
no scaleZ()
<div class="b"></div>
</div>
<div class="w">
scaleZ(10)
<div class="b b2"></div>
</div>
For an explanation of the calculations behind this, see What does the scaleZ() CSS transform function do?.
A common way to make a 3d cube with CSS is to use 6 surfaces and to transform them into the 6 planes of a cube, you could do this :
#cube {
position: relative;
width: 200px; height:200px;
margin: 100px auto;
perspective: 500px;
perspective-origin: 50% 10%;
}
#cube div {
font-size: 2rem;
position: absolute;
width: 200px; height: 200px;
background: rgba(0, 0, 0, 0.2);
border: 1px solid #000;
}
.back {
transform: translateZ(-100px) rotateY(180deg);
}
.right {
transform: rotateY(-270deg) translateX(100px);
transform-origin: top right;
}
.left {
transform: rotateY(270deg) translateX(-100px);
transform-origin: center left;
}
.top {
transform: rotateX(-90deg) translateY(-100px);
transform-origin: top center;
}
.bottom {
transform: rotateX(90deg) translateY(100px);
transform-origin: bottom center;
}
.front {
transform: translateZ(100px);
}
<div id="cube">
<div class="front">front</div>
<div class="back">back</div>
<div class="top">top</div>
<div class="bottom">bottom</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
I found out that the value for a scaling in Z axes is multiple with a value of translate for the Z axes. So you have to also apply translateZ in order to apply scaleZ.
transform: scaleZ(10) translateZ(1px);
see fiddle http://jsfiddle.net/jakethashi/ey8j5345/

Resources