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 to test .css file for syntax errors?

    Bootstrap 3 / CSS: How to properly vertically align in panel heading

    How can I center a logo and place the links left and right on the navbar using bootstrap?

    How do people make sections in HTML pages? [closed]

    Flex: How to embed fonts with CSS

    How to change the text my button displays?

    How to make this shape with css? [closed]

    Rails 3 - will_paginate plugin - how to style it

    How to make div css background hover

    Beginner: How to get a fixed element to a left position (float left?) - JSFiddle included

    How to use one popup box to display arbitrary number of information respectively?

    How to get color property from CSS with jQuery?

    How to place a
    to the right of an input field

    How do you force a website to be in landscape mode when viewed on a mobile device?

    CSS Syntax - How to interpret this?

    How to overlay a div over a canvas CSS

    How to make my popup window dead center no matter what width it is

    How to change a button data-icon size

    how to apply CSS styles in current document recieved from AJAX request?

    How to use Segoe Print font in CSS?

    How i can force my div to display in block?

    How to make IFrame fill width of screen

    Show/Hide Div's via | Save Scrollbar | Save State

    How can I horizontally align these divs?

    How to make LESS combine CSS rules with a comma

    How can I apply a css rule to all descendants of an elements

    How to move this button?

    How to reverse the float order of heading & body with CSS?

    CSS selector: how to select non-element sibling node?

    How to stop one layer going over another