Cómo funciona el anidamiento de elementos transformados en 3D -

PorAna Tudor es

Ana Tudor es una de esas personas cuyos perfiles de CodePen revisas y dice “mierda”. Ella es así de buena. Crea efectos visuales increíbles con CSS, uno de mis favoritos, este prisma infinitamente desempaquetado. ¡A continuación comparte su experiencia y detalla cómo crear hermosas transformaciones 3D anidadas!

Las transformaciones CSS 3D no funcionan en absoluto en IE9 y versiones anteriores ni en Opera 12 y versiones anteriores (Presto). Para obtener información de soporte detallada, visitecaniuse.com.

¡CSS preserve-3destá actualmente en desarrollo y pronto llegará a Internet Explorer!

Las animaciones CSS son increíblemente populares en este momento, y no me refiero solo a animar una simple propiedad de color o dimensión, me refiero también a transformaciones 3D; Los volteos CSS y los cubos giratorios son buenos ejemplos. Podemos encontrar fragmentos de CSS simples y ejemplos de transformaciones, pero es importante que los desarrolladores comprendan exactamente lo que está sucediendo. ¡Déjame guiarte paso a paso a través del proceso de anidar elementos de transformación 3D animados!

Digamos que tenemos una puerta en un marco:

El HTML es simplemente:

div class="contenedor" div class="marco" div class="puerta"/div /div/div

Para abrir esta puerta, agregamos una clase de door--open:

div class="contenedor" div class="marco" div class="puerta puerta--abierta"/div /div/div

Ahora le aplicamos una transformación 3D (en transform-origincualquier parte de su lado izquierdo):

.door--open { transform-origin: 0 0 /*cualquier valor de y que desees*/; transformar: rotarY(-45deg);}

El único prefijo que probablemente necesites para transformaciones 3D es el -webkit-prefijo. IE9 no los admite en absoluto e IE10+ (salvo las primeras vistas previas) los admite sin prefijos. Opera 12 y versiones anteriores (Presto) nunca los admitieron, mientras que Opera Next los admite con el -webkit-prefijo. Firefox los admite sin prefijos desde la versión 16 (desde 2012).

Esto resulta en:

No parece muy realista. La propiedad que se encarga de esto se llama perspectivey hace que las cosas que están más cerca parecen más grandes y las que están más lejos parecen más pequeñas.

La perspectivepropiedad debe aplicarse en el padre del elemento transformado 3D. Aplicarlo en cualquier antepasado funcionará en los navegadores WebKit, pero no en Firefox o IE.

Entonces vamos a agregar una frame--realisticclase al marco de nuestra puerta:

div class="contenedor" div class="marco marco--realista" div class="puerta puerta--abierta"/div /div/div

Ahora le ponemos un perspective. Cuanto menor sea el valor, menor será la distancia desde tus ojos, lo que hará que las cosas que están más cerca parezcan mucho más grandes que las que están más lejos.

.frame--realistic {  perspective: 20em;}

We get the following result:

Now this looks much better! But we can do more! For example, we can also animate the door in 3D. Just replace the door-open class with a door--ani class in the HTML and add the following CSS:

.door--ani {  transform-origin: 0 0;  animation: doorani 1.3s ease-in-out infinite alternate;}@keyframes doorani {  from { transform: rotateY(-43deg); }  to { transform: rotateY(43deg); }}

Result:

Now let’s say we want to also animate the frame a bit in 3D. That should be simple, right? Just add a frame--ani class to the frame, set an animation on it and move the perspective on the container:

The HTML would become:

div class="container container--realistic"  div class="frame frame--ani"    div class="door door--ani"/div  /div/div

And we would need to add the following CSS:

.container--realistic {  perspective: 20em;}.frame--ani {  animation: frameani 2s ease-in-out infinite alternate;}@keyframes frameani {  from { transform: rotateY(-30deg); }  to { transform: rotateY(30deg); }}

But what we get is:

It doesn’t look right anymore. It looks as if the door has been flattened into the plane of its parent. Actually, that’s exactly what happens because the default value of thetransform-style property (which tells the browser whether the 3D transformed children of a 3D transformed element should keep their own 3D transforms or not) has a default value of flat.

This can be fixed by setting transform-style: preserve-3d on the 3D transformed parent (the frame in our case). And then we get this nice result:

However, IE10/11 only support the flat value for the transform-style property. We can sometimes go around this by chaining all the transforms from the parent (and ancestors in general) onto the deepest 3D transformed element.

