Jump to content
Search Community

ModifiersPlugin not working on scale?

katerlouis test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

It's werid,

.. whatever I do, I can't get modifier to impact the scale property–

 

The same principle is working on y.

 

See the Pen QmyGbd by katerlouis (@katerlouis) on CodePen

 

See the Pen GxoNZg by katerlouis (@katerlouis) on CodePen

 

 

 

The docs state, you can define a "modifier" function for almost any property 

It would suprise me if scale isn't one of them. 

 

And how do I know which are part and which arent?

 

 

Thanks,

Louis

 

 

PS: Thank you for the demo @Sahil ;)

  • Like 1
Link to comment
Share on other sites

Scale is actually 2 different calculations.

 

var tween = TweenMax.to('.red', 1, {
  //this value won't matter
  scale: 2,
  modifiers: {
    scaleX: scaleModifier,
    scaleY: scaleModifier
  }
});

function scaleModifier(scale) {
  if (scale > 1.5) return 1.5;
  return scale;
}

 

 

  • Like 4
Link to comment
Share on other sites

Scale is going to be exception and few other properties like skew, you will need to use modifier on scaleX and scaleY. Though you can use same function as modifier on both properties.

 

Performance, I have never noticed any negative impact on the performance but it depends on how much calculation you are doing. I wouldn't use it for every tween unless it is necessary. @OSUblake is master of modifiers plugin, he will know better.

 

See the Pen xWZRpB by Sahil89 (@Sahil89) on CodePen

 

  • Like 2
Link to comment
Share on other sites

Oh, okay–

 

I will suggest to mention things like these in the DOCS– Plugin docs aren't that long, anyway. 

 

That behavior is pretty unexpected for low-medium skilled GSAP users; 

Wouldn't that be the same for rotation? Isn't rotation technically is placeholder for rotationZ? Yet modifier works on rotation alone.

Link to comment
Share on other sites

I know, I know, – you guys are veeery protective when it comes to code-size.

But this is a plugin, which is optional anyways ;)

 

How much would it cost to add scale and skew to the modifierplugin, and do the scaleX and scaleY thingy internally? I mean, when the code-size protected TweenMax does provide this shortcut, why doesn't ModifiersPlugin?

Using it like it works on y is way more convenient.

 

In my case I need to do this on 5 tweens inside a rather complex (at least for me) timeline. Placing five extra functions somewhere else wouldn't be so pretty :( – 

  • Like 1
Link to comment
Share on other sites

Sorry about the disappointment, @kreativzirkel. I have updated the docs per your request. I appreciate the suggestion. Great catch. 

 

I didn't quite follow why you'd need 5 extra functions elsewhere - could you explain? It should be pretty simple to use scaleX/scaleY instead of scale but I might be missing something obvious. 

 

In the next version, I could add a check in ModifiersPlugin so that if it finds "scale", it'll automatically create scaleX and scaleY also, that point to the same function. I think that's a decent compromise that wouldn't add a ton of code and would minimize complexity. The only down side is that it'd get called once for scaleX and once for scaleY of course. 

  • Like 2
Link to comment
Share on other sites

Quote

How much would it cost to add scale and skew to the modifierplugin, and do the scaleX and scaleY thingy internally? 

 

Assuming it does not impact performance I would say it be would desirable. It is rather counter intuitive the way it needs to be handled now and likely to trip up a lot of people. And the resulting code would be simplified and easier to follow when things get complex.

  • Like 3
Link to comment
Share on other sites

I thought of testing performance, and created this demo. I don't see significant amount of drop in the performance on PC.

 

On mobile though (Moto X Style and Chrome CPU throttling), you won't see drop for about 50 elements but for anything more than that your frames start dropping mainly because you are reading values from DOM on every frame.

 

If you decide to optimize further and willing to complicate your code, you need to track your values on resize, scroll or whatever event that causes them to change. So if you don't read values from DOM on every frame then you get about ~50FPS performance for upto 100 elements and it starts dropping after that.

 

So you should plan everything in a way that you won't need to use responsive tweens and use it for only scenarios where it is absolutely necessary.

 

See the Pen rdxZBx?editors=1010 by Sahil89 (@Sahil89) on CodePen

 

  • Like 2
Link to comment
Share on other sites

@GreenSock Would it be possible to pass scope/current tween or as third parameter to modifier function? So ratio can be accessed using this.ratio/parameter.ratio instead of using tweenReference.ratio? It can simplify some of the code.

 

For example, any tween inside the timeline can be used directly instead of having to define it separately and then add it into the timeline. In my demo above, I had to loop through all elements and create reference to each tween, which can be simplified if there was way to access current tween inside modifier function.

Link to comment
Share on other sites

16 hours ago, GreenSock said:

I didn't quite follow why you'd need 5 extra functions elsewhere - could you explain? It should be pretty simple to use scaleX/scaleY instead of scale but I might be missing something obvious.

 

I don't see a convenient way to make a function that serves all 5 cases properly, because the logic per element differs; some more, some less–

 

This constant scrolling between the timeline and the functions is really confusing– you know me by now :D – I like to stay as close as possible to the timeline

 

I have something like this:

var tl = new TimelineMax()
	.from(".elem1", 1, { scale: 0, xPercent: 100, modifiers: {
    		scaleX: elem1Scale,
	    	scaleY: elem1Scale,
	      	xPercent: function(value, target) {
    	    	// some logic
        	  	return newValue;
	        }
    	}
	})
	.from(".elem2", 1, { scale: 0, xPercent: 100, modifiers: {
    		scaleX: elem2Scale,
	    	scaleY: elem2Scale,
	      	xPercent: function(value, target) {
    	    	// some logic
        	  	return newValue;
	        }
    	}
	})
	.from(".elem3", 1, { scale: 0, xPercent: 100, modifiers: {
    		scaleX: elem3Scale,
	    	scaleY: elem3Scale,
	      	xPercent: function(value, target) {
    	    	// some logic
        	  	return newValue;
	        }
    	}
	})
	.from(".elem4", 1, { scale: 0, xPercent: 100, modifiers: {
    		scaleX: elem4Scale,
	    	scaleY: elem4Scale,
	      	xPercent: function(value, target) {
    	    	// some logic
        	  	return newValue;
	        }
    	}
	})
	
	.from(".elem5", 1, { scale: 0, xPercent: 100, modifiers: {
    		scaleX: elem5Scale,
	    	scaleY: elem5Scale,
	      	xPercent: function(value, target) {
    	    	// some logic
        	  	return newValue;
	        }
    	}
	})

var elem1Scale = function(value, target) {
 	// some logic
    return newValue;
}

var elem2Scale = function(value, target) {
 	// some logic
    return newValue;
}

var elem3Scale = function(value, target) {
 	// some logic
    return newValue;
}

var elem4Scale = function(value, target) {
 	// some logic
    return newValue;
}

var elem5Scale = function(value, target) {
 	// some logic
    return newValue;
}

 

Link to comment
Share on other sites

 

21 hours ago, Sahil said:

Would it be possible to pass scope/current tween or as third parameter to modifier function? So ratio can be accessed using this.ratio/parameter.ratio instead of using tweenReference.ratio? It can simplify some of the code.

 

This isn't nearly as easy as it may seem due to a lot of performance optimizations and the flow of code. I'll look into it more though and see if there's a way I can do it efficiently, but no promises. 

 

I can do that copying of "scale" to "scaleX"/"scaleY" in the next release pretty easily, though, so that should resolve your issue @kreativzirkel. In the mean time, though, here's a way to use a simple function to reduce that code sample you provided:

function scaleVars(vars) {
    vars.scaleX = vars.scaleY = vars.scale;
    delete vars.scale;
    return vars;
}

var tl = new TimelineMax()
    .from(".elem1", 1, { scale: 0, xPercent: 100, modifiers: scaleVars({
            scale: function(value, target) {
                // some logic
                return newValue;
            },
              xPercent: function(value, target) {
                // some logic
                  return newValue;
            })
        }
    })
    .from(".elem2", 1, { scale: 0, xPercent: 100, modifiers: scaleVars({
            scale: function(value, target) {
                // some logic
                return newValue;
            },
              xPercent: function(value, target) {
                // some logic
                  return newValue;
            })
        }
    })
    .from(".elem3", 1, { scale: 0, xPercent: 100, modifiers: scaleVars({
            scale: function(value, target) {
                // some logic
                return newValue;
            },
              xPercent: function(value, target) {
                // some logic
                  return newValue;
            })
        }
    })
    .from(".elem4", 1, { scale: 0, xPercent: 100, modifiers: scaleVars({
            scale: function(value, target) {
                // some logic
                return newValue;
            },
              xPercent: function(value, target) {
                // some logic
                  return newValue;
            })
        }
    })
    
    .from(".elem5", 1, { scale: 0, xPercent: 100, modifiers: scaleVars({
            scale: function(value, target) {
                // some logic
                return newValue;
            },
              xPercent: function(value, target) {
                // some logic
                  return newValue;
            })
        }
    });

 

