programmatically changing webkit-transformation values in animation rules

25,793

Solution 1

Use the CSSOM

var style = document.documentElement.appendChild(document.createElement("style")),
rule = " run {\
    0%   {\
        -webkit-transform: translate3d(0, 0, 0); }\
        transform: translate3d(0, 0, 0); }\
    }\
    100% {\
        -webkit-transform: translate3d(0, " + your_value_here + "px, 0);\
        transform: translate3d(0, " + your_value_here + "px, 0);\
    }\
}";
if (CSSRule.KEYFRAMES_RULE) { // W3C
    style.sheet.insertRule("@keyframes" + rule, 0);
} else if (CSSRule.WEBKIT_KEYFRAMES_RULE) { // WebKit
    style.sheet.insertRule("@-webkit-keyframes" + rule, 0);
}

If you want to modify a keyframe rule in a stylesheet that's already included, do the following:

var
      stylesheet = document.styleSheets[0] // replace 0 with the number of the stylesheet that you want to modify
    , rules = stylesheet.rules
    , i = rules.length
    , keyframes
    , keyframe
;

while (i--) {
    keyframes = rules.item(i);
    if (
        (
               keyframes.type === keyframes.KEYFRAMES_RULE
            || keyframes.type === keyframes.WEBKIT_KEYFRAMES_RULE
        )
        && keyframes.name === "run"
    ) {
        rules = keyframes.cssRules;
        i = rules.length;
        while (i--) {
            keyframe = rules.item(i);
            if (
                (
                       keyframe.type === keyframe.KEYFRAME_RULE
                    || keyframe.type === keyframe.WEBKIT_KEYFRAME_RULE
                )
                && keyframe.keyText === "100%"
            ) {
                keyframe.style.webkitTransform =
                keyframe.style.transform =
                    "translate3d(0, " + your_value_here + "px, 0)";
                break;
            }
        }
        break;
    }
}

If you don't know the order but do know the URL of the CSS file, replace document.styleSheets[0] with document.querySelector("link[href='your-css-url.css']").sheet.

Solution 2

Have you tried declaring the keyframe portion of your css in a <style> element in the head of your html document. You can then give this element an id or whatever and change it's content whenever you like with javaScript. Something like this:

<style id="keyframes">
        @-webkit-keyframes run {
            0%    { -webkit-transform: translate3d(0px,0px,0px); }            
            100%  { -webkit-transform: translate3d(0px, 1620px, 0px); }
        }
</style>

Then your jquery can change this as normal:

$('#keyframes').text('whatever new values you want in here');

Solution 3

Well from your example it seems to me that CSS animations may be overkill. Use transitions instead:

-webkit-transition: -webkit-transform .4s linear; /* you could also use 'all' instead of '-webkit-transform' */

and then apply a new transform to the element via js:

$("<yournode>")[0].style.webkitTransform = "translate3d(0px,"+ (height*i) +"px,0px)";

It should animate that.

Solution 4

I didn't get when you wanted to modify these values (i.e. use variables) but nevertheless here are 3 to 4 solutions and 1 impossible solution (for now).

  • server-side calculation: in order to serve a different CSS from time to time, you can tell PHP or any server-side language to parse .css files as well as .php or .html and then use PHP variables in-between PHP tags. Beware of file caching: to avoid it, you can load a stylesheet like style.css?1234567890random-or-time it will produce an apparent different file and thus won't be cached

  • SASS is also a server-side solution that needs Ruby and will provide you an existing syntax, probably cleaner than a hand-made solution as others have already about problems and solutions

  • LESS is a client-side solution that will load your .less file and a less.js file that will parse the former and provide you variables in CSS whatever your server is. It can also work server-side with node.js

  • CSS being dynamically modified while your page is displayed?
    For 2D there are jquery-animate-enhanced from Ben Barnett, 2d-transform or CSS3 rotate are pitched the other way around (they use CSS3 where possible and where there are no such functions, they fallback to existing jQuery .animate() and IE matrix filter) but that's it.
    You could create a plugin for jQuery that would manage with a few parameters what you want to achieve with 3D Transformation and avoid the hassle of modifying long and complex CSS rules in the DOM

  • CSS only: you could use -moz-calc [1][2] that works only in Firefox 4.0 with -webkit-transform that works only in ... OK nevermind :-)

Solution 5

A 'Chunky' solution?

Create transforms for heights within your chosen granularity, say 0-99, 100-199, 200-299, etc. Each with a unique animation name identifier like:

@-webkit-keyframes run100 {
        0%    { -webkit-transform: translate3d(0px,0px,0px); }            
        100%  { -webkit-transform: translate3d(0px,100px,0px); }
}

@-webkit-keyframes run200 {
        0%    { -webkit-transform: translate3d(0px,0px,0px); }            
        100%  { -webkit-transform: translate3d(0px,200px,0px); }
}

then create matching css classes:

.height-100 div { 
    -webkit-animation-name: run100;  
}

.height-200 div { 
    -webkit-animation-name: run200;  
}

then with javascript decide which chunk you're in and assign the appropriate class to the surrounding element.

$('#frame').attr('class', '').addClass('height-100');

Might be ok if the granularity doesn't get too fine!

Share:
25,793

Related videos on Youtube

clamp
Author by

clamp

hello

Updated on July 09, 2022

Comments

  • clamp
    clamp almost 2 years

    I have this stylesheet:

            @-webkit-keyframes run {
                0% {
                    -webkit-transform: translate3d(0px, 0px, 0px);
                }            
                100% {
                    -webkit-transform: translate3d(0px, 1620px, 0px);
                }
            }
    

    Now, I would like to modify the value of 1620px depending on some parameters. Like this:

            @-webkit-keyframes run {
                0% {
                    -webkit-transform: translate3d(0px, 0px, 0px);
                }            
                100% {
                    -webkit-transform: translate3d(0px, height*i, 0px);
                }
            }
    

    I would prefer to be able to use JavaScript and jQuery, though a pure CSS solution would be ok.

    This is for an iPhone game that runs in it's mobile Apple Safari browser.

    • vincicat
      vincicat about 13 years
      The best way will be you generate the css rule by javascript - WWDC 2010 CSS3 Animation session have a sample code doing this, please check.
  • clamp
    clamp about 13 years
    thanks, but that is actually not exactly what i am looking for. i would rather like to change the values in existing rules for animations
  • Lea Verou
    Lea Verou about 13 years
    calc() also works in IE9. Also, transforms work in every modern browser, not just Webkit (with the appropriate prefix of course).
  • clamp
    clamp about 13 years
    thanks for your detailed answer! i want to modify these values at any time after the page is loaded, so unfortunately the server-side solutions are not an option. i will have a look at the other solutions you have mentioned.
  • Eli Grey
    Eli Grey about 13 years
    "You could create a plugin for jQuery that would manage with a few parameters" is extreme overkill. The CSSOM is actually very simple for this use case. He's just insertRuleing a single CSSStyleRule into a CSSStyleSheet. It's one function call.
  • melfar
    melfar about 12 years
    should be $("<yournode>")[0] .style. webkitTransform
  • Alex
    Alex almost 12 years
    Absolutely amazing! Great answer! This helped me out so much!
  • Alex
    Alex almost 12 years
    Maybe I spoke too soon. I keep getting this error: Uncaught Error: SYNTAX_ERR: DOM Exception 12 and I am also getting Uncaught Error: SYNTAX_ERR: DOM Exception 1
  • rantingmong
    rantingmong over 10 years
    The last insertRule line should add it at index 0 not 1, this is the reason for the DOM Exception 1
  • user2136963
    user2136963 about 9 years
    If's from the first part probably should be reordered. See stackoverflow.com/questions/20007992/…
  • akaihola
    akaihola over 5 years
    @Tokimon I fixed that for you. Thanks for your answer, it was helpful for me.
  • Camille
    Camille almost 3 years
    Javascript equivalent of this great solution : document.getElementById('keyframes').innerHTML = "new css animation values" ;