How to combine transforms in CSS?


Tags: javascript,css,css3,transform,css-animations

Problem :

I have a CSS animation that uses transforms to move around relative to its current position.

CSS

fish {
    animation: fishanimation 4s ease-in-out infinite alternate;
}

@keyframes fishanimation {
  0% {
    transform: translateY(20px);
  }

  100% {
    transform: translateY(80px);
  }
}

Now I want to adjust the scale and rotation dynamically using javascript, but this gets overwritten by the running css animation. The transforms are not combined :(

Javascript

this.div.style.transform = "scale(0.4) rotate(45deg)";

Is it possible to have the scale and rotation apply to the already existing transformation? Something like:

element.transform = element.transform + "scale(0.4) rotate(34deg)";

EDIT:

This is not a duplicate of the question: how to combine css transforms. The point of this question is that an element may already have a transform that I don't want to overwrite. I want to add to it, without actually knowing what the current transform state is.



Solution :

As commented, I recommend you use a library called Velocity JS for this. Click for Velocity JS website.

If a library like suggested is not an option, then read on!

If you were looking to do multiple transforms like that in one on top of your previous transforms, then you'd need to use the matrix value for the transform. Things get a little complicated with the matrix. The parameters for the matrix are in this order: -

matrix(scaleX(),skewY(),skewX(),scaleY(),translateX(),translateY());

Let's use the example of starting off with the initial fish animation you mentioned: -

fish {
    animation: fishanimation 4s ease-in-out infinite alternate;
}

@keyframes fishanimation {
  0% {
    transform: matrix(1, 0, 0, 1, 0, 20);
  }

  100% {
    transform: matrix(1, 0, 0, 1, 0, 80);
  }
}

To dynamically change this in JavaScript will require some unpleasant string manipulation and getting the transform property of the element (which is more awkward than you think). Here's an example of how you might do it.

function getTransformValues(obj) {
    var transform = {
        scaleX: 1,
        skewX: 0,
        skewY: 0,
        scaleY: 1,
        translateX: 0,
        translateY: 0
    };

    var matrix = obj.css("-webkit-transform") ||
                 obj.css("-moz-transform")    ||
                 obj.css("-ms-transform")     ||
                 obj.css("-o-transform")      ||
                 obj.css("transform");

    if (matrix && matrix !== 'none') {
        var values = matrix.split('(')[1].split(')')[0].split(',');
        transform.scaleX = parseInt(values[0], 10);
        transform.skewX = parseInt(values[1], 10);
        transform.skewY = parseInt(values[2], 10);
        transform.scaleY = parseInt(values[3], 10);
        transform.translateX = parseInt(values[4], 10);
        transform.translateY = parseInt(values[5], 10);
    }

    return transform;
}

var values = getTransformValues($('#test'));
console.log(values);
// Object {scaleX: 1, skewX: 0, skewY: 0, scaleY: 2, translateX: 50, translateY: 40}

Now you've got those values you can start creating a new matrix by only changing the one you want, for example: -

var old = {
    scaleX: 1,
    skewX: 0,
    skewY: 0,
    scaleY: 2,
    translateX: 50,
    translateY: 40
};

$('#test').css('transform', 'matrix(' + old.scaleX + ', ' + old.skewY + ', ' + old.skewX + ', ' + old.scaleY + ', ' + old.translateX + ', ' + old.translateY + ')');

Bare with me... If you want to start manipulating the rotation angle things get even more complicated. To avoid bogging this answer so much, this part of the question has a solution at the following link: Get element -moz-transform:rotate value in jQuery

Hopefully you can see why adopting libraries such as Velocity JS, at least at the time of writing, is the best way to go for quick, easy, clean and smooth cross-browser animation.


    CSS Howto..

    How do I set up the Zurb Foundation icons?

    How to get global selector inside emulated view encapsulation (CSS / Angular2)

    How to put those things next to eachother? CSS

    How do I correct overlapping spacing error in CSS when it wraps text?

    how to put html inside php code [closed]

    How to add two CSS Class to control in the code behind?

    How to create shapes in css? [closed]

    How to make this layout in CSS?

    I have a div with a pseudo :after element creating a circle after it. How can I add something else inside that circle?

    jquery .show() hides immediately

    how to save style-css values for Later use then Reload those values back

    How to resize a div on drag? [Issue with rotation]

    How to render text in .NET in the same size as browsers does given CSS for the text

    how to put 2 css elements in the same row (one next to each other)?

    CSS: How to make a responsive grid without a framework

    How can I wrap text around a bottom-right div?

    how to remove css property using javascript?

    How to make sure items are added to the end of a moving list?

    How to make css menu width impossible to change when zooming or changing resolution?

    How to Highlight the Menu in css. I used a:active but it does not serve the purpose I expected

    How to split a div into multiple rows and columns in css?

    How to fix width of DIV that contains floated elements?

    How to align contents in different containers using only css

    How do I make my images in my div change opacity on hover?

    How do I get an html/css form to post to Gravity Forms?

    xHTML/CSS: How to make inner div get 100% width minus another div width

    How to properly float two columns side by side with css

    How to create a button to every list item which opens a menu over it?

    How to make dot-dash underline

    Adding some automatic versioning to CSS files. How come I'm not able to pull assembly info?