Does that help?

  • Like 4
Link to comment
Share on other sites

On 3/14/2018 at 3:38 AM, Sahil said:

Would it be possible to pass scope/current tween or as third parameter to modifier function? So ratio can be accessed using this.ratio/parameter.ratio instead of using tweenReference.ratio? It can simplify some of the code.

 

Alright, how about if we follow the pattern of having the function calls scoped to the tween itself (so "this" inside the function refers to the tween), just like callbacks? Here's an uncompressed version of ModifiersPlugin that has that change in place as well as the scale/scaleX/scaleY alias stuff: https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ModifiersPlugin-latest-beta.js

 

Better? 

  • Like 2
Link to comment
Share on other sites

Thanks Jack. Taking full advantage of my performance test demo I can see about 5-6 frame drop on mobile device with beta version. I wonder what @OSUblake will say about it.

 

For 10 elements it doesn't make any difference and runs at 60FPS, for 50 elements performance drops with beta. Thanks for the update, it simplifies the code. But I am curious about your opinion on performance difference, do you think it is significant or I am overthinking?

 

See the Pen JLKyBN?editors=0010 by Sahil89 (@Sahil89) on CodePen

 

Link to comment
Share on other sites

Actually, the difference you're seeing in performance has nothing to do with ModifiersPlugin. As strange as this may sound, it has to do with the fact that you're using a single tween vs. creating an individual one for each element. In other words, your tests involved other changes besides just swapping out ModifiersPlugin and referencing this.ratio instead of tween.ratio. It's those other changes that impacted performance. 

 

I'm trying to figure out WHY the one tween vs. many is behaving this way because it's very counter-intuitive quite frankly. I'm gonna have to dig deep into the guts. Quite curious. 

Link to comment
Share on other sites

Aha! Found it. It was related to some code in ModifiersPlugin that'd run on the first render for each target instead of just once for the tween, thus if your tween had 500 targets (in one tween), it'd run 499 too many times at the very start, and set up some tasks to do during the tween as well. That's what led to all the extra CPU load when you were animating a bunch of stuff in one tween. This only affected ModifiersPlugin. Very glad you caught the performance difference, Sahil. It helped me identify and fix that issue. I updated that file on codepen, so you should be good-to-go after a cache refresh. Sorry about the confusion. 

  • Like 3
Link to comment
Share on other sites

15 minutes ago, kreativzirkel said:

Is there an ETA for the updated ModifiersPlugin?

 

I can't give you an exact date, but hopefully within 2-4 weeks I'd say. Got a few other things I want to do to the codebase first. You're welcome to use the beta version in the meantime. 

  • Like 1
Link to comment
Share on other sites

@GreenSock - all joking aside, even after hanging around here for a few years, I'm still always impressed with the speed of improvements and bug fixes. I think that's one of those things people don't necessarily appreciate until they have a request or spot a little bug. We can all joke and whine about big companies like Adobe or Microsoft and trying to get their attention on something, but at GreenSock things get done quickly. It doesn't matter if it's a Club GreenSock Member or not, the request is given the same weight. Truly remarkable. :)

 

  • Like 5
Link to comment
Share on other sites

Great note, Craig.

Its worth repeating that all the hard work that you and the other moderators and contributors do makes it possible for Jack to improve the codebase. 

Its amazing that we have such great people around that go above and beyond. 

  • Like 4
Link to comment
Share on other sites

On 3/15/2018 at 5:00 PM, GreenSock said:

 

Alright, how about if we follow the pattern of having the function calls scoped to the tween itself (so "this" inside the function refers to the tween), just like callbacks? Here's an uncompressed version of ModifiersPlugin that has that change in place as well as the scale/scaleX/scaleY alias stuff: https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ModifiersPlugin-latest-beta.js

 

Better? 

 

I don't like that because it won't work with arrow functions.

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.
×
×
  • Create New...