Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animation #18

Open
nichoth opened this issue Apr 29, 2016 · 19 comments
Open

Animation #18

nichoth opened this issue Apr 29, 2016 · 19 comments

Comments

@nichoth
Copy link
Contributor

nichoth commented Apr 29, 2016

I would be interested in hearing how people animate elements when they are added or removed from the DOM.

@shama
Copy link
Collaborator

shama commented Apr 30, 2016

I generally use CSS animations and toggle with class names.

@nichoth
Copy link
Contributor Author

nichoth commented Apr 30, 2016

@shama you listen to a hook in the element lifecycle?

@shama
Copy link
Collaborator

shama commented Apr 30, 2016

Yep! Or just on an action, here is an example: http://requirebin.com/?gist=d8eb549ac5452bc512e5d12b6838cb3c

@SilentCicero
Copy link

@nichoth from and to CSS animations is definitly the best way to go here. For life cycles I use throw-down naturally =D

@nichoth
Copy link
Contributor Author

nichoth commented May 1, 2016

Thanks all. I would really like to fade out/fade in nodes as they are added or removed using CSS transition. I have been playing with morphdom hooks but haven't figured it out yet.

@SilentCicero
Copy link

@nichoth I'm working on something similar here: https://github.com/SilentCicero/yoyo-bootstrap/blob/master/fade.js

@shama
Copy link
Collaborator

shama commented May 1, 2016

@nichoth Create an animation class .fadein and assign to the element you want to fade in when creating it. Then the action that would cause it to fade out, removes the .fadein class and adds the .fadeout class. When the animation has completed, the action completes (such as calling yo.update() to replace the element or send a xhr, etc)

Usually when an element is inserted or removed from the DOM, it's too late to deliver an animation. So the morphdom hooks are not an ideal place. Animations should happen before the element is manipulated in the DOM.

@nichoth
Copy link
Contributor Author

nichoth commented May 1, 2016

Yes the morphdom hooks are not ideal.

@SilentCicero You are using the hooks in throw-down to do fade in/out within the update process?

@shama
Copy link
Collaborator

shama commented May 1, 2016

btw I just released animate-styles which publishes all the animate.css animations as CSS modules.

@SilentCicero
Copy link

@shama my one issue with built-in css styles is that they are really hard to export due to the way they are staged throughout the app. I understand that they can all just get added as styles in the page. But I find that a little messy. Dont we want a nice single css file. Doesn't that slow the DOM down to have a million style injects? In any case, I haven't fully vetted this worry.

See this: rtsao/csjs#30

But great package, more for the ecosystem !

@nichoth yes, so I'll use some throw-down hooks to stage the fading. But I think I actually just built my fade so that when the fade loads it's either fading in, or fading out. That's it. So it either has the fade-in class from bootstrap or the fade-out class.

Checkout the collapse I built for using life cycle hooks: https://github.com/SilentCicero/yoyo-bootstrap/blob/master/collapse.js

That one is more complicated, because you need to wait for the element to be mounted in the DOM before you can figure out whether it is collapsing or not.

@shama
Copy link
Collaborator

shama commented May 2, 2016

@SilentCicero For production builds, you would use a global browserify plugin that extracts all the CSS into a single file. Injecting a style tag is only for development of individual modules.

@SilentCicero
Copy link

@shama right, but it is harder than it looks. All modules have to be placed into files like csjs.js files, and all require statements will not work in the csjs.js files due to build staging.

I had this problem before. It seems hard to solve. rtsao/csjs#29

Maybe browserify could do it, but webpack could not. Unless you have other ideas on that?

@nichoth
Copy link
Contributor Author

nichoth commented May 3, 2016

Thanks everyone. I am filtering a list based on URL parameters. How we handle animation depends on application structure, and I haven't had time to try things yet. Something like an asynchronous lifecycle hook seems appropriate, like a wrapper around yo.update.

@SilentCicero Maybe throwdown is this, but I haven't had the time/brainpower to fully understand it :). Maybe a signature with an options object + defaults would make it easier to consume, like

connect({
  render: renderFn,
  unload: unloadFn
  // defaults for others
});

@SilentCicero
Copy link

SilentCicero commented May 4, 2016

@nichoth so for that I would just create a custom connect module, like so:

// connect.js
var components = require("throw-down/components"), observer = require("throw-down")

function connect (props) { 
  props = props || {}
  var id = "a" + parseInt(Math.random() * 10000000), f = function(){}
  props.construct && props.construct(id); props.el = props.render()
  props.el.dataset.tdid = id
  components[id] = {
    node: props.el, added: (props.mounted || f), mutated: (props.changed || f), removed: (props.unmounted || f)
  }
  return el
}

in use:

const connect = require("./connect")

connect({
  render: renderFn,
  construct: constructFn,
  mounted: mountFn,
  changed: changedFn,
  unmounted: unloadFn
});

I didn't do it this way because just using the connect module with null values was fine with me. The original:

const connect = require("throw-down/connect")

connect(renderFn, constructFn, mountedFn, changedFn, unmountedFn);

// dont want certain functions?

connect(renderFn, null, mountedFn)

// or

connect(renderFn, null, null, changedFn, unmountedFn)

I dont know, it's all the same to me. Adding a signature object just takes more time to type. I'm lazy.. so I did it the other way (with a little opinionated argumentation) =D

@shama what do you think of the above design ^ ? Should I got with an object/signature style or just leave the slightly opinionated argument list.

Also, for more designs see react-connect.js > https://github.com/SilentCicero/throw-down/blob/master/react-connect.js

@yoshuawuyts
Copy link
Collaborator

Hmm, yeah I think @shama's approach makes sense for most cases - just set and unset classes. Perhaps using something like classnames might make things a bit nicer.

I've done a bit of browsing, and for extremely complicated animations it might make sense to use finite state machines such as f1 or (my def. less robust creation) fsm-event.

@yoshuawuyts
Copy link
Collaborator

I reckon this issue will probably be resolved by #8, providing reliable hooks to attach animation handlers onto ✨

@jamesplease
Copy link

Element lifecycle hooks should be helpful for animating things in, but not so useful for animating out. The underlying algorithm that transforms the HTML (morphdom) won't respect a user trying to delay the removal of the node in a lifecycle hook, so @shama's suggestion to treat removing animated nodes differently will still be the best approach, I think.

React's TransitionGroup (inspired by Angular's ngAnimate lib) allows users to write the same code for animated and non-animated components. Tbqh I'm not sure how it does it (maybe using some private internal component props?), but I'm a fan of not needing to write special code to animate out components.

Their system isn't perfect, though. The TransitionGroup component can't be added/removed from the DOM at the same time as the thing being animated, which is limiting in certain edge situations.

@tbranyen's diffHTML provides animation hooks into the differ directly, which is even more powerful than React's implementation, and doesn't have any edge cases I can think of.

The analogous fix here would belong in morphdom, and the groundwork has been laid for that to be implemented if anyone cared to finish it (I prob. won't have time – but figured I'd chime in :P )

@thomhos
Copy link

thomhos commented Sep 21, 2016

Hello.

A quick question regarding animating views in / out. When defining an in animation on an element, and switching class on the out action, the animation should play nicely. However when the first element is a div and the next one coming in as well this doesn't work because the dom doesnt change i believe. This is happening in the case of switching views in Choo. How can I make sure to animate the old and new view even when the dom doesnt seem to change?

Thanks.

@kristoferjoseph
Copy link
Contributor

@thomhos, have you tried putting unique IDs on the elements you are trying to animate?

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

No branches or pull requests

7 participants