Comment combiner rotateX(50deg) rotateY(20deg) rotateZ(15deg)
en abrégé rotate3d()
?
rotateX(50deg)
équivaut à rotate3d(1, 0, 0, 50deg)
rotateY(20deg)
équivaut à rotate3d(0, 1, 0, 20deg)
rotateZ(15deg)
équivaut à rotate3d(0, 0, 1, 15deg)
Alors...
rotateX(50deg) rotateY(20deg) rotateZ(15deg)
est équivalent à
rotate3d(1, 0, 0, 50deg) rotate3d(0, 1, 0, 20deg) rotate3d(0, 0, 1, 15deg)
Pour un rotate3d(x, y, z, α)
générique, vous avez la matrice
où
Vous obtenez maintenant les matrices pour chacune des 3 _rotate3d
_ transformations et vous les multipliez. Et la matrice résultante est la matrice correspondant à l'unique _rotate3d
_ résultant. Vous ne savez pas trop comment extraire les valeurs de _rotate3d
_, mais il est facile de les extraire pour un seul _matrix3d
_.
Dans le premier cas (rotateX(50deg)
ou rotate3d(1, 0, 0, 50deg)
), vous avez:
_x = 1
_, _y = 0
_, _z = 0
_, _α = 50deg
_
Donc, la première ligne de la matrice dans ce cas est _1 0 0 0
_.
Le second est 0 cos(50deg) -sin(50deg) 0
.
Le troisième 0 sin(50deg) cos(50deg) 0
.
Et le quatrième est évidemment _0 0 0 1
_.
Dans le second cas, vous avez _x = 0
_, _y = 1
_, _z = 0
_, _α = 20deg
_.
Première rangée: cos(20deg) 0 sin(20deg) 0
.
Deuxième rangée: _0 1 0 0
_.
Troisième rangée: -sin(20) 0 cos(20deg) 0
.
Quatrième: _0 0 0 1
_
Dans le troisième cas, vous avez _x = 0
_, _y = 0
_, _z = 1
_, _α = 15deg
_.
Première rangée: cos(15deg) -sin(15deg) 0 0
.
Deuxième rangée sin(15deg) cos(15deg) 0 0
.
Et les troisième et quatrième rangées sont respectivement _0 0 1 0
_ et _0 0 0 1
_.
Remarque : vous avez peut-être remarqué que les signes des valeurs de péché pour la rotation transformer sont différentes de celles des deux autres transformations. Ce n'est pas une erreur de calcul. La raison en est que, pour l’écran, l’axe des Y est dirigé vers le bas et non vers le haut .
Il s’agit donc des trois matrices _4x4
_ que vous devez multiplier afin d’obtenir la matrice _4x4
_ pour la transformation unique résultante _rotate3d
_. Comme je l'ai dit, je ne sais pas à quel point il est facile d'extraire les 4 valeurs, mais les 16 éléments de la matrice 4x4 correspondent exactement aux 16 paramètres de l'équivalent _matrix3d
_ de la transformation chaînée.
ÉDITER :
En fait, il s’avère que c’est assez facile ... Vous calculez la trace (somme des éléments diagonaux) de la matrice pour la matrice _rotate3d
_.
4 - 2*2*(1 - cos(α))/2 = 4 - 2*(1 - cos(α)) = 2 + 2*cos(α)
Vous calculez ensuite la trace pour le produit des trois matrices _4x4
_, vous assimilez le résultat à 2 + 2*cos(α)
vous extrayez _α
_. Ensuite, vous calculez x
, y
, z
.
Dans ce cas particulier, si j’ai calculé correctement, la trace de la matrice résultant du produit des trois matrices _4x4
_ sera:
_T =
cos(20deg)*cos(15deg) +
cos(50deg)*cos(15deg) - sin(50deg)*sin(20deg)*cos(15deg) +
cos(50deg)*cos(20deg) +
1
_
Donc, cos(α) = (T - 2)/2 = T/2 - 1
, ce qui signifie que α = acos(T/2 - 1)
.
Syntaxe:
rotate3d(x, y, z, a)
Valeurs:
x
est un <number>
décrivant la coordonnée x du vecteur indiquant l’axe de rotation.y
est un <number>
décrivant la coordonnée y du vecteur indiquant l’axe de rotation.z
est un <number>
décrivant la coordonnée z du vecteur indiquant l’axe de rotation.a
est un <angle>
représentant l'angle de la rotation. Un angle positif désigne une rotation dans le sens des aiguilles d'une montre, un angle négatif un dans le sens inverse des aiguilles d'une montre.Comme dans :
.will-distort{
transform:rotate3d(10, 10, 10, 45deg);
}
Cela dépend de ce que vous essayez de faire, ce "bidouillage" pourrait vous aider. Supposons que vous réalisiez une animation et que vous souhaitiez ajouter une transformation après une transformation, etc., et que vous ne souhaitiez pas que le CSS ressemble à une centaine de transformations:
Cela fonctionne en chrome: 1. Appliquez la transformation que vous voulez à un élément. 2. La prochaine fois que vous souhaitez ajouter une transformation, ajoutez-la à la transformation calculée: "window.getComputedStyle (element) .transform" - mais veillez à placer la nouvelle transformation à gauche. 3. Maintenant, votre transformation ressemblerait à "rotationZ (30deg) matrix3d (......). 4. La prochaine fois que vous souhaitez ajouter une autre transformation, répétez le processus - Chrome réduit toujours les transforme en notation matrix3d.
TL; DR- applique les transformations souhaitées, puis récupère la transformation matrix3d calculée.
Cette astuce vous permet également de créer rapidement une fonctionnalité permettant de faire pivoter un objet par rapport à votre cadre de référence dans n’importe quelle direction. Voir l'exemple ci-dessous:
EDIT : J'ai également ajouté des traductions xyz. En utilisant cela, il serait très facile de placer des objets dans des emplacements 3D spécifiques avec des orientations spécifiques à l'esprit. Ou ... imaginez un cube qui rebondit et change son axe de rotation à chaque rebond en fonction de la manière dont il atterrit!
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>
La valeur exacte est rotate3d(133,32,58,58deg)
Voir le violon (For chrome et Safari, en utilisant -webkit-transform)