How to mix css3 transform properties without overriding (in realtime)?

前端 未结 6 1627
灰色年华
灰色年华 2020-12-11 00:26

Is there any way to combine (mix) css transform properties without overriding? For example there I want to rotate and scale. http://jsfiddle.net/hyzhak/bmyN3/

html<

相关标签:
6条回答
  • 2020-12-11 00:32

    Instead of rotate and scale you could use the matrix function.

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

    In the example given, I believe the following would produce the desired result:

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

    For an explanation of matrix calculations:

    • http://en.wikipedia.org/wiki/Linear_transformation#Examples_of_linear_transformation_matrices

    And some useful tools exist for calculating these matrices as CSS, such as:

    • http://www.boogdesign.com/examples/transforms/matrix-calculator.html
    0 讨论(0)
  • 2020-12-11 00:36

    The way I get around this issue is to add a wrapper class around the one I want. For example, I have the wrapper which has its position set via javascript, and then the internal which is is affected by css animations - both on the transform property.

    I know adding DOM nodes isn't ideal but it circumvents the script-heavy solution and lets the browser optimise the animations and transitions as it would normally.

    0 讨论(0)
  • 2020-12-11 00:50

    Here's an attempt at solving the problem with Javascript: http://jsfiddle.net/eGDP7/

    I'm using a data attribute on the html to list the classes with transforms that we want to apply:

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

    I iterate through the classes and find out what css rules they represent:

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

    I find any transforms and apply the transforms to a matrix:

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

    And I, finally, apply that matrix to the node as a transform.

    Currently:

    • The code is a bit messy
    • The CSS parsing is limited to scale(x,y), translate(x,y), and rotate with degree or radian values
    • And it would only work with the webkit vendor prefix

    I might tidy it up and turn it into a utility if useful to anyone.

    0 讨论(0)
  • 2020-12-11 00:52

    One thing you could do is get the computed transform style in JS and concatenate your secondary transform value:

    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 讨论(0)
  • 2020-12-11 00:54

    Hmm...as far as I know, you would have to create new class and combine them this way (separated by a space):

    -webkit-transform: rotate(90deg) scale(0.25, 0.25);
    
    0 讨论(0)
  • 2020-12-11 00:56

    Currently there is no way to do this, it only accepts one command for transform at a time and cannot add or subtract like you'd like. Thus you'll have to add or remove a class depending on what the first and second type is and write a custom transform for that element

    Using a CSS preprocessor language like SASS or LESS could make combining transitions easier, the following allows for any number of transitions to be combined into one, but requires being told which ones to add (this is 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

    Really the only way to do it currently would be to use javascript, essentially adding a class with a transform, saving a variable of that class' transforms, removing the class and doing the same with another class, then combine the two matrices of the class' transforms. EDIT: See brejep's javascript answer for more on this approach

    0 讨论(0)
提交回复
热议问题