tốc ký xoay3d


79

Làm thế nào để kết hợp rotateX(50deg) rotateY(20deg) rotateZ(15deg)trong tốc ký rotate3d()?

Câu trả lời:


314

rotateX(50deg) tương đương với rotate3d(1, 0, 0, 50deg)

rotateY(20deg) tương đương với rotate3d(0, 1, 0, 20deg)

rotateZ(15deg) tương đương với rotate3d(0, 0, 1, 15deg)

Vì thế...

rotateX(50deg) rotateY(20deg) rotateZ(15deg)

tương đương với

rotate3d(1, 0, 0, 50deg) rotate3d(0, 1, 0, 20deg) rotate3d(0, 0, 1, 15deg)


Đối với một cái chung rotate3d(x, y, z, α), bạn có ma trận

ma trận xoay chung

Ở đâu

giải trình


Bây giờ bạn nhận được các ma trận cho mỗi rotate3dphép biến đổi trong số 3 phép biến đổi và bạn nhân chúng lên. Và ma trận kết quả là ma trận tương ứng với đơn kết quả rotate3d. Không chắc làm thế nào để dễ dàng trích xuất các giá trị rotate3dtừ nó, nhưng chắc chắn là dễ dàng để trích xuất các giá trị đó cho một lần matrix3d.


Trong trường hợp đầu tiên ( rotateX(50deg)hoặc rotate3d(1, 0, 0, 50deg)), bạn có:

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

Vì vậy, hàng đầu tiên của ma trận trong trường hợp này là 1 0 0 0.

Cái thứ hai là 0 cos(50deg) -sin(50deg) 0.

Cái thứ ba 0 sin(50deg) cos(50deg) 0.

Và điều thứ tư rõ ràng là 0 0 0 1.


Trong trường hợp thứ hai, bạn có x = 0, y = 1, z = 0, α = 20deg.

Hàng đầu tiên: cos(20deg) 0 sin(20deg) 0.

Hàng thứ hai: 0 1 0 0.

Hàng thứ ba: -sin(20) 0 cos(20deg) 0.

Thứ tư: 0 0 0 1


Trong trường hợp thứ ba, bạn có x = 0, y = 0, z = 1, α = 15deg.

Hàng đầu tiên: cos(15deg) -sin(15deg) 0 0.

Hàng thứ hai sin(15deg) cos(15deg) 0 0.

Và hàng thứ ba và thứ tư là 0 0 1 00 0 0 1tương ứng.


Lưu ý : bạn có thể nhận thấy rằng các dấu hiệu của giá trị sin đối với biến đổi xoayY khác với hai biến đổi còn lại. Đó không phải là một sai lầm tính toán. Lý do cho điều này là đối với màn hình, bạn có trục y hướng xuống chứ không phải hướng lên.


Vì vậy, đây là ba 4x4ma trận mà bạn cần nhân để có được 4x4ma trận cho kết quả rotate3dbiến đổi đơn . Như tôi đã nói, tôi không chắc việc lấy ra 4 giá trị dễ dàng như thế nào, nhưng 16 phần tử trong ma trận 4x4 chính xác là 16 tham số matrix3dtương đương của phép biến đổi chuỗi.


CHỈNH SỬA :

Trên thực tế, hóa ra nó khá dễ dàng ... Bạn tính dấu vết (tổng các phần tử đường chéo) của ma trận cho rotate3dma trận.

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

Sau đó, bạn tính toán dấu vết cho tích của ba 4x4ma trận, bạn cân bằng kết quả với 2 + 2*cos(α)bạn trích xuất α. Sau đó, bạn tính toán x, y, z.

Trong trường hợp cụ thể này, nếu tôi tính toán chính xác, dấu vết của ma trận tạo ra từ tích của ba 4x4ma trận sẽ là:

T = 
cos(20deg)*cos(15deg) + 
cos(50deg)*cos(15deg) - sin(50deg)*sin(20deg)*cos(15deg) + 
cos(50deg)*cos(20deg) + 
1

Vì vậy cos(α) = (T - 2)/2 = T/2 - 1, có nghĩa là vậy α = acos(T/2 - 1).


6
vâng, tôi thậm chí không biết làm thế nào để kiểm tra thực tế điều đó. Tôi hoàn toàn sẽ làm cho đến khi tôi thấy tội lỗi. vì nó đã mở ra tâm trí của tôi. khi tôi nhìn thấy tội lỗi. ace Shoutout của cơ sở
Andrew Luhring

