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

A "native" driver for web, using CSS transitions #66

Open
ndbroadbent opened this issue May 8, 2017 · 8 comments
Open

A "native" driver for web, using CSS transitions #66

ndbroadbent opened this issue May 8, 2017 · 8 comments

Comments

@ndbroadbent
Copy link

x-post from necolas/react-native-web#470

Hi there,

I just wanted to throw out an idea that I've been successfully implementing in my own app. The app was barely usable on the web, because I use a lot of animations (it's a game). Many of them seem to perform very badly when run purely from JavaScript. So what I've started to do is add a lot of Platform specific code to my animation calls. I add a CSS transition and duration with setNativeProps, then I set the animation duration to 0, and run it. I also inject an Animated.delay into the sequence, which just waits for the CSS transition to finish.

This pattern has worked really well for me so far, so I would like to talk about bringing this into the Animated library (or perhaps react-native-web). It would be a new implementation that you could enable by setting useNativeDriver. iOS and Android already have their own native animation drivers, so I think it makes a lot of sense to build a native driver for web using CSS transitions.
@necolas also mentioned the Web Animations API, but I don't know if that will be usable any time soon, since it's not very supported. (No support at all on IE or Safari, and only in nightly / developer builds for Firefox.)

My idea would be to wrap animations with something like this:

// Returns an object that conforms to the Animated.Animated API
// (with start and stop functions)
const wrapAnimatedTimingWithCSSTransition = (animatedValue, { toValue, duration }) => {
  // Sets the value immediately, but also waits for the given duration
  const animation = Animated.sequence([
    Animated.timing(animatedValue, { toValue, duration: 0 }),
    Animated.delay(duration),
  ])

  return {
    start: (callback) => { 
      // Not sure how this would be done
      setTransitionPropertiesForAnimatedValue(animatedValue)

      animation.start(() => {
        resetTransitionPropertiesForAnimatedValue(animatedValue)
        if (callback) callback
      })
    },

    stop: () => { 
      animation.stop() 
    },
  }
}

There's a lot of things I'm not sure how to do, but that's the general idea.

One major caveat: you can't set separate transition durations for multiple transform properties. e.g. rotation and scale can't be controlled independently. In practice, this hasn't been an issue for me. I think a sane default would be to just choose the minimum duration, if multiple are provided. Or if all of the animations are started at the same time, then we could use the longest duration with keyframes.

@necolas
Copy link

necolas commented May 8, 2017

since it's not very supported

Support in Chrome means you can still reach 40-80% of users (depending on your app's geographic distribution) and vastly improve the experience on most Android phones (where hogging the main thread ruins performance).

@ndbroadbent
Copy link
Author

That is a very good point. But still, I wouldn't want to put all my energy into this implementation, and still end up with an app that performs really badly on other browsers. I do want to rip out all of my web-specific animation stuff before launching, because it's getting out of hand and bugs are becoming pretty hard to track down. So I think I might start with a proof-of-concept for the CSS transitions. And if the performance is good enough after that, I'm not sure if it would be worth also doing the Web Animations API.

@drcmda
Copy link
Contributor

drcmda commented Apr 5, 2018

@ndbroadbent do you have a test implementation or rough sketches for this? And would you be interested in working together on this? I have a fork of animated that i've been working on: https://github.com/drcmda/react-spring since animated itself doesn't look like it's very active any longer. A native driver would be fantastic, even if it only reaches 40%-80%.

@necolas
Copy link

necolas commented Apr 5, 2018

Animated is developed within React Native and periodically updated here. You could build react spring on top of React Native which would avoid RN(W) users from downloading a second copy of Animated.

I'm interested in a native web driver but no one has contributed one yet :)

@drcmda
Copy link
Contributor

drcmda commented Apr 5, 2018

Made some bigger changes as i removed the imperative api as well inflexible primitives. I figured these changes wouldn't be accepted upstream. If i find the free time, i'll probably give web animations as a native driver a shot. Would add a PR here if it comes to be.

@browniefed
Copy link
Member

As stated in a few other threads Animated in it's current fashion isn't the best suited for the web. However if it tied into priority queue of latest React it may become a potential viable candidate.

There I don't think there is a ton of interest from many about pushing Animated on the web in it's current form, as @drcmda had mentioned he forked it and has been improving the API surfaced area.

So I'd recommend giving either this, or React Native version a fork and building from there. This version has a few additions to make it actually work on the web but I believe necolas has also done a lot of that for RNW

@necolas
Copy link

necolas commented Apr 5, 2018

Oops when I said "here" I meant in RNW. If you want to hack on a native driver for web I think forking RNW is a good way to get started, as the Animated implementation is identical to that in RN

@drcmda
Copy link
Contributor

drcmda commented Apr 5, 2018

Looking at some of the web animation api primitives, would it even be feasible at all? It looks like these are all duration based easings. How'd animated be able at all to natively render a spring for instance?

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

4 participants