rotation3d速记


Answers:


314

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

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

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

所以...

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

相当于

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


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

通用旋转矩阵

哪里

说明


现在rotate3d,您将获得3个变换中每个变换的矩阵,并将它们相乘。生成的矩阵是对应于生成的single的矩阵rotate3d。不确定从中提取值的方法有多容易,但是从中提取值rotate3d肯定很容易matrix3d


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

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

因此,在这种情况下,矩阵的第一行是1 0 0 0

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

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

显然,第四个是0 0 0 1


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

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

第二行:0 1 0 0

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

第四: 0 0 0 1


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

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

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

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


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


因此,这是4x4您需要相乘的三个矩阵,以获得4x4用于得到的单个rotate3d转换的矩阵。就像我说过的那样,我不确定取出4个值有多么容易,但是4x4矩阵中的16个元素恰好是matrix3d等效链式转换的16个参数。


编辑

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

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

然后,您可以计算这三个4x4矩阵的乘积的迹线,并将结果与2 + 2*cos(α)extract相等α。然后你计算xyz

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

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

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


6
是的,我什至不知道该如何检查。我完全要去看罪了。因为它打开了我的视野。当我看到罪恶时。大喊王牌基地
安德鲁·卢林

1
@AndrewLuhring了不起。
13年

1
注意,仅当[x,y,z]向量被归一化时,即,向量长度Math.sqrt(x*x + y*y + z*z)为一时,旋转矩阵才适用。如果未归一化,则可以轻松地将其转换为归一化的形式,方法是每次潜水xy并按z其长度进行。
Jose Rui Santos

您必须持有数学美术硕士学位。谢谢你的这首诗,安娜!
伊达

@安德鲁(Andrew):别担心,罪恶对我们许多人都有利...叹息。
大卫说恢复莫妮卡2014年

15

句法:

rotate3d(x, y, z, a)

值:

  • x<number>对表示旋转轴的矢量的x坐标的描述。
  • y<number>描述表示旋转轴的矢量的y坐标。
  • z<number>对表示旋转轴的矢量的z坐标的描述。
  • a<angle>代表旋转角度。正角表示顺时针旋转,负角表示逆时针旋转。

像 :

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

在这里摆弄

可以在这里

关于它的更多文档


6
也许我很胖,但是我认为他要求的是一种从链式转换到单一转换的算法rotate3d,而不是对的定义rotate3d
2013年

3
我想他想知道如何在CSS
中用

7

根据您要执行的操作,此“ hack”可以为您提供帮助。假设您正在制作动画,并且想要在转换之后添加转换,依此类推,并且您不希望CSS看起来像是在进行100转换:

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

TL; DR-应用所需的任何变换,然后获取计算出的matrix3d变换。

此技巧还可以使您快速(即,无需自己做任何数学运算)就可以实现使对象相对于参考框架沿任何方向旋转的功能。请参阅以下示例:

编辑:我也添加了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>


这是有史以来最有用的帖子之一,谢谢
damiano celent 2016年

3

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

查看小提琴(对于chrome和Safari,使用-webkit-transform)


12
如何精确计算?
2013年

1
@Ana我不是,这就是为什么您的答案要好10倍:)
Bigood
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.