A "native" driver for web, using CSS transitions
See original GitHub issuex-post from https://github.com/necolas/react-native-web/issues/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.
Issue Analytics
- State:
- Created 6 years ago
- Comments:8 (4 by maintainers)
Top GitHub Comments
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).
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?