web-dev-qa-db-fra.com

Comment mélanger les propriétés de transformation css3 sans surcharger (en temps réel)?

Existe-t-il un moyen de combiner (mélanger) les propriétés de transformation css sans les surcharger? Par exemple là je veux faire pivoter et mettre à l'échelle. http://jsfiddle.net/hyzhak/bmyN3/

html

<div class="item rotate-90 tiny-size">
    Hello World!
</div>

css

.rotate-90 {
    -webkit-transform: rotate(90deg);
}
.tiny-size {
    -webkit-transform: scale(0.25, 0.25);
}

PS

J'ai juste beaucoup d'éléments et beaucoup de classes simples pour transformer la vue des éléments. Et je veux juste ajuster leur vue en ajoutant et en supprimant certaines classes. La combinaison de toutes les classes ne fonctionne pas car il y aura des centaines de combinaisons.

De plus, je veux le faire en temps réel.

Le nombre de transformations peut être d’environ 5 et chacune d’entre elles peut contenir environ 10 états. Décrivez donc simplement toutes leurs combinaisons avec les mains pour obtenir environ

10*10*10*10*10 = 100000 cases

C'est une mauvaise solution.

24
Eugene Krevenets

Voici une tentative de résolution du problème avec Javascript: http://jsfiddle.net/eGDP7/

J'utilise un attribut de données sur le code HTML pour lister les classes avec les transformations que nous voulons appliquer:

<div class="compoundtransform" data-transformations="scaletrans2, rotatetrans1">Test subject</div>

Je parcours les classes et découvre quelles règles css elles représentent:

function getCSSRulesForClass( selector ) {
    var sheets = document.styleSheets;
    var cssRules = [];
    for (var i = 0; i<sheets.length; ++i) {
        var sheet = sheets[i];
        if( !sheet.cssRules ) { continue; }
        for (var j = 0; j < sheet.cssRules.length; ++j ) {
            var rule = sheet.cssRules[j];
            if (rule.selectorText && rule.selectorText.split(',').indexOf(selector) !== -1) {
                var styles = rule.style;
                for( var k = 0; k<styles.length; ++k ) {
                    var style = styles[k];
                    cssRules.Push( { 
                        property: style,
                        value: styles[style]
                    } );
                }
            }
        }
    }
    return cssRules;
}

Je trouve toutes les transformations et les applique à une matrice:

function convertTransformToMatrix( source, transformValue ) {
    var values = transformValue.split(") "); // split into array if multiple values
    var matrix = cloneObject( source );
    for ( var i = 0; i<values.length; ++i ) {
        var value = values[i];
        if( isRotate( value ) ) {
            var rotationValue = cssRotationToRadians( value );
            var cosValue = Math.cos( rotationValue );
            var sinValue = Math.sin( rotationValue );
            var a = matrix.a;
            var b = matrix.b;
            var c = matrix.c;
            var d = matrix.d;
            var tx = matrix.tx;
            var ty = matrix.ty;
            matrix.a = a*cosValue - b*sinValue;
            matrix.b = a*sinValue + b*cosValue;
            matrix.c = c*cosValue - d*sinValue;
            matrix.d = c*sinValue + d*cosValue;
            matrix.tx = tx*cosValue - ty*sinValue;
            matrix.ty = tx*sinValue + ty*cosValue;
        } else if ( isScale( value ) ) {
            var scale = cssScaleToObject( value );
            matrix.a *= scale.x;
            matrix.b *= scale.y;
            matrix.c *= scale.x;
            matrix.d *= scale.y;
            matrix.tx *= scale.x;
            matrix.ty *= scale.y;
        } else if ( isTranslate( value ) ) {
            var translate = cssTranslateToObject( value );
            matrix.tx += translate.x;
            matrix.ty += translate.y;
        }
    }
    return matrix;
}

Et enfin, j'applique cette matrice au nœud en tant que transformation.

Actuellement:

  • Le code est un peu brouillon
  • L'analyse CSS est limitée à l'échelle (x, y), à la traduction (x, y) et à la rotation avec des valeurs en degrés ou en radians 
  • Et cela ne fonctionnerait qu'avec le préfixe du fournisseur de webkit

Je pourrais le ranger et le transformer en un utilitaire si utile à n'importe qui.

7
BrettJephson

Hmm ... pour autant que je sache, il faudrait créer une nouvelle classe et les combiner de cette façon (séparés par un espace):

-webkit-transform: rotate(90deg) scale(0.25, 0.25);
9
m59

Pour résoudre ce problème, j'ajoute une classe wrapper à celle que je souhaite. Par exemple, j'ai le wrapper qui a sa position définie via javascript, puis l'interne qui est affecté par les animations CSS - les deux sur la propriété de transformation.

Je sais que l'ajout de nœuds DOM n'est pas idéal, mais cela contourne la solution de script et permet au navigateur d'optimiser les animations et les transitions comme il le ferait normalement.

5
Hugo Scott-Slade

Actuellement, il n'y a aucun moyen de le faire, il n'accepte qu'une commande pour transform à la fois et ne peut pas ajouter ou soustraire comme vous le souhaitez. Ainsi, vous devrez ajouter ou supprimer une classe en fonction de ce que sont les premier et second types et écrire une variable transform personnalisée pour cet élément.

L'utilisation d'un langage de préprocesseur CSS tel que SASS ou LESS pourrait faciliter la combinaison des transitions. Les éléments suivants permettent de combiner un nombre quelconque de transitions en un seul, mais il est nécessaire de préciser les options à ajouter (il s'agit de SCSS).

.item {
  width:500px;
  height:500px;
  font-size:150px;
  background:blue;
}

$firstTransform: rotate(90deg);
$secondTransform: scale(0.25, 0.25);

@mixin transform($transform...) {
  -webkit-transform: $transform;
     -moz-transform: $transform;
      -ms-transform: $transform;
       -o-transform: $transform;
          transform: $transform;
}
.rotate-90 {
  @include transform($firstTransform);
}
.tiny-size {
  @include transform($secondTransform);
}
.both {
  @include  transform($firstTransform $secondTransform);
}

Demo

Actuellement, la seule façon de le faire serait d'utiliser du javascript, en ajoutant essentiellement une classe avec une transformation, en enregistrant une variable de cette classe, en supprimant la classe et en faisant la même chose avec une autre classe, puis en combinant les deux matrices de la classe. ' se transforme. EDIT: Voir la réponse javascript de brejep pour plus d'informations sur cette approche

4
Zach Saucier

Au lieu de faire pivoter et redimensionner, vous pouvez utiliser la fonction de matrice.

transform: matrix(a, b, c, d, tx, ty);

Dans l'exemple donné, je pense que ce qui suit produirait le résultat souhaité:

transform: matrix(0,-0.25,0.25,0,0,0);

Pour une explication des calculs matriciels:

Et il existe des outils utiles pour calculer ces matrices en tant que CSS, tels que:

2
BrettJephson

Vous pouvez notamment obtenir le style de transformation calculé dans JS et concaténer votre valeur de transformation secondaire:

HTML

<div class="rotate-scale"></div>

CSS

.rotate-scale {
   transform: rotate(90deg);
}

JS

var el = document.querySelector('.rotate-scale'),
    // rotation will get the transform value declared in css
    rotation = window.getComputedStyle(el).getPropertyValue('transform');

el.style.transform = rotation + 'scale(0.25, 0.25)';
0
Taylor Plante