ericdrowell / KineticJS

KineticJS is an HTML5 Canvas JavaScript framework that extends the 2d context by enabling canvas interactivity for desktop and mobile applications.
http://www.kineticjs.com
3.98k stars 754 forks source link

Transition vs Green Sock #439

Closed mihhail-lapushkin closed 11 years ago

mihhail-lapushkin commented 11 years ago

I did a quick patch to make the code backwards compatible with transitionTo. Then I tested both 4.4 and 4.5 KJS on my game that is the 4th community demo on KJS website. I can say that your code worked smoother. The difference was not dramatic, but for heavy levels with lots of circles GS lagged more (yes, I was using batchDraw).

I can send you the links if you want to see for yourself.

So I would suggest you continue with your transitioning code. GS is really fancy, but canvas is just a bit different world, here redrawing eats up most of the CPU regardless of how fast is your JS code and it's important that the animation code is aware of that and takes maximum effort to redraw in the most efficient manner. I believe your code did not have much of that and maybe GS is still better and it lags because of some KJS updates, but I just wanted to make a point about why a standalone tweening library might not be so good :)

And the most annoying thing about GS is that I would have to pay for the pricy license if I release a CocoonJS packaged paid app to mobile stores!

ericdrowell commented 11 years ago

wow this sounds pretty serious.

according to my perf tests, GS actually ran a bit faster than my original implementation of Transition. Is it possible that your patch introduced a perf hit?

One cool thing about using a 3rd party transition library is that it only updates properties, it doesn't handle the redraws. KineticJS still fully controls the animation engine, and the redraw logic. I'll take a look at this.

And in terms of the license. How can I say this. Holy crap. I was under the impression that GS did not require a license for use under any condition. From this alone, I'll have to to pull it back out (won't be too much trouble).

Thanks for pointing this out! Looks like I'll be releasing v4.5.1 soon.

atomictag commented 11 years ago

I've been using GS with Kinetic for a while now (before 4.5) and I honestly can say its performance is amazing. It also allows a better control of transitions and animations that eventually makes code simpler and more reusable, so I am not planning to move back to other tweening solutions.

Said that, it makes a lot of sense for Kinetic to provide its own transitions in order to:

+1 for pulling back transitions into the framework +1 to allow developers to rely on GS if they want/can do so

mihhail-lapushkin commented 11 years ago

the patch does not affect animation code, so it can't affect the speed

var redrawNode = this.nodeType === 'Stage' ? this : this.getLayer();
var duration = config.duration;

var vars = {
  onUpdate: function() { redrawNode.batchDraw(); },
  onComplete: config.callback ? config.callback.bind(this) : undefined,
  ease: easingMap[config.easing ? config.easing : 'linear']
};

delete config.duration;
delete config.callback;
delete config.easing;

for (var prop in config) {
  var val = config[prop];

  if (typeof val === 'object') {
    for (var p in val) {
      vars['set' + capitalize(prop) + capitalize(p)] = val[p];
    }
  } else {
    vars['set' + capitalize(prop)] = val;
  }
}

TweenLite.killTweensOf(this);

return TweenLite.to(this, duration, vars);

+1 to port transition control logic from GS to KJS :)

Thanks for quick reply!

jackdoyle commented 11 years ago

Thanks for sharing the concerns, guys. Of course I applaud Eric's decision to recommend GSAP as the animation tool of choice in KineticJS (not that I'm biased or anything) because there are HUGE workflow benefits, plus a bunch of added capabilities and even enhanced speed. It's a bold move that I think benefits users quite a bit, but I totally understand the push-back about dependencies and even licensing. Eric and I are discussing that now.

If the native stuff is left in, not only is there a file size and API bloat cost, but Eric would have to enhance and maintain that stuff too over time. And it just can't compare to all the stuff GSAP can do, so ultimately do you guys feel it's wise to keep it in there? Every minute Eric works on transition-related stuff is a minute he's not spending on another feature or bug fix.

Just to clarify, virtually all uses (including most commercial uses) are covered under the standard no-charge license. See http://www.greensock.com/licensing/ for details. It's extremely rare that folks need the special license (I'd guess 2% or less of users). And that license is responsible for getting the engine to where it's at today maturity-wise. GSAP represents many thousands of hours of development, refinement, optimization, documentation, support, etc.

Thanks for chiming in, atomictag, with your experience.

mihhail-lapushkin, one of the reasons your version might be running a bit slower is because you're doing a few expensive tasks in there, like "delete" three times and 2 nested for...in loops. In all my tests, TweenLite was faster than the native transition stuff in KineticJS, sometimes by a wide margin. I'd be curious to see a simple demo that indicates otherwise (not arguing - just genuinely curious).

mihhail-lapushkin commented 11 years ago

Hi Jack,

I have no doubts that GS is better in all possible means. The code that I showed runs only once to start the animation, but the problem was that the animation itself was a bit less smooth, although both performed quite good and even the CPU usage was the same. On a faster computer or the one with SSD or even in a faster browser like Chrome the difference is not noticeable, but that does not help me, since I make the game for mobile devices, where every bit of FPS makes sense. Maybe the problem was really in the updated KJS or how I had to make tiny adjustments to some parts of the game to make it compatible with 4.5, I don't know. It was a pretty clear comparison on a real product: same codebase with different engines. I will try to test it in CocoonJS on a really old device to see if results repeat. There the difference is more noticeable.

Thanks for the great discussion!

ericdrowell commented 11 years ago

I'm working on a new Tween class that's similar to my old Transition class. It will be like a Lite version of TweenLite, optimized specifically for KineticJS. It's nearly complete. The API will be consistent with Kinetic.Animation and Kinetic filters. The api will look like this:

var tween = new Kinetic.Tween({ node: rect, x: 300, ease: Kinetic.Eases.EaseInOut, duration: 1 });

tween.play(); tween.pause(); tween.reverse(); tween.reset(); tween.finish(); tween.kill(); tween.goto(time);

similar to Kinetic filters, the ease property will point directly to a function, not a key that maps to a function. This will make it easier for developers to create their own easings, or even pull in easings from other libraries.

This will come packaged with KineticJS v4.5.1 (or it can be removed using the custom build). It will not provide methods for tweening along curves, or controling tweening order via Timelines. For these types of advanced use cases, I'll point people to GS. As Jack points out, most people won't need to purchase a license. But I absolutely don't want people to create an app with KineticJS + GS, and then later find out that they need to buy a license for the GS portion, especially if they are just doing some basic tweens.

Since this is a rewrite, I'm expecting the performance to be screaming. stay tuned.

mihhail-lapushkin commented 11 years ago

Thanks for your hard work Eric!

I did a few more tests on desktop and actually have not found any significant differences in performance. From the visual point of view both engines performed identical. Regarding CocoonJS, I was not able to test it, because 4.5 version had some serious problems with animations, although it worked fine on desktop. Properties were tweening, but only one redraw was being executed though the whole tween. Maybe it has something to do with batchDraw, CJS delays RAF or something. Anyway, if 4.5.1 won't fix this I will investigate it more deeply.

ericdrowell commented 11 years ago

Thanks for hangin in there! 4.5.1 will be released this weekend.

ericdrowell commented 11 years ago

Done. Here's the commit:

https://github.com/ericdrowell/KineticJS/commit/622041aeafb9b5bfe4108b89e9f6c156c4f55ec8

and here's an example usage:

https://github.com/ericdrowell/KineticJS/blob/master/tests/js/manualTests.js#L173

I also added the ability to yoyo with a yoyo property. I didn't have a need for a kill() method. Anytime the tween pauses, the corresponding KineticJS animation auto stops. If you remove a reference to the tween instance, the JS garbage collector will auto remove it from memory.

One last tweak that I need to add, is tween overrides. When two tweens are tweening the same property of the same node, the last tween needs to take precedence. I'll have a follow up commit with this tomorrow.

jackdoyle commented 11 years ago

By the way, mihhail-lapushkin, you said that v4.5 had some major issues in CocoonJS on mobile, right? As if RAF wasn't working correctly? I haven't looked at the KineticJS source, so I cannot confirm this (Eric, please chime in), but I do know that iOS Safari has a bug (the browser itself) that causes requestAnimationFrame to only fire a few times initially and then suddenly stop. I wonder if something like that is at play here. This only happens the first time you load a page, but when you refresh, things work fine. GSAP has a workaround in place (it automatically falls back to using setTimeout() in this scenario) so that should work seamlessly, but if KineticJS isn't working around that bug with the RAF, that could explain why the batchDraw() stuff seemed to cut out. If you're using GSAP, you can add a "tick" listener to TweenLite.ticker to drive whatever you want, and it should work consistently (instead of relying directly on RAF).

To be clear, normal polyfills don't work around that particular bug because the browser technically does support RAF but it just breaks at times.

Maybe none of this is the least bit applicable here - I just figured I'd mention it in case it's helpful somehow.

mihhail-lapushkin commented 11 years ago

Thanks for your comment Jack!

Eric, onFinished seems to not work.

ericdrowell commented 11 years ago

The new Tween class is a full rewrite. The old Transition class was a port that someone from the community submitted. There were a lot of things that I didn't like about it, such as the "onFinished" event name. This has changed to "onFinish" to be consistent with other event types, such as onClick, onMouseover, etc. I took out the "ed" :)

ericdrowell commented 11 years ago

hey guys, it does turn out that a bug was introduced when refactoring the Animation class - the setTimeout fallback was lost. It's been fixed and will be a part of 4.5.1:

https://github.com/ericdrowell/KineticJS/wiki/Release-Schedule#451-apr-11-2013

@mihhail-lapushkin can you verify if a JS error was being thrown?

mihhail-lapushkin commented 11 years ago

Well, in the blacklist you still have onFinished and I don't see any onFinish events fired...

Are you asking about those 4.5 animation problems? I experienced not in Safari, but in CocoonJS and I am not sure if they are even related to this bug.

ericdrowell commented 11 years ago

Thanks! I changed the onFinished key to onFinish

the 4.5 animation issue will affect all browers using an older version of webkit. I believe CocoonJS uses webit, correct?

mihhail-lapushkin commented 11 years ago

nope, you're mistaking with PhoneGap CocoonJS is separate browser-like emulator for canvas only

ericdrowell commented 11 years ago

right, it uses accelerated canvas. Okay. I didn't think that KineticJS every worked wth accelerated canvas. It's already on my todo list.

ericdrowell commented 11 years ago

It is done. v4.5.1 is live. Here's a tutorial that shows off the new API:

http://www.html5canvastutorials.com/kineticjs/html5-canvas-stop-and-resume-transitions-with-kineticjs/

Sorry for the confusion!

P.S., I still fully believe that GreenSock is the best Tween library on the planet. for more advanced use cases, drop the Tween class and go with GS.