Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>
like image 278
Sreenidhi Avatar asked Dec 06 '16 13:12

Sreenidhi


2 Answers

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.
like image 146
Harry Avatar answered Nov 09 '22 12:11

Harry


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.

like image 44
Bálint Avatar answered Nov 09 '22 13:11

Bálint