1
@AndrewLuhring Thật tuyệt vời.
aendrew

1
Lưu ý rằng ma trận xoay chỉ có thể áp dụng nếu [x,y,z]vectơ được chuẩn hóa, tức là chỉ khi độ dài vectơ Math.sqrt(x*x + y*y + z*z)là một. Nếu nó không được bình thường, nó có thể dễ dàng được chuyển đổi thành một bình thường, bởi lặn mỗi x, yztheo chiều dài của họ.
Jose Rui Santos

Bạn phải có bằng Thạc sĩ Mỹ thuật về Toán học. Cảm ơn vì bài thơ này, Ana!
Ida

@Andrew: đừng lo lắng, nhiều người trong chúng ta tội lỗi sẽ tốt hơn ... thở dài.
David nói hãy phục hồi Monica vào

15

Cú pháp:

rotate3d(x, y, z, a)

Giá trị:

  • x Là một <number>mô tả tọa độ x của vector biểu thị trục quay.
  • y Là một <number>mô tả tọa độ y của vector biểu thị trục quay.
  • z Là một <number>mô tả tọa độ z của vector biểu thị trục quay.
  • a Là một <angle>đại diện cho góc quay. Góc dương biểu thị sự quay theo chiều kim đồng hồ, góc âm biểu thị chiều quay ngược chiều kim đồng hồ.

Giống như trong :

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

Đã tìm ở đây

Caniuse nó ở đây

Tài liệu khác về nó


6
Có lẽ tôi là người dày dặn, nhưng tôi nghĩ anh ấy đang yêu cầu một thuật toán để chuyển từ biến đổi chuỗi thành một biến đổi duy nhất rotate3d, không phải cho định nghĩa rotate3d.
Ana

3
Tôi nghĩ rằng ông muốn biết làm thế nào để kết hợp rotateX (50deg) rotateY (20deg) rotateZ (15deg) ở tốc ký rotate3d () trong CSS
Milche patern

7

Tùy thuộc vào những gì bạn đang cố gắng làm, 'hack' này có thể giúp bạn. Giả sử bạn đang làm hoạt ảnh và bạn muốn thêm chuyển đổi sau khi chuyển đổi, v.v. và bạn không muốn CSS trông giống như đang thực hiện 100 lần biến đổi:

Điều này hoạt động trong chrome: 1. Áp dụng bất kỳ biến đổi nào bạn muốn cho một phần tử. 2. Lần tới khi bạn muốn thêm một biến đổi, hãy thêm nó vào biến đổi được tính toán: "window.getComputedStyle (element) .transform" - nhưng hãy đảm bảo đặt biến đổi mới ở bên trái. 3. Bây giờ biến đổi của bạn trông giống như "xoayZ (30deg) matrix3d ​​(......). 4. Lần tới khi bạn muốn thêm một biến đổi khác, hãy lặp lại quy trình - Chrome luôn giảm các biến đổi thành ký hiệu matrix3d.

TL; DR- áp dụng bất kỳ phép biến đổi nào bạn muốn và sau đó nhận được phép biến đổi ma trận3d được tính toán.

Thủ thuật này cũng cho phép bạn nhanh chóng (nghĩa là, không cần tự mình làm bất kỳ phép toán nào) tạo một chức năng xoay một đối tượng liên quan đến hệ quy chiếu của bạn theo bất kỳ hướng nào. Xem mẫu bên dưới:

CHỈNH SỬA : Tôi cũng đã thêm các bản dịch xyz. Sử dụng điều này, sẽ rất dễ dàng để đặt các đối tượng ở các vị trí 3d cụ thể với các hướng cụ thể trong tâm trí. Hoặc ... tưởng tượng một khối lập phương nảy lên và thay đổi trục quay của nó với mỗi lần trả lại tùy thuộc vào cách nó tiếp đất!

	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>


Đây là một trong hầu hết các bài viết hữu ích bao giờ hết, thnak bạn
Damiano Celent

3

Giá trị chính xác là rotate3d(133,32,58,58deg)

Xem fiddle (Đối với chrome và Safari, sử dụng -webkit-biến đổi)


12
Làm thế nào để bạn tính toán chính xác nó?
Ana

1
@Ana tôi không, đó là lý do tại sao câu trả lời của bạn là 10x tốt hơn :)
Bigood
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.