如何rotateX(50deg) rotateY(20deg) rotateZ(15deg)
在速记中结合rotate3d()
?
4 回答
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 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 α
。然后计算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)
。
句法:
rotate3d(x, y, z, a)
价值观:
x
<number>
描述表示旋转轴的向量的 x 坐标 。y
是<number>
描述表示旋转轴的向量的 y 坐标。z
是<number>
描述表示旋转轴的矢量的 z 坐标。a
是一个<angle>
表示旋转的角度。正角表示顺时针旋转,负角表示逆时针旋转。
像 :
.will-distort{
transform:rotate3d(10, 10, 10, 45deg);
}
取决于你想要做什么,这个“黑客”可以帮助你。假设您正在制作动画,并且您希望在转换之后添加转换等等,并且您不希望 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>
确切的值是rotate3d(133,32,58,58deg)
查看小提琴(对于 chrome 和 Safari,使用 -webkit-transform)