Jump to content

OSUblake last won the day on August 15 2019

OSUblake had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


Community Answers

  1. OSUblake's post in draggable onDrag hitTest with a timer was marked as the answer   
    Here's another way to do this. Create a flag and a paused delayedCall. The flag is just a quick way to let you know that the timer has started.
    If you detect a hit and the flag is false, restart the delayedCall and set the flag. If the flag is set and you detect a hit, do nothing. If the flag is set and there is no hit, pause the delayedCall and clear the flag. 
    var draggable = new Draggable(foo, { onDrag: function() { // We're not hitting the target if (!this.hitTest(hitTarget)) { // We were hitting the target if (this.hitID) { this.hitID = 0; this.hitTimer.pause(); } return; } // We just hit the target if (!this.hitID) { this.hitID++; this.hitTimer.restart(true); } } }); draggable.hitID = 0; draggable.hitTimer = TweenLite.delayedCall(0.7, function() { // your callback }).pause(); See the Pen qmOeMd by osublake (@osublake) on CodePen

  2. OSUblake's post in Multiple timelines sharing ".add(.play())" won't play was marked as the answer   
    Looks like there is a lot of confusion going on here. Like PointC said, a child can only belong to one parent. Made a similar post yesterday about that.
    But I think the bigger issue here is understanding .add() and how stuff evaluates.
    Using .add(), you can add a tween, timeline, callback, or label. So what are you adding here?
    playMe.add(scaleMe.play()) If you said a callback/function, you're wrong. You're adding the scaleMe timeline to the playMe timeline. You're calling .play(), and if you look in the docs, you'll see that it returns itself, which would be the timeline.
    To call play as callback, you would need to do one of these...
    // Bound callback playMe.add(scaleMe.play.bind(scaleMe)); // Add callback playMe.addCallback(scaleMe.play, "+=0", [], scaleMe); // Callback playMe.add(function() { scaleMe.play(); }); Let's look at how some other things evaluate.
      What is this?
    playMe.add(noop); function noop() {} That's a callback.
    Then what is this?
    playMe.add(noop()) function noop() {} That will result in an error. By default, every function in JavaScript returns undefined when it's called. That lets the JavaScript engine know when the function is done running. The reason for the error is because it's returning undefined, and you can't add undefined to a timeline.
    So what's this?
    playMe.add(createTween()) function createTween() { TweenLite.to("#foo", 1, { x: 100 }); } Another error. It's returning undefined.
    What about now?
    playMe.add(createTween()) function createTween() { return TweenLite.to("#foo", 1, { x: 100 }); } That's a tween, which will be added to the timeline.
    What about now?
    playMe.add(createTween) function createTween() { return TweenLite.to("#foo", 1, { x: 100 }); } That's a callback, which will create a tween that will run independently from the timeline. Returning something in callback will have no effect, it's void.
    What's going to happen here?
    playMe .add(createTween1) .add(createTween2()) function createTween1() { return TweenLite.to("#foo", 1, { x: 100 }); } function createTween2() { return TweenLite.to("#bar", 1, { x: 100 }); } If the timeline is empty, both tweens will start playing at the same time. The second tween is the only one that will be part of the timeline. The first tween is created inside a callback.
    So what's going to happen here?
    playMe .add(createTween1()) .add(createTween2()) function createTween1() { return TweenLite.to("#foo", 1, { x: 100 }); } function createTween2() { return TweenLite.to("#bar", 1, { x: 100 }); } The tweens will play sequentially, and both tweens will be part of the timeline.
  3. OSUblake's post in Competing progress() calls inside of resize was marked as the answer   
    Hi @zachschnackel,
    Not sure if I totally understand your issue, but here's how I handle resizing. I record the state of an animation, usually it's progress value and reversed state, but it all depends on the animation. For a repeating animation that yoyos, I would just record the totalProgress.
    Next, I set the progress of the animation to 0 and clear it. That should prevent any inline styling issues. Finally, I rebuild the animation, and set the state of the animation to the values I recorded earlier. The performance impact of creating new animations is minimal, and is something I would not worry too much about unless you notice it's an issue. Rendering is the bottleneck 99% of time, not your JS.
    Here's a simple demo of how that looks.
    See the Pen 3f8b76a324743b25b786026d5b711fff?editors=0010 by osublake (@osublake) on CodePen

    And here's a more advanced demo using some media query listeners. 
    See the Pen ee36b4d9caaea7e27815cd5f7f76d14c?editors=0010 by osublake (@osublake) on CodePen

  4. OSUblake's post in Maintain velocity on re-positioned objects with ThrowProps was marked as the answer   
    Here are some nice functions you can use with the ModifiersPlugin...
    One thing to keep in mind about the ThrowPropsPlugin is that it's not tied to Draggable. So here's a quick fork showing how you can create a throw tween with some modifiers. I think calculating the end position using that formula will eliminate the jump at the end.
    See the Pen LWwoBP?editors=0010 by osublake (@osublake) on CodePen

    And if you're still looking into using Pixi, here's how to get the ThrowPropsPlugin working with it. Pretty similar to what I did in the demo above.
    See the Pen 524a3acb87900129a205f2fa1143bc5d?editors=0010 by osublake (@osublake) on CodePen

  5. OSUblake's post in this.hitTest in onDragEnd but for final position was marked as the answer   
    Using throwProps creates a tween. Set its progress to 1, run your hit test, then reset the tween. The green box will turn red if it's going to land on the blue.

    See the Pen d1687bdbb9d06162e9ad804996979691?editors=0010 by osublake (@osublake) on CodePen
  6. OSUblake's post in Re-Run tween in a timeline at a later point in the timeline was marked as the answer   
    There are several issues with that. A tween can be part of a timeline in only one place, and will be controlled by it's parent, so you would need to restart the timeline in some way to replay the same tween.
    This is similar to what you are trying to do, but with 3 tweens...
    See the Pen WpVzym?editors=0010 by osublake (@osublake) on CodePen

    But I would recommend a better approach. Use functions to create your tweens. It reduces the amount of code you need to write, and you can pass parameters into your functions to customize the tween.
    See the Pen aJeYVN?editors=0010 by osublake (@osublake) on CodePen

  7. OSUblake's post in CustomEase might not be properly normalizing SVG path data was marked as the answer   
    I'm not familiar with how the coordinate system AfterEffects works, but by looking at your screenshot, it appears to be starting in the bottom-left corner. For svg, the y-axis is reversed, starting in the top-left corner, so try flipping the y values.
  8. OSUblake's post in BezierPlugin.bezierThrough with type = 'soft' was marked as the answer   
    The bezierThrough method is only for doing Beziers with type thru as it's proprietary. The soft method is not, and is pretty common if you search around.
    But you don't have to do that. I made a demo the other day to show somebody about using that method to draw stuff, so I just added the soft type so you can see a side-by-side comparison. Blue is the thru, and red is soft. 
    See the Pen 7047db2bc35bde1c480e954878a2e699?editors=0010 by osublake (@osublake) on CodePen

  9. OSUblake's post in Restart timeline was marked as the answer   
    You have some logic errors going there.
    But first, don't use setTimeout/setInterval for animations. It's not synced to the animation frames, and can cause problems if the users switches tabs and comes back later. Use TweenLite.delayedCall() instead. 
    About your logic problem. You're declaring a new timeline on each call to your carousel function, then you have an if statement with a call to restart the timeline, then you declare the animations for that new timeline. The if statement is restarting the timeline, there's just no animations to restart because you're declaring them after the if statement.
    If all you're trying to do is cycle through some animations, you could probably do it all in a loop like this...
    See the Pen ryZZmy?editors=0010 by osublake (@osublake) on CodePen

  10. OSUblake's post in TweenLite.ticker does not work as expected was marked as the answer   
    Hi ,
    GSAP uses rAF, and if you're calling rAF, that means there will be two calls out for it, which get added to a queue. That means there is no guarantee your call will happen in the same order or frame as GSAP's call. Letting GSAP make the call will help keep your rendering in sync with the objects it updates. You can even prioritize the order in which things get called.
    Need to run some logic before GSAP updates? Not a problem. Just add a listener with a positive priority. Need to do some cleaning up after GSAP updates? Just a add a listener with a negative priority.
    // Called before update TweenLite.ticker.addEventListener("tick", preUpdate, this, false, 100); // Called after update TweenLite.ticker.addEventListener("tick", postUpdate, this, false, -100); Don't need those listeners anymore? Remove them.
    TweenLite.ticker.removeEventListener("tick", preUpdate); TweenLite.ticker.removeEventListener("tick", postUpdate); If there's an active listener on the ticker, it's going to call it. That should be the expected behavior for any ticker, not just GSAP's. I use the ticker for other stuff, like frame based animations or throttling browser events. If GSAP stopped calling any listeners after it was done animating, well that would be bad. GSAP has no way of knowing what I'm using the listener for. 
    And you might now even need to use the ticker. You said you were using a main timeline, so you could use its onUpdate callback  to call your render method. That's what I do for simple stuff that doesn't require the ticker to run constantly.
    To help get a better understanding of what I just talked about, I made a really simple demo for you. Notice how the listeners are happening in the correct order. If you change their priorities, the count won't come out to zero. And when I'm done with the animation, I just remove the listeners. 
    See the Pen d360a2ce841054f74fac985ac7062c44?editors=0010 by osublake (@osublake) on CodePen

  11. OSUblake's post in draggable with dragClickables:on prevents some textarea shortcuts was marked as the answer   
    To prevent selecting text outside of the textarea, you could do something like this in the onPress callback.

    See the Pen QpOGBp?editors=0010 by osublake (@osublake) on CodePen
  12. OSUblake's post in Gsap and glitches in 3d model animation was marked as the answer   
    What you have looks good! While you can do 3d using html/svg, it's really not designed for complex stuff. The glitching you're seeing might be a culling issue, which you can sometimes fix using more shapes.
    If you want to do more complex 3d stuff, I would recommend using a 3d library like Three.js or Babylon.js. Both work great with GSAP. Three.js is a more general purpose library. Babylon is geared more for animation and games, and I would have to say that it's easier to use.
    * Not sure why, but I'm getting a not secured warning for that Babylon link in Chrome. It's a Microsoft product, so I'm assuming it's safe.
    BTW, your demo reminded of some stuff done by See the Pen public by Yakudoo (@Yakudoo) on CodePen
    . They're kind of advanced, but you can see what's possible using a 3d library.
    See the Pen YXxmYR?editors=0010 by Yakudoo (@Yakudoo) on CodePen

  13. OSUblake's post in document.querySelectorAll() not working was marked as the answer   
    It works, but I think you might be confusing its usage with jQuery. document.querySelectorAll() returns a nodelist, which is kind of like an array of elements. So to create a click event and animation for each element, you need to loop through that nodelist, creating a unique click event and animation for each element.
    If you're new to JavaScript, I would recommend calling a function from the loop to prevent any scope issues. Also, it's generally not a good idea to assign a function to an event. Use addEventListener instead.
    // Bad element.onclick = function() { ... }; // Good element.addEventListener("click", function() { ... }); See if this helps you out...
    See the Pen QpqjdB?editors=0010 by osublake (@osublake) on CodePen

    And there's no shame in using jQuery. It's battle tested, works, and could simplify a lot of this.
  14. OSUblake's post in How to play a part of TimelineLite? was marked as the answer   
    You can tween the progress, time, etc of a timeline with a regular tween.
    TweenLite.fromTo(myTimeline, 2, { time: 5}, { time: 7, ease: Linear.easeNone });
  15. OSUblake's post in Draggable Progress Monitor was marked as the answer   
    The callbacks for throwProps are listed in the Draggable docs (onThrowUpdate, onThrowComplete). Simple demo...
    See the Pen d693ccaaccc43be08024b1e9567f7222?editors=0010 by osublake (@osublake) on CodePen

  16. OSUblake's post in GSAP doesn't work with innerHTML was marked as the answer   
    The correct way to do this without jQuery is to use insertAdjacentHTML. Please see this post.
  17. OSUblake's post in grouping parallel tweens in a timeline more conveniently was marked as the answer   
    While not always a good idea, every object in JavaScript has a prototype that you can add methods and properties to. For your group idea to work, it will require some work, and might not be worth the effort, but here's the basic idea. You'll have to create an object with the methods of a timeline you want to use, but without a duration and position parameter. Basically a fake timeline. You'll use that fake timeline to add tweens to the real timeline.
    See the Pen 336146a07bb599bb5c895d860fbc4615?editors=0010 by osublake (@osublake) on CodePen

  18. OSUblake's post in Why are rotateZ and rotetionZ different? was marked as the answer   
    Order matters for transforms, so you have it backwards. These are the same.
    TweenMax.to(obj, 1, { transform: "rotateZ(100deg) rotateY(100deg) rotateX(100deg)" }); TweenMax.to(obj, 1, { rotationX: 100, rotationY: 100 , rotationZ: 100 });
  19. OSUblake's post in Rotate SVG path around its center was marked as the answer   
    That's a transform matrix, which combines all transforms. Click the red pill...
    But I doubt that is the problem. I see you have CSS transitions. Try removing those. If you need more help, please make a demo.
  20. OSUblake's post in Combining click and hover animation was marked as the answer   
    It sounds like what you have might already be simpler than using GSAP for everything, but it's still possible. I show how to toggle animations based on various conditions in this thread.
    Those demos use jQuery, but arrays have a map function too, so it works out pretty much the same.
    See the Pen OWKevR?editors=1010 by osublake (@osublake) on CodePen

  21. OSUblake's post in Draggable clickable (same element) was marked as the answer   
    To allow events to go through, do like this...
    Draggable.create(draggables, { allowEventDefault: true });
    See the Pen KaOjaq by osublake (@osublake) on CodePen
  22. OSUblake's post in Physics collision vs applyBounds() for draggable? was marked as the answer   
    If all you're trying to do is keep your draggable from overlapping with another one, you can just set the bounds. There's no need for hit testing.
    See the Pen a820ab5bf748b4d1f45083edb2a0843f?editors=0010 by osublake (@osublake) on CodePen

  23. OSUblake's post in Having two scripts with including TweenLite from npm/gsap was marked as the answer   
    I know nothing about Browserify, but I can tell where this default is coming from
    _gsap2.default.to(...); //_gsap2.default is undefined. It's because you're importing like this, which is for export default.
    import TweenLite from 'gsap'; It should be like this...
    import {TweenLite} from 'gsap';  I always tell people you only need to import GSAP once like this. This will put GSAP on the window, making it global so you don't have to import it again.
    import "gsap"; Or better yet, don't import gsap at all. Use a CDN and let the browser cache it. 
  24. OSUblake's post in How to stick the element to the border was marked as the answer   
    I can think of several ways to do this, but it's all going to depend on the behavior you want and the shape of the room. A room with more than 4 corners is going to add a little complexity.
    I didn't see your latest posts about how you were thinking you wanted to snap on drag end, but here's how you can make it snap while dragging. I'm using a new snap point feature, which isn't the docs, but it's discussed here.
    I couldn't get the axis lock to change while dragging, so I'm manually doing that. It detects if it's inside a corner, and if so, it clears the lockedAxis value, allowing it to adjust to a change in axis movement.
    See the Pen 6d3b6653862f81c2cf7e9891bedc35e7?editors=0010 by osublake (@osublake) on CodePen

    That demo allows for a little wiggle room in the corners, but if you wanted it to be a little stricter, you could skip the liveSnap and just change the bounds whenever you're inside a corner. Basically create a bounds object that will only allow movement along a certain edge.
  25. OSUblake's post in Best way to apply a modifier tween on multiple targets? was marked as the answer   
    Funny. I actually asked about being able to pass in indexes to a modifier functions, but that idea only made it to function-based values.
    I'm pretty sure your going to need some type of loop here, unless there's some super crazy es6 way of destructuring it. I know all the cool kids are using "let" and "const" statements nowadays, and here it actually works out because "let" creates a new scope on each iteration. If you replace "let" with "var", it won't work correctly because the i value will be the same for each animation.
    I've been avoiding using "let" because it can be really slow... and I think it looks stupid, but that's just me. 
    I've never had a problem with var because I normally don't run a lot of code inside a loop. I usually pass something off to a function, which will create a new scope. 
    See the Pen bgOevd?editors=0010 by osublake (@osublake) on CodePen

    Actually, if you look at all the demos I made in that thread, almost every single one is done the same way. I'm using a simple loop to pass some value off to a function, which creates the animation.