CreateJS / TweenJS

A simple but powerful tweening / animation library for Javascript. Part of the CreateJS suite of libraries.
http://createjs.com/
MIT License
3.56k stars 966 forks source link

Timeline '_updateTimeline' related issue. #37

Closed legman closed 7 years ago

legman commented 10 years ago

Hello there!

I believe I have unearthed a bug/design flaw that boils down to a few things. I came across this issue firstly when I needed to dynamically remove a MovieClip's child created via Toolkit.

It turns out that MovieClips that exist within another MovieClip's timeline don't actually have any parents until the following frame when _updateTimeline is called.

console.log(someMC.parent);    // Returns null
someParentMC._updateTimeline();
console.log(someMC.parent);    // Returns someParentMC

The issue came about again when a colleague asked me for help regarding an issue he was having when a MovieClip wasn't changing frame despite him calling gotoAndStop();

The problem turned out to be the MovieClip's parent had more than 1 frame which lead to different code generation via Toolkit. MovieClips with a single frame simply use addChild(), where as MovieClips with multiple frames use timeline.addTween().

The latter leads to the above issue where _updateTimeline() has not been called until the following frame at which point the frames actually exist.

As shown above in the sample code, calling _updateTimeline() prematurely resolves the issue but this method is essentially protected and more importantly highlights the lack of addedToStage/removedFromStage event dispatching that would be used in AS3.

You are obviously waiting for the next frame to initialise a MovieClips timeline because you can't do it in the constructer. I feel addedToStage/removedFromStage functionality would be helpful in this situation, although its not 100% ideal because you would still have to add the parent to the display list before its timeline was initialised but it would still be better than waiting for the next frame.

In general, I think addedToStage/removedFromStage would be a great addition to DisplayObject.

Please let me know what you think of my findings, is this a bug or a design oversight, maybe _updateTimeline() should be considered public and documented?

Thanks for your time!

gskinner commented 10 years ago

I just recently pushed an update to EaselJS NEXT with "added" and "removed" events. You can see the discussion here: https://github.com/CreateJS/EaselJS/issues/272

I can definitely see your point here. It's a use case we hadn't considered. There was a lot of work done to keep file size down, and code readable in the Flash output, and that meant we didn't want to duplicate the frame 0 state in both the timeline and the symbol definition. The issue that you've encountered is that the initial state isn't available until the timeline actually advances to that frame.

You could call gotoAndStop(0), though in the current version of MovieClip this will mean that the next "tick" it will advance to frame 1.

I'm not sure of an ideal solution. In 99.9% of cases, people should be using gotoAndStop() to trigger _updateTimeline(), which is why its private. Maybe we should support gotoAndStop(-1)? Or, maybe the "added" event will handle this edge case for you? Totally open to suggestions on this one.

gskinner commented 7 years ago

I believe this issue has been resolved in more recent Animate builds.