For example, let’s say we have a slightly rotated cube (without the top and bottom faces for simplicity). The HTML is:

div class="container container--realistic"  div class="cube"    div class="face"/div    div class="face"/div    div class="face"/div    div class="face"/div  /div/div

And the relevant CSS:

.cube {  position: relative;  width: 5em; height: 5em;  transform-style: preserve-3d;  transform: rotateY(30deg) rotateX(10deg);}.face {  position: absolute;  width: 100%; height: 100%;}.face:nth-child(1) {  transform: /*rotateY(0deg)*/ translateZ(2.5em /* half the side length, 5em in this case */);}.face:nth-child(2) {  transform: rotateY( 90deg)   translateZ(2.5em);}.face:nth-child(3) {  transform: rotateY(180deg)   translateZ(2.5em);}.face:nth-child(4) {  transform: rotateY(270deg)   translateZ(2.5em);}

With this code (you can checka more detailed explanation for it if you wish), we get the following result:

To make this work in IE, we need to remove the transform from the cube and chain it before the transforms for each face (and if the cube also had a 3D transformed parent, then we would have to remove that transform from it and chain it onto the transforms for each face before that of the cube). We also move the perspective from the container to the cube. Like this:

.cube--ie {  perspective: 20em;  transform: none;}.face--ie:nth-child(1) {  transform: rotateY(30deg) rotateX(10deg)              translateZ(2.5em);}.face--ie:nth-child(2) {  transform: rotateY(30deg) rotateX(10deg)              rotateY( 90deg) translateZ(2.5em);}.face--ie:nth-child(3) {  transform: rotateY(30deg) rotateX(10deg)             rotateY(180deg) translateZ(2.5em);}.face--ie:nth-child(4) {  transform: rotateY(30deg) rotateX(10deg)             rotateY(270deg) translateZ(2.5em);}

And we get the same result, even in IE:

Not very convenient, but it’s not that bad. Not much more code, not much uglier… Well, the problem appears when we want to animate the cube. As long as we can rely on transform-style: preserve-3d working, we simply need to add a cube--ani class and this little bit of CSS:

.cube--ani {  animation: rot 4s linear infinite;}@keyframes rot {  to { transform: rotateY(-330deg) rotateX(370deg); }}

However, for IE10/11, we cannot have 3D transforms on the cube itself, so we have chained them onto the faces. Which means that’s where we need to animate them. Which means… exactly, one set of keyframes for each face!

.cube--ie {  animation: none;}.cube--ani .face--ie:nth-child(1) {  animation: rot1 4s linear infinite;}@keyframes rot1 {  to {    transform: rotateY(-330deg) rotateX(370deg)                translateZ(2.5em);  }}.cube--ani .face--ie:nth-child(2) {  animation: rot2 4s linear infinite;}@keyframes rot2 {  to {    transform: rotateY(-330deg) rotateX(370deg)                rotateY(90deg) translateZ(2.5em);  }}.cube--ani .face--ie:nth-child(3) {  animation: rot3 4s linear infinite;}@keyframes rot3 {  to {    transform: rotateY(-330deg) rotateX(370deg)                rotateY(180deg) translateZ(2.5em);  }}.cube--ani .face--ie:nth-child(4) {  animation: rot4 4s linear infinite;}@keyframes rot4 {  to {    transform: rotateY(-330deg) rotateX(370deg)                rotateY(270deg) translateZ(2.5em);  }}

All that, in order to achieve the same result:

Y si se requiere tanto código cuando sólo hay cuatro caras, ¿te imaginas el terrible desastre que resultaría al intentar hacer esto con unas 100 caras?

Quizás se pregunte sobre el caso de la puerta, donde el elemento principal (el marco) también tiene una altura y un ancho y es visible. Bueno, la única solución para animar tanto la puerta como el marco en IE10/11 es cambiar el HTML de modo que el marco y la puerta sean hermanos y animarlos individualmente, al mismo tiempo que se encadenan las transformaciones del marco a la puerta.

Acerca de Ana Tudor

Le encantan las matemáticas, especialmente la geometría. Le gusta jugar con código. Apasionado por experimentar y aprender cosas nuevas. Fascinado por la astrofísica y la ciencia en general. Gran aficionado al avance tecnológico y sus aplicaciones en todos los campos. Muestra interés por los deportes de motor, el dibujo, los dibujos animados clásicos, la música rock, los peluches y los animales con garras afiladas y dientes grandes. Sueña con tener un tigre de verdad.

about.me anatudor Publicaciones

Te podría interesar...

Deja una respuesta

Subir