Jump to content
GreenSock

eigenface

Members
  • Posts

    72
  • Joined

  • Last visited

eigenface's Achievements

Newbie

Newbie (1/14)

0

Reputation

  1. Thanks. For anyone who is reading this thread after searching for the same topic, like I did, I found a good quadratic bezier length algorithm here: https://code.google.com/p/bezier/source/browse/trunk/bezier/src/flash/geom/Bezier.as I found other implementations didn't handle edge cases well - sometimes they returned NaN.
  2. I'm in a similar situation to da2020, in that I need to be able to specify the speed of an object on a bezier tween. In order to get the duration, I need the distance along the bezier curve. I could use a similar solution, that is, convert "thru" points to quadratic control points using BezierPlugin.bezierThrough, use a custom algorithm to calculate the bezier curve length from the control points, and then use a type:"quadratic" bezier tween with those same control points. However, I notice BezierPlugin has a _length property which appears to be the total bezier curve length, or at least the approximate length that BezierPlugin uses. Is it better to use the value of this _length property when calculating duration from speed (because this is the length of the path an object on the tween will actually follow)? Would it be possible to expose this _length to the public API in some way? It would be handy, and it seems a shame not to expose it, if it's already being calculated anyway.
  3. Thanks so much for this detailed explanation. My previous example works correctly if I add smoothChildTiming:true to the parentTimeline as you've indicated. To be honest, I didn't fully understand the explanation. I have a few questions, to make sure I'm setting things up correctly in my project. In my project, I want to put user-generated tweens in several different bottom-level timelines so I can pause/kill them by category (carsTimeline, trainsTimeline...), as well as add the timelines as children of a common parent timeline so I can pause/kill everything easily. Also, I want the bottom-level timelines to have autoRemoveChildren:true, so I won't accumulate completed tweens (which are never used again.) 1. Do I need to add smoothChildTiming:true to every ancestor timeline, except the bottom-level timeline which contains the tweens, like so? carsTimeline = new TimelineMax({ autoRemoveChildren:true }); parentTimeline = new TimelineMax({ smoothChildTiming:true }); grandParentTimeline = new TimelineMax({ smoothChildTiming:true, paused:true }); ... carsTimeline.add(TweenMax.delayedCall(carDelay, spawnCar), carsTimeline.time()); ... parentTimeline.add(carsTimeline); grandParentTimeline.add(parentTimeline); ... grandParentTimeline.play() As you can see, I also have paused:true in the top-level timeline, so I can add some initial tweens (in fact, delayed calls) and start them later. 2. I don't need to use totalTime(), right? (time() honors delays, just not repeatDelays)
  4. With GSAP 12.1.3, the above simplified example works correctly, but when I try it with my project, I still get weird behavior. I've included another sample that demonstrates the problem. All I've done is add a parent timeline. package { import com.greensock.TweenMax; import com.greensock.TimelineMax; import com.greensock.easing.*; import flash.display.SimpleButton; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.Event; public class Main extends Sprite { protected var tween:TweenMax; protected var timeline:TimelineMax; protected var parentTimeline:TimelineMax; protected var circle:Sprite; public function Main() { addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true); } protected function addedToStageHandler(event:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); timeline = new TimelineMax(); parentTimeline = new TimelineMax(); parentTimeline.add(timeline); circle = new Sprite(); circle.graphics.beginFill(0); circle.graphics.drawCircle(320, 340, 100); circle.graphics.endFill(); addChild(circle); var upState:Sprite = new Sprite(); upState.graphics.beginFill(0xFF0000); upState.graphics.drawRect(270, 140, 100, 100); upState.graphics.endFill(); var button:SimpleButton = new SimpleButton(upState, upState, upState, upState); addChild(button); button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true); } protected function mouseDownHandler(event:MouseEvent):void { if (tween != null) { tween.kill(); } circle.alpha = 1; tween = TweenMax.to(circle, 3, { alpha:0, ease:Quint.easeOut }); timeline.add(tween, timeline.time()); } } } Now, only the first click behaves as expected. Subsequent clicks do nothing while the alpha fade is in progress. If I click after the fade is complete, the circle appears at full alpha, and once again subsequent clicks do nothing. Is this behavior correct? Is there a way to make this work?
  5. Thanks a lot, Jack and Carl! Everything works as expected now.
  6. Thanks again, Carl! Your new mouseDownHandler with the play() call works as expected. However, I still think I've found a bug or inconsistency, which you may want to address in the update. I still get weird behavior if I add the play() call to my original mouseDownHandler (and pass { paused:true } to the timeline constructor.) In that case, the first click has the desired effect, but subsequent clicks do nothing at all. Here is the code to reproduce this apparent bug: package { import com.greensock.TweenMax; import com.greensock.TimelineMax; import com.greensock.easing.*; import flash.display.SimpleButton; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.Event; public class Main extends Sprite { protected var tween:TweenMax; protected var timeline:TimelineMax; protected var circle:Sprite; public function Main() { addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true); } protected function addedToStageHandler(event:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); timeline = new TimelineMax({ paused:true }); circle = new Sprite(); circle.graphics.beginFill(0); circle.graphics.drawCircle(320, 340, 100); circle.graphics.endFill(); addChild(circle); var upState:Sprite = new Sprite(); upState.graphics.beginFill(0xFF0000); upState.graphics.drawRect(270, 140, 100, 100); upState.graphics.endFill(); var button:SimpleButton = new SimpleButton(upState, upState, upState, upState); addChild(button); button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true); } protected function mouseDownHandler(event:MouseEvent):void { if (tween != null) { tween.kill(); } circle.alpha = 1; tween = TweenMax.to(circle, 3, { alpha:0, ease:Quint.easeOut }); timeline.add(tween, timeline.time()).play(); } } } Is this behavior a bug? I mean, according to the API, the above mouseDownHandler should produce the same result as your new mouseDownHandler, right? Or no?
  7. Thanks, Carl! Your mouseDownHandler almost works correctly. The first click jumps to somewhere in the middle of an alpha fade already in progress, depending on how long you wait before clicking the first time. Subsequent clicks have the desired effect. I have been using the latest version of GSAP (12.1.2) - are you seeing this first-click problem also? In addition, I just want to get confirmation that I'm not crazy - my original mouseDownHandler looks like it should work, right? (It exhibits the same weirdness it always did if I switch totalTime to time.) My mouseDownHandler looks like a different way of writing your mouseDownHandler, but the visible behavior should be the same. The fact they exhibit different behavior seems buggy. Or am I missing some subtlety of the API?
  8. I've included a simplified sample of some code from a project I'm working on. The user initiates a tween by clicking a button. I want to throw this tween in a timeline with a bunch of other user-initiated tweens (not included in the sample), so I can pause/resume and kill them all en masse. Because these tweens are user-initiated, they can be created and started at any time, with other tweens already in progress. You can run the sample code to see how this is supposed to look: every time you press the button, the circle starts fading out, and you can press the button repeatedly to reset the fade and start it over. Then you can try uncommenting the last line of code (adding the tweens to the timeline.) My intention is for this to make no difference to how the circle behaves when you press the button - nothing should change. As you'll see, the behavior is actually quite different with the last line uncommented. I've tried with and without the second parameter to timeline.add, and I've tried adding overwrite:"all" to the tween (instead of killing it manually), all with different, unsatisfactory results. Are these behaviors intended? Is there a way to do this, that is, add new tweens to a timeline at arbitrary future times, without affecting the behavior of the tweens? . package { import com.greensock.TweenMax; import com.greensock.TimelineMax; import com.greensock.easing.*; import flash.display.SimpleButton; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.Event; public class Main extends Sprite { protected var tween:TweenMax; protected var timeline:TimelineMax; protected var circle:Sprite; public function Main() { addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true); } protected function addedToStageHandler(event:Event = null):void { timeline = new TimelineMax(); circle = new Sprite(); circle.graphics.beginFill(0); circle.graphics.drawCircle(320, 340, 100); circle.graphics.endFill(); addChild(circle); var upState:Sprite = new Sprite(); upState.graphics.beginFill(0xFF0000); upState.graphics.drawRect(270, 140, 100, 100); upState.graphics.endFill(); var button:SimpleButton = new SimpleButton(upState, upState, upState, upState); addChild(button); button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true); } protected function mouseDownHandler(event:MouseEvent):void { if (tween != null) { tween.kill(); } circle.alpha = 1; tween = TweenMax.to(circle, 3, { alpha:0, ease:Quint.easeOut }); //timeline.add(tween, timeline.totalTime()); } } }
  9. Thanks for the great example! This seems to work well. I notice you don't pass the 'paused:true' parameter to the tween or the timeline. This doesn't seem to make a difference one way or the other to the loop (the actual animation does not run if paused, of course.) Are there any subtle reasons why passing 'paused:true' is not a good idea?
  10. I'm animating an object across the screen, which the user has to track and find later. I'm also animating an object which moves around on top so as to occlude the object the user is trying to track. The amount of time the tracker is supposed to be occluded is specified in advance. The way I've found to handle this in the general case is to generate some random paths for the tracker and occluder to follow. Then, I simulate the objects animating down those paths, and use bitmap logic on each timestep to determine when they occlude. If the occlude time is not in the correct range, I generate more random paths and repeat. Of course, I want the simulation to happen as fast as possible - I don't want it to take just as long as actually animating the objects. I want to run through the timesteps in a loop, rather than waiting for enterFrame events like GSAP normally does. I really like the power and flexibility of GSAP for animating the objects in various ways - that's part of the what makes the task work. But I need to know exactly how they'll render in advance, without waiting for a normal animation to complete. Is it enough to do something like this: var tl:TimelineMax = new TimelineMax({ onUpdate:checkOcclusion, paused:true }); // add tracker and occluder objects for (var i:int = 0; i < steps; i++) { tl.render(i*timeStep); } Or do I have to worry about what's going on in the _updateRoot function of Animation.as? Both _updateRoot and render are declared private in the docs (though public in reality, for code-architecture reasons, I assume.) So I figure I should ask your advice about this in case there are subtle issues.
  11. Oops, posted at the same time. Thanks for the help. For future reference, the correct code is: TweenMax.to(this, pathTime, { bezier:{ values:pathObjArray, autoRotate:true, type:"soft" }, ease:Linear.easeNone, onComplete:onComplete }); where pathObjArray.length == 3 because the endPoint values have been added to the end of values:pathObjArray.
  12. Did you by any chance change whether or not the end point is supposed to be included in the bezier point array? I ask because even though my point array has 2 points, when I use type:"quadratic", I get an error which looks like it's due to not having enough bezier points. Adding the end point to the bezier point array causes even weirder behavior, though. I'm just taking shots in the dark here as to how the bezier tween has changed from v10 to v12, it would be nice to have a "canonical" translation.
  13. A while back, I made a flash app using gs v10, using bezier tweens. Recently, I recompiled it for some necessary maintenance, using gs v12. The bezier tweens are messed up - the sprites being tweened don't orient to the curves, and sequences of bezier tweens that used to flow smoothly one into the next now make the sprite suddenly jump from one angle to a different angle when one tween stops and the next one starts. I've tried testing out all the new bezier settings (including type:"thruBasic"), trying to recreate the behavior of the v10 tweens, but I can't figure out how. Is there a way? My original tween code looked like this: TweenMax.to(this, pathTime, { x:endPoint.x, y:endPoint.y, bezier:pathObjArray, orientToBezier:true, ease:Linear.easeNone, onComplete:onComplete }); where pathObjArray.length == 2. What code should I use to recreate the same behavior as closely as possible in v12?
  14. I notice the LoaderMax version number is inching up on 2. I'm curious, is there a new, potentially-API-changing version in the works, similar to the major releases of TweenLite/Max? If so (and even if not), I have a feature request: I'd like to pass in a callback or event handler that will be called if the loader has not completed after a given period of time. Better yet, I'd like to be able to set a number of times for the loader to automatically retry if it fails due to such a timeout. True, it's not difficult to set this up outside LoaderMax, and every feature adds kb. But when you have a lot of traffic on your website, serving lots of content, CDN, etc. then the reality is a certain percentage of all loads "hang", that is, the load never completes even though no error is ever thrown. Timing out and retrying the load in these cases is a necessary feature of any loading setup suitable for a large-scale operation, and it would be nice if LoaderMax supported this out-of-the-box.
×