Rotate3d стенография

263
7

Как объединить rotateX(50deg) rotateY(20deg) rotateZ(15deg) в сокращенном rotate3d()?

спросил(а) 2013-03-04T20:26:00+04:00 6 лет, 9 месяцев назад
4
Решение
546

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, α) у вас есть матрица


generic rotate matrix


где


explanation

Теперь вы получаете матрицы для каждого из преобразований 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 соответственно.

Примечание. Возможно, вы заметили, что знаки значений sin для преобразования rotateY отличаются от значений двух других преобразований. Это не ошибка вычисления. Причина этого в том, что для экрана у вас ось y направлена ​​вниз, а не вверх.

Итак, это три матрицы 4x4, которые необходимо размножить, чтобы получить матрицу 4x4 для результирующего одиночного преобразования rotate3d. Как я уже сказал, я не уверен, насколько легко получить 4 значения, но 16 элементов в матрице 4x4 являются именно 16 параметрами эквивалента matrix3d цепного преобразования.

ИЗМЕНИТЬ


На самом деле это оказывается довольно легко... Вы вычисляете трассировку (сумму диагональных элементов) матрицы для матрицы rotate3d.


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


Затем вы вычисляете трассировку для произведения трех матриц 4x4, вы приравниваете результат с помощью 2 + 2*cos(α) вы извлекаете α. Затем вы вычисляете x, y, z.


В этом конкретном случае, если я правильно вычислил, след матрицы, получаемой из произведения трех матриц 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, что означает, что α = acos(T/2 - 1).

ответил(а) 2013-03-04T21:51:00+04:00 6 лет, 9 месяцев назад
Еще 3 ответа
118

Синтаксис:


rotate3d(x, y, z, a)

значения:


    x
    Является a <number>, описывающим x-координату вектора, обозначающего ось вращения.
    y
    Является a <number>, описывающим y-координату вектора, обозначающего ось вращения.
    z
    Является a <number>, описывающим z-координату вектора, обозначающего ось вращения.
    a
    Является <angle>, представляющим угол поворота. Положительный угол обозначает вращение по часовой стрелке, отрицательный угол против часовой стрелки.

Как в:

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

Спрятано здесь


Caniuse здесь


Дополнительные документы об этом

ответил(а) 2013-03-04T20:39:00+04:00 6 лет, 9 месяцев назад
93

В зависимости от того, что вы пытаетесь сделать, этот "взлом" может вам помочь. Скажем, вы делаете анимацию, и вы хотите добавить преобразование после преобразования и т.д., И вы не хотите, чтобы CSS выглядел так, как будто он выполняет 100 преобразований:


Это работает в chrome:
 1. Примените любое преобразование, которое вы хотите к элементу.
 2. В следующий раз, когда вы захотите добавить преобразование, добавьте его в вычисленное преобразование:    "window.getComputedStyle(элемент).transform" - но обязательно поставьте новое преобразование влево.
 3. Теперь ваше преобразование будет выглядеть как "rotateZ (30deg) matrix3d ​​(......).
 4. В следующий раз, когда вы захотите добавить другое преобразование, повторите процесс - Chrome всегда уменьшает преобразование к нотации matrix3d.


TL; DR - примените любые преобразования, которые вы хотите, а затем получите вычисленное преобразование matrix3d.


Этот прием также позволяет быстро (то есть, не делая математику самостоятельно) сделать функциональность, которая вращает объект по отношению к вашей системе отсчета в любом направлении. См. Пример ниже:


EDIT. Я добавил также переводы xyz. Используя это, было бы очень просто разместить объекты в определенных трехмерных местах с определенными ориентациями. Или... представьте себе куб, который отскакивает и меняет его ось вращения с каждым отскоком в зависимости от того, как он приземляется!


	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-07T07:27:00+03:00 4 года, 9 месяцев назад
63

Точное значение rotate3d(133,32,58,58deg)


Смотрите fiddle (для хром и Safari, используя -webkit-transform)

ответил(а) 2013-03-04T21:09:00+04:00 6 лет, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема