Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
strah

Tweening inherited values

Recommended Posts

Hi,

 

I am wondering if it's possible to tween children elements just by setting class name of a parent element.

Just in case the question is not clear I have prepared a JSFiddle to illustrate the problem:

 

http://jsfiddle.net/ESS4c/

 

The goal is to have paragraph text nicely animated between both states. Is that possible?

Link to comment
Share on other sites

I have found a solution (or rather a workaround). It is using CSSRule plugin

 

var rule = CSSRulePlugin.getRule("p");
var ruleTxt = rule.cssText.replace("; ", ",").replace(";", "");
var properties = ruleTxt.split(',');
var obj = {};

properties.forEach(function (property) {
    var tup = property.split(': ');
    obj[tup[0]] = tup[1];
});


document.getElementById('button').addEventListener("click", function () {
    TweenMax.to("#parent", 1, {
        className: "-=alert",
        onComplete: cleanUp
    });
    TweenMax.to($("#parent p"), 1, obj)
});

function cleanUp() {
    //removes ALL inline styling
    $("#parent p").attr("style", "");
}

 

 

Working sample here: http://jsfiddle.net/ESS4c/1/ Can it be done smarter/prettier? Also, if the content of the parent element is complex this solution would produce quite long code...

Link to comment
Share on other sites

I just ran into this today. I had some big ambitions for using the new className tweening ability, but this is kin-of a deal-breaker for me. I realize that it would be probably be an expensive operation to calculate all the inherited styles for animation purposes, but I think this feature won't feel fully implemented unless inherited styles are supported.

 

I'm going to file a bug on github

Link to comment
Share on other sites

First let me clarify that className does work with inherited properties. But it looks like the problem in your example has to do with the fact that you've got a selector for your child element(s) that no longer applies when you remove a particular class from the parent.

 

In your example, you've got this rule:

.alert p {
    color: red;
    margin-left: 30px;
} 

But then you tween its parent to remove the "alert" className, thus at the end of the tween when the transition has finished, that rule no longer applies. Remember, when you tween something, you define the target (the first parameter) and GSAP honors that - it doesn't reach out and tween a bunch of other targets that you didn't request.

 

In order to accommodate your request, when the tween instantiates, it would literally need to walk through the dom (descendant elements of the target), record all the properties, then switch the parent's classNames, analyze each property, figure out what's changed, and create a new tween for any children whose properties changed. So if you've got a div with 20 child divs and 30 list items, tweening the className of that one object could spawn 50 extra tweens. The initialization of the main tween would be much more CPU-intensive too because of all the analysis.

 

 

The other major problem with this functionality would be the control of the tween itself. For example:

//let's assume this spawns 50 extra tweens because of the children:
var tween = TweenLite.to(element, 2, {className:"newClass"});

//what happens when we do this?:
tween.reverse();

//or this?:
tween.kill(null, {left:true});

Do you see the conundrum?

 

 

So this isn't a bug with GSAP (as far as I can tell, unless I'm missing something) - it's just a logic issue with the way you're applying css selectors and using targets in your tweens. Not that you're doing anything "wrong" at all. And I completely understand why you'd want a feature like this. So...


I've taken a stab at a solution. To get around the issue of spawning phantom/hidden tweens internally and violating the standard behavior, I decided to add a static "cascadeTo()" method to CSSPlugin that's basically IDENTICAL to the regular TweenLite.to() method, but it walks through all the children as you've suggested, creates any necessary tweens, and then spits back an array of TweenLite instances. That way, we avoid the complications I mentioned above with the API, and we make it pretty easy to drop the resulting tweens into a TimelineLite or TimelineMax for controlling them all together as a single unit. This "return an array of tweens" behavior is identical to what the TweenMax stagger methods do.

 

 

For example:

//simple:
CSSPlugin.cascadeTo(element, 1, {className:"-=alert"});

//or drop them into a TimelineLite for easy control:
var tl = new TimelineLite();tl.add( CSSPlugin.cascadeTo(element, 1, {className:"-=alert"}) );
tl.pause();
tl.resume();
tl.seek(0.5);
...

To be clear, this is an experimental feature I'm putting into the attached preview of the upcoming 1.9.2 release. I'd love to get feedback about functionality, the API (better method name?), etc.

 

 

Does this address your concern?

1.9.2_preview1.1.zip

Link to comment
Share on other sites

Hi Jack,

 

you are the hero! Thank you very much. That solves the problem.

 

I know it wasn't a bug - it was just a missing 'nice to have'. And now it is there :-)

 

Cheers.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×