jeremyckahn / shifty

The fastest TypeScript animation engine on the web
https://jeremyckahn.github.io/shifty/doc/
MIT License
1.54k stars 88 forks source link

Provide a way to manually define the "scheduling" policy #35

Closed jraoult closed 10 years ago

jraoult commented 10 years ago

Sometimes requestAnimationFrame is not usable mainly because of its throtling feature when the window is not visible. That's is usualy fine for UI tweening but for example I'm tweening the volume value of a MediaElement and I don't want this tween to be throttled.

Currently, the internal schedule function is automaticaly picked between RAF and then setTimeout if RAF is not available. Would be great to at least allow to force setTimout usage or even better provide a way to define a schedule function.

jeremyckahn commented 10 years ago

That sounds reasonable. There would need to be a static method for overriding the schedule function inside of the shifty.core.js closure. Perhaps something like:

/**
 * @param {boolean} useSetTimeout True to force Tweenable to
 * use setTimeout for scheduling, false to set it to use
 * requestAnimationFrame if it is available.
 */
Tweenable.forceSetTimeout = function (useSetTimeout) {};

How does that API seem to you? I can probably implement this in the next few days (it might have to wait until the weekend), but it shouldn't be too hard if you'd like to take a stab at it before I can get to it.

jraoult commented 10 years ago

Glad to see how reactive you are.

For my use case in need to define it on a per Tweenable instance basis. I actually have to tween one "UI" property (opacity) and one sound property so I would like to have the first tween sheduled by RAF and the other one by setTimeout.

My first idea was to add a boolean property named visual in the config object given to the Tweenable constructor (with a default value to true when omitted). Then move the schedule function definition into the contructor and instead of testing if (typeof window !== 'undefined') I would test if (typeof window !== 'undefined' || !option.visual). My idea was here to abstract the implementation details and let Shifty choose the best scheduling method according to the hint given by the user. But, we migh want to be more explicit with an option named like rafScheduling or even more low level with an option like schedulingFn by which the user can pass any implementation.

jeremyckahn commented 10 years ago

Of those options, I like the schedulingFn one the most. Shifty is meant to be a low-level library, and I don't want to introduce semantics such as visual that might not fit all use cases. A minor concern of mine is taking what is currently one-time setup logic (determining the scheduling method to use) and moving it to the constructor where it may be executed multiple times. However, the performance cost is likely negligible and not worth blocking the flexibility gain from this feature.

As for the API, I would rather add a prototype method than support another tween config value or constructor parameter. I feel that it's important to keep the API as simple as possible for typical use cases. Here's what I'm thinking:

/**
 * @param {Function(Function, number)} scheduleFunction The function 
 * to be called to schedule the next frame to be rendered.
 */
Tweenable.prototype.setScheduleFunction = function (scheduleFunction) {};

What do you think?

jraoult commented 10 years ago

I totally understand the rational and I agree with this "philosophy", it is actually why I chose Shifty. The setScheduleFunction is fine by me and it will fix my use case. As for the the performance cost I think it is negligible indeed specially if the default schedule function is defined once and then affected to the instance property at construction.

Are you happy to implement it or do you want me to send a pull request?

jeremyckahn commented 10 years ago

Sorry I didn't respond, I went to bed. :)

I'm glad we're on the same page with the approach. I don't think it should be too hard to implement this API, but I might not be able to get to it for a few days. You are welcome to put together a Pull Request and I will review/merge it when I have some time. Thanks!

jraoult commented 10 years ago

Ok, I worked last night on what we agreed on so that I could move forward with my project. I'll write some tests next week end and I'll send you a pull request.

jeremyckahn commented 10 years ago

Great, thanks for the update, and for implementing the feature. I'll keep an eye out for your Pull Request.

jeremyckahn commented 10 years ago

@jraoult, were you still planning to submit a Pull Request, or should this be closed?

jraoult commented 10 years ago

@jeremyckahn sorry, I was on holiday. The code is ready, I'll submit that this week end.

jeremyckahn commented 10 years ago

Looks like this never got closed — I'll do so now. Thanks again!