web-dev-qa-db-fra.com

rotation3d sténographie

Comment combiner rotateX(50deg) rotateY(20deg) rotateZ(15deg) en abrégé rotate3d()?

79
Artem Svirskyi

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

generic rotate matrix

explanation


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).

314
Ana

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);
}

Fiddled ici

Caniuse it here

Plus de documentation à ce sujet

15
Milche Patern

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>
7
Roman Rekhler

La valeur exacte est rotate3d(133,32,58,58deg)

Voir le violon (For chrome et Safari, en utilisant -webkit-transform)

3
Bigood