¿Cómo combinar rotateX(50deg) rotateY(20deg) rotateZ(15deg)en taquigrafía rotate3d()?
fuente
¿Cómo combinar rotateX(50deg) rotateY(20deg) rotateZ(15deg)en taquigrafía rotate3d()?
rotateX(50deg) es equivalente a rotate3d(1, 0, 0, 50deg)
rotateY(20deg) es equivalente a rotate3d(0, 1, 0, 20deg)
rotateZ(15deg) es equivalente a rotate3d(0, 0, 1, 15deg)
Entonces...
rotateX(50deg) rotateY(20deg) rotateZ(15deg)
es equivalente a
rotate3d(1, 0, 0, 50deg) rotate3d(0, 1, 0, 20deg) rotate3d(0, 0, 1, 15deg)
Para un genérico rotate3d(x, y, z, α), tienes la matriz

dónde

Ahora obtienes las matrices para cada una de las 3 rotate3dtransformadas y las multiplicas. Y la matriz resultante es la matriz correspondiente al sencillo resultante rotate3d. No estoy seguro de lo fácil que es extraer los valores rotate3dde él, pero seguro que es fácil extraerlos para uno solo matrix3d.
En el primer caso ( rotateX(50deg)o rotate3d(1, 0, 0, 50deg)), tienes:
x = 1, y = 0 ,z = 0 ,α = 50deg
Entonces, la primera fila de la matriz en este caso es 1 0 0 0 .
El segundo es 0 cos(50deg) -sin(50deg) 0 .
El tercero 0 sin(50deg) cos(50deg) 0 .
Y el cuarto es obviamente 0 0 0 1 .
En el segundo caso, tiene x = 0, y = 1,z = 0 ,α = 20deg .
Primera fila: cos(20deg) 0 sin(20deg) 0 .
Segunda fila: 0 1 0 0 .
Tercera fila: -sin(20) 0 cos(20deg) 0 .
Cuarto: 0 0 0 1
En el tercer caso, tiene x = 0, y = 0,z = 1 ,α = 15deg .
Primera fila: cos(15deg) -sin(15deg) 0 0 .
Segunda fila sin(15deg) cos(15deg) 0 0 .
Y la tercera y la cuarta fila son 0 0 1 0y 0 0 0 1respectivamente.
Nota : puede haber notado que los signos de los valores sin para la transformada rotateY son diferentes a los de las otras dos transformadas. No es un error de cálculo. La razón de esto es que, en la pantalla, el eje Y apunta hacia abajo, no hacia arriba.
Entonces, estas son las tres 4x4matrices que necesita multiplicar para obtener la 4x4matriz de la rotate3dtransformación simple resultante . Como dije, no estoy seguro de lo fácil que puede ser sacar los 4 valores, pero los 16 elementos de la matriz 4x4 son exactamente los 16 parámetros del matrix3dequivalente de la transformación encadenada.
EDITAR :
En realidad, resulta que es bastante fácil ... Calcula la traza (suma de elementos diagonales) de la matriz para la rotate3dmatriz.
4 - 2*2*(1 - cos(α))/2 = 4 - 2*(1 - cos(α)) = 2 + 2*cos(α)
Luego calcula la traza para el producto de las tres 4x4matrices, equipara el resultado con lo 2 + 2*cos(α)que extrae α. A continuación, a calcular x, y, z.
En este caso particular, si calculé correctamente, la traza de la matriz resultante del producto de las tres 4x4matrices será:
T =
cos(20deg)*cos(15deg) +
cos(50deg)*cos(15deg) - sin(50deg)*sin(20deg)*cos(15deg) +
cos(50deg)*cos(20deg) +
1
Entonces cos(α) = (T - 2)/2 = T/2 - 1, lo que significa eso α = acos(T/2 - 1).
[x,y,z]vector está normalizado, es decir, solo si la longitud del vectorMath.sqrt(x*x + y*y + z*z)es uno. Si no se normaliza, fácilmente se puede convertir en un uno normalizado, por buceo de cadax,yyzpor su longitud.Sintaxis:
rotate3d(x, y, z, a)Valores:
xEs un<number>descripción de la coordenada x del vector que denota el eje de rotación.yEs una<number>descripción de la coordenada y del vector que denota el eje de rotación.zEs una<number>descripción de la coordenada z del vector que denota el eje de rotación.aEs una<angle>representación del ángulo de rotación. Un ángulo positivo denota una rotación en el sentido de las agujas del reloj, un ángulo negativo en el sentido contrario a las agujas del reloj.Como en :
.will-distort{ transform:rotate3d(10, 10, 10, 45deg); }Jugado aquí
Puedo usarlo aquí
Más documentos al respecto
fuente
rotate3d, no la definición derotate3d.Depende de lo que intente hacer, este 'truco' podría ayudarlo. Digamos que está haciendo una animación, y quiere agregar transformación tras transformación y así sucesivamente, y no quiere que el CSS parezca que está haciendo cientos de transformaciones:
Esto funciona en Chrome: 1. Aplique cualquier transformación que desee a un elemento. 2. La próxima vez que desee agregar una transformación, agréguela a la transformación calculada: "window.getComputedStyle (element) .transform", pero asegúrese de poner la nueva transformación a la izquierda. 3. Ahora su transformación se vería como "rotateZ (30deg) matrix3d (......). 4. La próxima vez que desee agregar otra transformación, repita el proceso - Chrome siempre reduce las transformaciones a la notación matrix3d.
TL; DR: aplique las transformaciones que desee y luego obtenga la transformación matrix3d calculada.
Este truco también te permite rápidamente (es decir, sin hacer ningún cálculo por ti mismo) crear una funcionalidad que gire un objeto con respecto a tu marco de referencia en cualquier dirección. Vea la muestra a continuación:
EDITAR : También he agregado traducciones xyz. Con esto, sería muy fácil colocar objetos en ubicaciones 3D específicas con orientaciones específicas en mente. O ... ¡imagina un cubo que rebota y cambia su eje de giro con cada rebote dependiendo de cómo aterrice!
var boxContainer = document.querySelector('.translator'), cube = document.getElementById('cube'), optionsContainer = document.getElementById('options'); var dims = ['x', 'y', 'z']; var currentTransform; var currentTranslate; var init = function () { optionsContainer.querySelector('.xRotation input') .addEventListener('input', function (event) { if (currentTransform != 'none') { var newTransform = 'rotateX(' + (360 - event.target.value) + 'deg) ' + currentTransform; } else { var newTransform = 'rotateX(' + (360 - event.target.value) + 'deg)'; } cube.style.transform = newTransform; }, false); optionsContainer.querySelector('.yRotation input') .addEventListener('input', function (event) { if (currentTransform != 'none') { var newTransform = 'rotateY(' + (360 - event.target.value) + 'deg) ' + currentTransform; } else { var newTransform = 'rotateY(' + (360 - event.target.value) + 'deg)'; } cube.style.transform = newTransform; }, false); optionsContainer.querySelector('.zRotation input') .addEventListener('input', function (event) { if (currentTransform != 'none') { var newTransform = 'rotateZ(' + (360 - event.target.value) + 'deg) ' + currentTransform; } else { var newTransform = 'rotateZ(' + (360 - event.target.value) + 'deg)'; } cube.style.transform = newTransform; }, false); optionsContainer.querySelector('.xTranslation input') .addEventListener('input', function (event) { if (currentTranslate != 'none') { var newTransform = 'translateX(' + (100 - event.target.value) + 'px) ' + currentTranslate; } else { var newTransform = 'translateX(' + (100 - event.target.value) + 'px)'; } boxContainer.style.transform = newTransform; }, false); optionsContainer.querySelector('.yTranslation input') .addEventListener('input', function (event) { if (currentTranslate != 'none') { var newTransform = 'translateY(' + (100 - event.target.value) + 'px) ' + currentTranslate; } else { var newTransform = 'translateY(' + (100 - event.target.value) + 'px)'; } boxContainer.style.transform = newTransform; }, false); optionsContainer.querySelector('.zTranslation input') .addEventListener('input', function (event) { if (currentTranslate != 'none') { var newTransform = 'translateZ(' + (500 - event.target.value) + 'px) ' + currentTranslate; } else { var newTransform = 'translateZ(' + (500 - event.target.value) + 'px)'; } boxContainer.style.transform = newTransform; }, false); reset(); }; function reset() { currentTransform = window.getComputedStyle(cube).transform; currentTranslate = window.getComputedStyle(boxContainer).transform; optionsContainer.querySelector('.xRotation input').value = 360; optionsContainer.querySelector('.yRotation input').value = 360; optionsContainer.querySelector('.zRotation input').value = 360; optionsContainer.querySelector('.xTranslation input').value = 100; optionsContainer.querySelector('.yTranslation input').value = 100; optionsContainer.querySelector('.zTranslation input').value = 500; } window.addEventListener('DOMContentLoaded', init, false); document.addEventListener('mouseup', reset, false);.translator { height: 200px; position: absolute; width: 200px; transform-style: preserve-3d; } .threeSpace { height: 200px; moz-perspective: 1200px; o-perspective: 1200px; perspective: 200px; position: absolute; transform-origin: 50px 50px 100px; webkit-perspective: 1200px; width: 100px; perspective-origin: 100px 25px; transform-style: preserve-3d; } #pointer{ position:relative; height:2px; width:2px; top:25px; left:100px; background:blue; z-index:9999; } #cube { height: 100%; moz-transform-origin: 90px 110px 0px; moz-transform-style: preserve-3d; o-transform-origin: 90px 110px 0px; o-transform-style: preserve-3d; position: absolute; transform-origin: 90px 110px 0px; transform-style: preserve-3d; webkit-transform-origin: 90px 110px 0px; webkit-transform-style: preserve-3d; width: 100%; } #cube .midPoint{ position:absolute; top:48px; left:48px; height:1px; width:1px; background:green; } #cube figure { border: 2px solid black; color: white; display: block; font-size: 60px; font-weight: bold; height: 96px; line-height: 96px; position: absolute; text-align: center; width: 96px; /* transform-style: preserve-3d; */ } #cube .front { background: hsl(0, 100%, 50%); } #cube .back { background: hsl(60, 100%, 50%); } #cube .right { background: hsl(120, 100%, 50%); } #cube .left { background: hsl(180, 100%, 50%); } #cube .top { background: hsl(240, 100%, 50%); } #cube .bottom { background: hsl(300, 100%, 50%); } #cube .front { moz-transform: translateZ(50px); o-transform: translateZ(50px); transform: translateZ(50px); webkit-transform: translateZ(50px); } #cube .back { moz-transform: rotateX(-180deg) translateZ(50px); o-transform: rotateX(-180deg) translateZ(50px); transform: rotateX(-180deg) translateZ(50px); webkit-transform: rotateX(-180deg) translateZ(50px); } #cube .right { moz-transform: rotateY(90deg) translateZ(50px); o-transform: rotateY(90deg) translateZ(50px); transform: rotateY(90deg) translateZ(50px); webkit-transform: rotateY(90deg) translateZ(50px); } #cube .left { moz-transform: rotateY(-90deg) translateZ(50px); o-transform: rotateY(-90deg) translateZ(50px); transform: rotateY(-90deg) translateZ(50px); webkit-transform: rotateY(-90deg) translateZ(50px); } #cube .top { moz-transform: rotateX(90deg) translateZ(50px); o-transform: rotateX(90deg) translateZ(50px); transform: rotateX(90deg) translateZ(50px); webkit-transform: rotateX(90deg) translateZ(50px); } #cube .bottom { moz-transform: rotateX(-90deg) translateZ(50px); o-transform: rotateX(-90deg) translateZ(50px); transform: rotateX(-90deg) translateZ(50px); webkit-transform: rotateX(-90deg) translateZ(50px); } #options{ position:absolute; width:80%; top:40%; } #options input { width: 60%; }<body> <div class="threeSpace"> <div id="pointer"></div> <div class="translator"> <div id="cube"> <figure class="front"><div class='midPoint'></div></figure> <figure class="back"></figure> <figure class="right"></figure> <figure class="left"></figure> <figure class="top"></figure> <figure class="bottom"></figure> </div> </div> </div> <section id="options"> <p class="xRotation"> <label>xRotation</label> <input type="range" min="0" max="720" value="360" data-units="deg" /> </p> <p class="yRotation"> <label>yRotation</label> <input type="range" min="0" max="720" value="360" data-units="deg" /> </p> <p class="zRotation"> <label>zRotation</label> <input type="range" min="0" max="720" value="360" data-units="deg" /> </p> <p class="xTranslation"> <label>xTranslation</label> <input type="range" min="0" max="200" value="100" data-units="deg" /> </p> <p class="yTranslation"> <label>yTranslation</label> <input type="range" min="0" max="200" value="100" data-units="deg" /> </p> <p class="zTranslation"> <label>zTranslation</label> <input type="range" min="0" max="1000" value="500" data-units="deg" /> </p> </section> </body>fuente
El valor exacto es
rotate3d(133,32,58,58deg)Ver el violín (para Chrome y Safari, usando -webkit-transform)
fuente