如何以速记rotateX(50deg) rotateY(20deg) rotateZ(15deg)
组合rotate3d()
?
答案 0 :(得分:313)
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
个变换中每个变换的矩阵,然后将它们相乘。并且得到的矩阵是对应于得到的单个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 0
和0 0 0 1
。
注意 :您可能已经注意到rotateY变换的sin值的符号与其他两个变换的不同。这不是一个计算错误。原因在于,对于屏幕,您的y轴指向下方,而不是向上。
因此,这些是您需要乘以的三个4x4
矩阵,以便为生成的单4x4
转换获取rotate3d
矩阵。正如我所说,我不确定将4个值输出是多么容易,但4x4矩阵中的16个元素恰好是链接变换的matrix3d
等效的16个参数。 / p>
修改强>:
实际上,结果很简单......你计算了rotate3d
矩阵矩阵的轨迹(对角元素之和)。
4 - 2*2*(1 - cos(α))/2 = 4 - 2*(1 - cos(α)) = 2 + 2*cos(α)
然后,您计算三个4x4
矩阵的乘积的跟踪,将结果与提取2 + 2*cos(α)
的{{1}}等同。然后,您计算α
,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
。
答案 1 :(得分: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);
}
答案 2 :(得分: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>
答案 3 :(得分:3)
确切的值为rotate3d(133,32,58,58deg)
请参阅fiddle(对于chrome和Safari,使用-webkit-transform)