CSS 旋转3d速记

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15207351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 21:53:42  来源:igfitidea点击:

rotate3d shorthand

csscss-transforms

提问by Artem Svirskyi

How to combine rotateX(50deg) rotateY(20deg) rotateZ(15deg)in shorthand rotate3d()?

如何rotateX(50deg) rotateY(20deg) rotateZ(15deg)速记组合rotate3d()

回答by Ana

rotateX(50deg)is equivalent to rotate3d(1, 0, 0, 50deg)

rotateX(50deg)相当于 rotate3d(1, 0, 0, 50deg)

rotateY(20deg)is equivalent to rotate3d(0, 1, 0, 20deg)

rotateY(20deg)相当于 rotate3d(0, 1, 0, 20deg)

rotateZ(15deg)is equivalent to rotate3d(0, 0, 1, 15deg)

rotateZ(15deg)相当于 rotate3d(0, 0, 1, 15deg)

So...

所以...

rotateX(50deg) rotateY(20deg) rotateZ(15deg)

rotateX(50deg) rotateY(20deg) rotateZ(15deg)

is equivalent to

相当于

rotate3d(1, 0, 0, 50deg) rotate3d(0, 1, 0, 20deg) rotate3d(0, 0, 1, 15deg)

rotate3d(1, 0, 0, 50deg) rotate3d(0, 1, 0, 20deg) rotate3d(0, 0, 1, 15deg)



For a generic rotate3d(x, y, z, α), you have the matrix

对于泛型rotate3d(x, y, z, α),你有矩阵

generic rotate matrix

通用旋转矩阵

where

在哪里

explanation

解释



You now get the matrices for each of the 3 rotate3dtransforms and you multiply them. And the resulting matrix is the matrix corresponding to the resulting single rotate3d. Not sure how to easy it is to extract the values for rotate3dout of it, but it's sure easy to extract those for a single matrix3d.

您现在获得了 3 个rotate3d变换中的每一个的矩阵,然后将它们相乘。生成的矩阵是与生成的 single 对应的矩阵rotate3d。不确定从中提取值有多容易rotate3d,但肯定很容易提取单个matrix3d.



In the first case (rotateX(50deg)or rotate3d(1, 0, 0, 50deg)), you have:

在第一种情况(rotateX(50deg)rotate3d(1, 0, 0, 50deg))中,您有:

x = 1, y = 0, z = 0, α = 50deg

x = 1, y = 0, z = 0,α = 50deg

So the first row of the matrix in this case is 1 0 0 0.

所以在这种情况下矩阵的第一行是1 0 0 0

The second one is 0 cos(50deg) -sin(50deg) 0.

第二个是0 cos(50deg) -sin(50deg) 0

The third one 0 sin(50deg) cos(50deg) 0.

第三个0 sin(50deg) cos(50deg) 0

And the fourth one is obviously 0 0 0 1.

而第四个显然是0 0 0 1



In the second case, you have x = 0, y = 1, z = 0, α = 20deg.

在第二种情况下,您有x = 0, y = 1, z = 0, α = 20deg

First row: cos(20deg) 0 sin(20deg) 0.

第一行:cos(20deg) 0 sin(20deg) 0

Second row: 0 1 0 0.

第二行:0 1 0 0

Third row: -sin(20) 0 cos(20deg) 0.

第三行:-sin(20) 0 cos(20deg) 0

Fourth: 0 0 0 1

第四: 0 0 0 1



In the third case, you have x = 0, y = 0, z = 1, α = 15deg.

在第三种情况下,您有x = 0, y = 0, z = 1, α = 15deg

First row: cos(15deg) -sin(15deg) 0 0.

第一行:cos(15deg) -sin(15deg) 0 0

Second row sin(15deg) cos(15deg) 0 0.

第二排sin(15deg) cos(15deg) 0 0

And the third and the fourth row are 0 0 1 0and 0 0 0 1respectively.

第三行0 0 1 0和第四行0 0 0 1分别是和。



Note: you may have noticed that the signs of the sin values for the rotateY transform are different than for the other two transforms. It's not a computation mistake. The reason for this is that, for the screen, you have the y-axis pointing down, not up.

注意:您可能已经注意到,rotateY 变换的 sin 值的符号与其他两个变换的不同。这不是计算错误。这样做的原因是,对于屏幕,y 轴是向下的,而不是向上的。



So these are the three 4x4matrices that you need to multiply in order to get the 4x4matrix for the resulting single rotate3dtransform. As I've said, I'm not sure how easy it can be to get the 4 values out, but the 16 elements in the 4x4 matrix are exactly the 16 parameters of the matrix3dequivalent of the chained transform.

所以这些是4x4您需要相乘的三个矩阵,以获得4x4结果单个rotate3d变换的矩阵。正如我所说的,我不确定获取 4 个值有多容易,但是 4x4 矩阵中的 16 个元素正是matrix3d链式变换等效项的16 个参数。



