81

如何rotateX(50deg) rotateY(20deg) rotateZ(15deg)在速记中结合rotate3d()

4

4 回答 4

315

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, α),您有矩阵

通用旋转矩阵

在哪里

解释


您现在获得了 3 个变换中的每一个的矩阵,rotate3d并将它们相乘。并且得到的矩阵是对应于得到的 single 的矩阵rotate3d。不知道如何轻松地从中提取值rotate3d,但肯定很容易为单个matrix3d.


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

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

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

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

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

而第四个显然是0 0 0 1


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

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

第二行:0 1 0 0

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

第四:0 0 0 1


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

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

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

第三和第四行分别是0 0 1 00 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 α。然后计算x, y, z.

在这种特殊情况下,如果我计算正确,则由三个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)

于 2013-03-04T18:51:06.220 回答
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);
}

在这里摆弄

Caniuse 在这里

更多关于它的文档

于 2013-03-04T17:39:16.697 回答
7

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

这适用于 chrome: 1. 将您想要的任何变换应用于元素。2. 下次要添加变换时,将其添加到计算的变换中:“window.getComputedStyle(element).transform” - 但确保将新变换放在左侧。3. 现在你的变换看起来像“rotateZ(30deg) matrix3d(......)。 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>

于 2015-03-07T04:27:51.417 回答
3

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

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

于 2013-03-04T18:09:11.073 回答