ractivejs / ractive

Next-generation DOM manipulation
http://ractive.js.org
MIT License
5.94k stars 397 forks source link

Allow use of animation API outside of transitions #1404

Closed pakastin closed 7 years ago

pakastin commented 9 years ago

Is it possible to use the transitions API manually, without adding to / removing from DOM?

Madgvox commented 9 years ago

What's your use case? Ractive doesn't really care what happens when the DOM isn't changing. That's probably a better task for jquery animation or some other animation library.

pakastin commented 9 years ago

I want to use as few JS libraries as possible (not using jquery). Would be great to be able to use the Ractive.js's animateStyle manually (without loading any extra libraries), since it is there already.. Possible?

Madgvox commented 9 years ago

There is http://docs.ractivejs.org/latest/ractive-animate, but I'm assuming that's not useful to you. That is a pretty good question, actually. Given that you can access nodes using ractive.find and ractive.findAll, it kind of makes sense that you should be able to animate them using the existing animateStyle.

@martypdx @Rich-Harris Is there a specific reason that those functions are only available to transitions?

pakastin commented 9 years ago

Yes I know there is ractive.animate, but I think it is not using CSS3 transitions, right? animateStyle would be far more powerful. I wouldn't mind to be able to use setStyle as well :)

dagnelies commented 9 years ago

It's a bad idea.

These transitions are related to adding/removing items from the model. When you add/change/remove the data, the corresponding visual elements appear/disappear. Everything is in sync.

Doing this manually would defy the purpose of RactiveJs. It could introduce conflicts (an element was removed while still in the data and vice-versa). Therefore, I am against this change. It's all about having sync between data and view, and this would scrape it all.

Instead of wanting to access the animations directly, simply surround it with {{#flag}}...{{/}} and everything will be taken care of. Actually, you don't even need to call the transitions, it'll be done for you.

Rich-Harris commented 9 years ago

My own experience is this:

I think there are valid situations where you'd want transition-like behaviour without adding/removing nodes. Take the interactive tutorials as an example - when you click on the circular navigation buttons, there's a subtle 'ripple' effect that emanates from the button. There isn't a great way to do that with data-binding, so instead we do this:

<span on-tap='ripple' class='...'>{{i + 1 }}</span>
this.on({
  ripple: function ( event ) {
    if ( event.node.classList ) {
      setTimeout( () => event.node.classList.add( 'tapped' ), 100 );
    }
  }
});

In the case above we're just using a CSS animation. That's the simplest approach. But it you needed something more complex (and supported in old browsers, via timers) then CSS animations wouldn't be possible.

I think it would be possible to expose some of the functions Ractive uses to coordinate this stuff. I'm not convinced it's the right thing to do though - having something like Ractive.util.animateStyle(...) would give the impression that this kind of thing was 'sanctioned', and unlikely to cause problems, when the reality is that it can get hairy quite quickly if you're not careful (I've definitely been bitten by this sort of thing - recently, in fact). My recommendation would probably be to use something designed explicitly for the task, like Velocity.js, which is a standalone animation engine.

Madgvox commented 9 years ago

I can vouch for velocity. That library is very lightweight, so if size is a concern it won't make a big impact.

It makes sense to use a library made for tweening, which ractive certainly is not. At that point I guess the question becomes the reverse: why are there animation utils in transitions in the first place? It seems like that would be outside ractive's scope of responsibility since ractive isn't an animation library.

I think I can answer my own question here. It's a matter of convenience. There's a reasonable expectation that a transition involves some kind of animating. Ractive provides those utils as a courtesy. It would be annoying to have to include an outside library in order to just make an element fade out when it's removed. It's not as reasonable an expectation on ractive's part that animation will take place outside a transition because like I said in my previous post, ractive doesn't really care what happens to nodes when data isn't changing. Thus, no need for animation utils.

As for op, there are quite a few very lightweight libraries for animation. You should easily be able to do the animation you want without adding to much weight to your project. On Oct 24, 2014 10:18 AM, "Rich Harris" notifications@github.com wrote:

My own experience is this:

  • Making changes imperatively rather than declaratively causes all kinds of crazy state management headaches, as @dagnelies https://github.com/dagnelies says. But...
  • ...sometimes you have to.

I think there are valid situations where you'd want transition-like behaviour without adding/removing nodes. Take the interactive tutorials http://learn.ractivejs.org/hello-world/1 as an example - when you click on the circular navigation buttons, there's a subtle 'ripple' effect that emanates from the button. There isn't a great way to do that with data-binding, so instead we do this https://github.com/ractivejs/learn.ractivejs.org/blob/master/src/ractive_components/left-nav.html#L201-L205 :

{{i + 1 }}

this.on({ ripple: function ( event ) { if ( event.node.classList ) { setTimeout( () => event.node.classList.add( 'tapped' ), 100 ); } }});

In the case above we're just using a CSS animation. That's the simplest approach. But it you needed something more complex (and supported in old browsers, via timers) then CSS animations wouldn't be possible.

I think it would be possible to expose some of the functions Ractive uses to coordinate this stuff. I'm not convinced it's the right thing to do though - having something like Ractive.util.animateStyle(...) would give the impression that this kind of thing was 'sanctioned', and unlikely to cause problems, when the reality is that it can get hairy quite quickly if you're not careful (I've definitely been bitten by this sort of thing - recently, in fact). My recommendation would probably be to use something designed explicitly for the task, like Velocity.js http://julian.com/research/velocity/, which is a standalone animation engine.

— Reply to this email directly or view it on GitHub https://github.com/ractivejs/ractive/issues/1404#issuecomment-60419793.

martypdx commented 9 years ago

I don't think there's anything wrong with Ractive having better support for declarative transitions and animations. I do think there are some distinct issues:

Yes I know there is ractive.animate, but I think it is not using CSS3 transitions, right?

@pakastin fyi - key difference is that ractive.animate animates the model, not the view.

pakastin commented 9 years ago

All I'd need is to be able to animate i.e. translate transform (with polyfills) and have a callback function – like:

Ractive.prototype.animateStyle( element, 'transform', 'translate("100%", 0)').then( function () {
  element.classList.add('hidden')
} );

I have tried to add CSS transitions and to listen transitionend -events, but they seem to trigger at wrong times and are a mess to write polyfills for. Usually I use TweenMax (gsap) for animations, but for a certain project I want to use CSS transitions instead.

evs-chris commented 7 years ago

There's a transition method available now, so I'm going to close this :smile: