Wie rotateX(50deg) rotateY(20deg) rotateZ(15deg)
in Kurzschrift zu kombinieren rotate3d()
?
Wie rotateX(50deg) rotateY(20deg) rotateZ(15deg)
in Kurzschrift zu kombinieren rotate3d()
?
Antworten:
rotateX(50deg)
ist äquivalent zu rotate3d(1, 0, 0, 50deg)
rotateY(20deg)
ist äquivalent zu rotate3d(0, 1, 0, 20deg)
rotateZ(15deg)
ist äquivalent zu rotate3d(0, 0, 1, 15deg)
Damit...
rotateX(50deg) rotateY(20deg) rotateZ(15deg)
ist äquivalent zu
rotate3d(1, 0, 0, 50deg) rotate3d(0, 1, 0, 20deg) rotate3d(0, 0, 1, 15deg)
Für ein Generikum rotate3d(x, y, z, α)
haben Sie die Matrix
wo
Sie erhalten nun die Matrizen für jede der 3 rotate3d
Transformationen und multiplizieren sie. Und die resultierende Matrix ist die Matrix, die der resultierenden Single entspricht rotate3d
. Ich bin mir nicht sicher, wie einfach es ist, die Werte daraus zu extrahieren rotate3d
, aber es ist sicher einfach, diese für eine einzelne zu extrahieren matrix3d
.
Im ersten Fall ( rotateX(50deg)
oder rotate3d(1, 0, 0, 50deg)
) haben Sie:
x = 1
, y = 0
, z = 0
,α = 50deg
Die erste Zeile der Matrix ist in diesem Fall also 1 0 0 0
.
Der zweite ist 0 cos(50deg) -sin(50deg) 0
.
Der dritte 0 sin(50deg) cos(50deg) 0
.
Und der vierte ist offensichtlich 0 0 0 1
.
Im zweiten Fall haben Sie x = 0
, y = 1
, z = 0
, α = 20deg
.
Erste Reihe : cos(20deg) 0 sin(20deg) 0
.
Zweite Reihe : 0 1 0 0
.
Dritte Reihe : -sin(20) 0 cos(20deg) 0
.
Vierte: 0 0 0 1
Im dritten Fall, haben Sie x = 0
, y = 0
, z = 1
, α = 15deg
.
Erste Reihe : cos(15deg) -sin(15deg) 0 0
.
Zweite Reihe sin(15deg) cos(15deg) 0 0
.
Und die dritte und die vierte Reihe sind 0 0 1 0
und 0 0 0 1
jeweils.
Hinweis : Möglicherweise haben Sie bemerkt, dass die Vorzeichen der Sin-Werte für die rotateY-Transformation anders sind als für die beiden anderen Transformationen. Es ist kein Rechenfehler. Der Grund dafür ist, dass für den Bildschirm die y-Achse nach unten und nicht nach oben zeigt.
Dies sind also die drei 4x4
Matrizen, die Sie multiplizieren müssen, um die 4x4
Matrix für die resultierende einzelne rotate3d
Transformation zu erhalten. Wie gesagt, ich bin mir nicht sicher, wie einfach es sein kann, die 4 Werte herauszuholen, aber die 16 Elemente in der 4x4-Matrix sind genau die 16 Parameter des matrix3d
Äquivalents der verketteten Transformation.
EDIT :
Eigentlich stellt sich heraus, dass es ziemlich einfach ist ... Sie berechnen die Spur (Summe der diagonalen Elemente) der Matrix für die rotate3d
Matrix.
4 - 2*2*(1 - cos(α))/2 = 4 - 2*(1 - cos(α)) = 2 + 2*cos(α)
Sie berechnen dann die Kurve für das Produkt der drei 4x4
Matrizen und setzen das Ergebnis mit 2 + 2*cos(α)
Ihrem Extrakt gleich α
. Dann berechnen Sie x
, y
, z
.
In diesem speziellen Fall 4x4
lautet die Spur der Matrix, die sich aus dem Produkt der drei Matrizen ergibt , wenn ich richtig berechnet habe :
T =
cos(20deg)*cos(15deg) +
cos(50deg)*cos(15deg) - sin(50deg)*sin(20deg)*cos(15deg) +
cos(50deg)*cos(20deg) +
1
Also cos(α) = (T - 2)/2 = T/2 - 1
, was bedeutet das α = acos(T/2 - 1)
.
[x,y,z]
Vektor normalisiert ist, dh nur, wenn die Vektorlänge Math.sqrt(x*x + y*y + z*z)
eins ist. Wenn es nicht normiert ist, kann es leicht in ein normiertes eines umgewandelt werden, durch Tauchen jedem x
, y
und z
durch ihre Länge.
Syntax:
rotate3d(x, y, z, a)
Werte:
x
Wird eine <number>
Beschreibung der x-Koordinate des Vektors , der die Drehachse angibt.y
Ist eine <number>
Beschreibung der y-Koordinate des Vektors, der die Rotationsachse bezeichnet.z
Ist eine <number>
Beschreibung der z-Koordinate des Vektors, der die Rotationsachse bezeichnet.a
Ist eine <angle>
Darstellung des Drehwinkels. Ein positiver Winkel bezeichnet eine Drehung im Uhrzeigersinn, ein negativer Winkel eine Drehung gegen den Uhrzeigersinn.Wie in :
.will-distort{
transform:rotate3d(10, 10, 10, 45deg);
}
rotate3d
, nicht um die Definition von rotate3d
.
Abhängig davon, was Sie versuchen, könnte dieser "Hack" Ihnen helfen. Angenommen, Sie führen eine Animation durch und möchten eine Transformation nach der anderen hinzufügen, und Sie möchten nicht, dass das CSS so aussieht, als würde es Hunderte von Transformationen ausführen:
Dies funktioniert in Chrome: 1. Wenden Sie die gewünschte Transformation auf ein Element an. 2. Wenn Sie das nächste Mal eine Transformation hinzufügen möchten, fügen Sie sie der berechneten Transformation hinzu: "window.getComputedStyle (element) .transform" - stellen Sie jedoch sicher, dass Sie die neue Transformation links platzieren. 3. Jetzt würde Ihre Transformation wie folgt aussehen: "rotateZ (30deg) matrix3d (......). 4. Wenn Sie das nächste Mal eine weitere Transformation hinzufügen möchten, wiederholen Sie den Vorgang - Chrome reduziert die Transformationen immer auf die Matrix3d-Notation.
TL; DR - Wenden Sie die gewünschten Transformationen an und erhalten Sie dann die berechnete Matrix3d-Transformation.
Mit diesem Trick können Sie auch schnell (dh ohne selbst zu rechnen) eine Funktion erstellen, mit der ein Objekt in Bezug auf Ihren Referenzrahmen in eine beliebige Richtung gedreht wird. Siehe das folgende Beispiel:
EDIT : Ich habe auch xyz-Übersetzungen hinzugefügt. Auf diese Weise wäre es sehr einfach, Objekte an bestimmten 3D-Orten mit bestimmten Ausrichtungen zu platzieren. Oder ... stellen Sie sich einen Würfel vor, der mit jedem Sprung seine Drehachse springt und ändert, je nachdem, wie er landet!
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>