Skip to content
This repository was archived by the owner on Aug 11, 2019. It is now read-only.

Conversation

m59peacemaker
Copy link

Adds an option to tween so that when a tween is aborted by a new tween, the new tween's duration is adjusted according to how far the previous tween had progressed. This is like what svelte transitions do when a transition reverses an already running transition. Brief chat discussion about this.

@Rich-Harris
Copy link
Member

Thanks for the PR. Having thought about this a bit, I can't help but feel that it isn't quite the right solution. It's very likely that the duration for a given tween needs to be adjusted according to the difference between the current and starting value, which is only related to the progress along the previous tween in very specific circumstances. (Those specific circumstances are present with transitions, which is why it more-or-less works there.)

Exactly how that difference affects the duration depends on the effect you're trying to achieve (hence all the stuff about exponents in the original chat) — it's probably futile to try and create a convenience API for that. But I think it would make sense to add a spring method, that you'd use like so...

component.spring('foo', 100, {
  // I'm making this part up, would need to research
  // how to model spring physics. might only need
  // one variable!
  tension: 80,
  friction: 10
});

...and which would result in natural-looking motion. For example you could call that code repeatedly with the same value, and you wouldn't get the stop-start effect associated with easing functions. And the duration would naturally adjust to the difference between the start and end values. What do you think?

@m59peacemaker
Copy link
Author

m59peacemaker commented Aug 31, 2017

spring is awesome. I think it's been smarter than me, but maybe I just saw the light. These should produce identical behavior?

Tell me if I translate correctly (other than tension/friction):

      transitionIn () {
        this.tween(
          'modalStyle',
          { opacity: 1 },
          { duration: 400, easing: cubicOut, adjustDuration: true }
        )
      },
      transitionOut () {
        this.tween(
          'modalStyle',
          { opacity: 0 },
          { duration: 400, easing: cubicOut, adjustDuration: true }
        )
      },
      transitionIn () {
        this.spring('style', { opacity: 1 }, { duration: 400, easing: cubicOut, tension, friction })
      },
      transitionOut () {
        this.spring('style', { opacity: 0 }, { duration: 400, easing: cubicOut, tension, friction })
      },

@Rich-Harris
Copy link
Member

The idea behind spring physics models is that you don't set a duration or an easing function (because those are just ways to approximate spring physics) — instead you say what characteristics the spring has, and the duration (and velocity at any given moment) are derived from that moment-by-moment.

So it'd be more like this:

transitionIn () {
  this.spring('style', { opacity: 1 }, { tension, friction })
},
transitionOut () {
  this.spring('style', { opacity: 0 }, { tension, friction })
}

@m59peacemaker
Copy link
Author

I see. That does pose some difficulties. My use case is for transitions in/out that svelte-transitions are currently not able to handle. I think spring would work for the way I have it at the moment, but I would like to make the transitions customizable with options. Wouldn't people expect an easing option rather than tension and friction? Also, is it possible to create the same effects, such as bounce?

@Rich-Harris
Copy link
Member

It's probably better illustrated with some code — here's something I forked from a CodePen: https://jsfiddle.net/e674dddL/. Notice that it tracks the velocity of the mass, and on each frame calculates the acceleration...

acceleration = (stiffness * distance from target) - (damping * velocity)

...adds that to the current velocity, and adds the velocity to the current values. The result of that is smooth-looking motion. By tweaking the variables (careful not to set the damping too high!) you can get all kinds of different effects that easing functions are basically just trying to replicate. If you want a short duration, set a high stiffness; if you want bounce, set a low damping.

There isn't anywhere for duration and easing to 'go' — they're derived from the physical properties of the spring.

For fun, change the click on line 61 to mousemove. Notice how it doesn't matter that we keep changing the target x, y values (the equivalent of calling component.spring(...) over and over) — it just keeps doing its thing:

spring

@Rich-Harris
Copy link
Member

lemme know if you get a chance to try out spring(...), and if it meets your needs. Docs here: https://github.com/sveltejs/svelte-extras#springkey-end-options-live-demo

@m59peacemaker
Copy link
Author

spring() is working very well!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants