rotate3d скорочення


Відповіді:


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, α)вас є матриця

загальна матриця обертання

де

пояснення


Тепер ви отримуєте матриці для кожного з 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

Отже cos(α) = (T - 2)/2 = T/2 - 1, що означає α = acos(T/2 - 1).


6
так, я навіть не знаю, як це перевірити. Я повністю збирався, поки не побачив гріх. бо це відкрило мій розум. коли я побачив гріх. крик туза основи
Ендрю Лурінг

1
@AndrewLuhring Дивовижно.
aendrew

1
Зверніть увагу, що матриця обертання застосовується лише в тому випадку, якщо [x,y,z]вектор нормалізований, тобто лише якщо довжина вектора Math.sqrt(x*x + y*y + z*z)одна. Якщо його не нормувати, його можна легко перетворити на нормований, зануривши кожногоx , yта zза їх довжиною.
Хосе Руї Сантос

Ви повинні мати магістра образотворчого мистецтва з математики. Дякую за цей вірш, Ана!
Іда

@Andrew: не хвилюйся, гріх покращує багатьох з нас ... зітхай.
Девід каже, щоб відновити Моніку

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.
Ана

3
Я думаю, що він хоче знати, як поєднати rotateX (50deg) rotateY (20deg) rotateZ (15deg) у скороченні rotate3d () в CSS
Milche Patern

7

Залежно від того, що ви намагаєтесь зробити, цей "хак" може вам допомогти. Скажімо, ви робите анімацію, і ви хочете додати перетворення після перетворення і так далі, і ви не хочете, щоб CSS виглядав так, ніби він робить 100 перетворень:

Це працює в chrome: 1. Застосуйте будь-яке перетворення, яке ви хочете, до елемента. 2. Наступного разу, коли ви захочете додати перетворення, додайте його до обчислюваного перетворення: "window.getComputedStyle (element) .transform" - але обов’язково поставте нове перетворення ліворуч. 3. Тепер ваше перетворення буде виглядати як "rotateZ (30deg) matrix3d ​​(......). 4. Наступного разу, коли ви захочете додати ще одне перетворення, повторіть процес - Chrome завжди зводить перетворення до позначень matrix3d.

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

Цей трюк також дозволяє швидко (тобто, не роблячи жодної математики самостійно) зробити функціонал, який обертає об’єкт відносно вашої системи відліку в будь-якому напрямку. Дивіться зразок нижче:

EDIT : Я також додав переклади 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>


Це один з найкорисніших дописів коли-небудь, thnak you
damiano celent

3

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

Дивіться скрипку (для chrome та Safari, використовуючи -webkit-transform)


12
Як саме ви обчислюєте це?
Ана

1
@Ana Я не знаю, тому ваша відповідь у 10 разів краща :)
Bigood
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.