EDIT:

编辑

Actually, it turns out it's pretty easy... You compute the trace (sum of diagonal elements) of the matrix for the rotate3dmatrix.

实际上,事实证明这很容易……您可以计算矩阵的rotate3d矩阵的迹(对角线元素的总和)。

4 - 2*2*(1 - cos(α))/2 = 4 - 2*(1 - cos(α)) = 2 + 2*cos(α)

4 - 2*2*(1 - cos(α))/2 = 4 - 2*(1 - cos(α)) = 2 + 2*cos(α)

You then compute the trace for the product of the three 4x4matrices, you equate the result with 2 + 2*cos(α)you extract α. Then you compute x, y, z.

然后计算三个4x4矩阵的乘积的迹线,将结果等同于2 + 2*cos(α)您的 extract α。然后计算x, y, z

In this particular case, if I computed correctly, the trace of the matrix resulting from the product of the three 4x4matrices is going to be:

在这种特殊情况下,如果我计算正确,由三个4x4矩阵的乘积产生的矩阵的迹将是:

T = 
cos(20deg)*cos(15deg) + 
cos(50deg)*cos(15deg) - sin(50deg)*sin(20deg)*cos(15deg) + 
cos(50deg)*cos(20deg) + 
1

So cos(α) = (T - 2)/2 = T/2 - 1, which means that α = acos(T/2 - 1).

所以cos(α) = (T - 2)/2 = T/2 - 1,这意味着α = acos(T/2 - 1)

回答by Milche Patern

Syntax:

句法:

rotate3d(x, y, z, a)

Values:

价值观:

  • xIs a <number>describing the x-coordinate of the vector denoting the axis of rotation.
  • yIs a <number>describing the y-coordinate of the vector denoting the axis of rotation.
  • zIs a <number>describing the z-coordinate of the vector denoting the axis of rotation.
  • aIs an <angle>representing the angle of the rotation. A positive angle denotes a clockwise rotation, a negative angle a counter-clockwise one.
  • x<number>描述表示旋转轴的向量的 x 坐标。
  • y<number>描述表示旋转轴的向量的 y 坐标。
  • z<number>描述表示旋转轴的向量的 z 坐标。
  • a<angle>代表旋转的角度。正角表示顺时针旋转,负角表示逆时针旋转。

Like in :

像 :

.will-distort{
    transform:rotate3d(10, 10, 10, 45deg);
}

Fiddled here

在这里摆弄

Caniuse it here

可以在这里使用

More docs about it

有关它的更多文档

回答by Roman Rekhler

Depends on what you are trying to do, this 'hack' could help you. Let's say you are doing animation, and you want add transformation after transformation and so on, and you don't want the CSS to look like it's doing 100's of transformations:

取决于你想要做什么,这个“黑客”可以帮助你。假设您正在制作动画,并且您希望在转换后添加转换等等,并且您不希望 CSS 看起来像是在执行 100 次转换:

This works in chrome: 1. Apply whatever transform you want to an element. 2. Next time you want to add a transform, add it to the computed transform: "window.getComputedStyle(element).transform" - but make sure to put the new transform to the left. 3. Now your transform would look like "rotateZ(30deg) matrix3d(......). 4. Next time you want to add another transform, repeat the process - Chrome always reduces the transforms to matrix3d notation.

这适用于 chrome: 1. 将您想要的任何变换应用于元素。2. 下次要添加变换时,将其添加到计算变换:“window.getComputedStyle(element).transform” - 但确保将新变换放在左侧。3. 现在你的变换看起来像 "rotateZ(30deg) matrix3d(......). 4. 下次你想添加另一个变换时,重复这个过程 - Chrome 总是将变换减少到 matrix3d 表示法。

TL;DR- apply whatever transforms you want, and then get the computed matrix3d transformation.

TL;DR- 应用您想要的任何变换,然后获得计算的 matrix3d 变换。

This trick also lets you quickly (that is, without doing any math by yourself) make a functionality that rotates an object with respect to your reference frame in any direction. See the sample below:

这个技巧还可以让您快速(即,无需自己进行任何数学运算)创建一个功能,该功能可以相对于您的参考系在任何方向上旋转对象。请参阅下面的示例:

EDIT: I have added xyz translations as well. Using this, it would be very easy to place objects in specific 3d locations with specific orientations in mind. Or...imagine a cube that bounces and changes it's spin axis with each bounce depending on how it lands!

编辑:我也添加了 xyz 翻译。使用它,可以很容易地将对象放置在具有特定方向的特定 3d 位置。或者……想象一个立方体,它会弹跳并根据着陆方式在每次弹跳时改变它的自旋轴!

 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>

回答by Bigood

The exact value is rotate3d(133,32,58,58deg)

确切的值是 rotate3d(133,32,58,58deg)

See the fiddle(For chrome and Safari, using -webkit-transform)

请参阅小提琴(对于 chrome 和 Safari,使用 -webkit-transform)