React-motion: RGB Color not Interpolated

Created on 21 Mar 2016  路  10Comments  路  Source: chenglou/react-motion

I'm trying to find a way to interpolate color, particularly fill for an SVG. I had no luck with hex codes, so I moved to a consistent rgb() value, but am finding that though the integer changes, it doesn't interpolate. What's do you recommend as best practice for animating color?

Here's a reduced test case:
http://codepen.io/sdras/pen/a25064109af93ebc8b3d17b9755583ae?editors=1010

Thanks!
Sarah

docs duplicate question

All 10 comments

@sdras The color does not interpolate because rgb() requires integer values from 0 to 255, but the spring is high-precision and generates decimals with floating point, for example 49.91165769112001 -- only the initial and the final states are integers (50 and 34), that's why the first and last colors are rendered properly.

The best practice is to make a separate spring for color, from 0 to 1, and use it as a parameter for the color interpolation.

        <Motion style={{
          fill: spring(this.state.open ? 50 : 34),
          rotate: spring(this.state.open ? 0 : 180),
          color: spring(this.state.open ? 0 : 1),
        }}>
          {({ fill, rotate, color }) => {
            const rgba = {
              r: Math.round(color * 255),
              g: Math.round(color * 255),
              b: Math.round(color * 255),
              a: 1.0,
            };
            return (
              <svg viewBox="0 0 803.9 738.1" aria-labelledby="title">
                <title>React-Motion</title>
                <polygon 
                  style={{
                      WebkitTransform: `rotate(${rotate}deg)`,
                      transform: `rotate(${rotate}deg)`,
                      fill: `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`,
                      opacity: 1.0,  // The `cls-4` puts `opacity` style, the override is for `rgba` example purposes.
                  }}
                  className="cls-4" points="406.4 16 644.8 428.9 168 428.9 406.4 16" />
              </svg>
            );
          }}
        </Motion>

For more complex color manipulation, a library such as https://www.npmjs.com/package/color might be useful.

@sdras rgb(${Math.round(fill)}, ${Math.round(fill)}, ${Math.round(fill)}) -- but it will be difficult to see the difference between 34 and 50... try cranking one up to 255 to be sure it's working.

@sompylasar thanks! that makes great sense. I'll do that.

Do you think it might be good to have color interpolation, such as hex values, added as a feature? Maybe it's something I can work on to contribute.

@sdras I don't think there is a place for color interpolation in the react-motion core. Node modules should generally go Unix-way: do one thing and do it well.

It's not so hard to interpolate a composite value such as RGB color given a single 0.0 -> 1.0 parameter, _there is even a module specifically for that_ (https://github.com/miguelmota/interpolate-rgb).

Probably, there should be some short "how-to" on interpolation of arbitrary values, including colors, in the README of react-motion, with a reference to https://en.wikipedia.org/wiki/Linear_interpolation (and to other kinds of interpolation, if needed).

@chenglou, the author, might have another opinion.

@sdras you can make an own module with react-motion dependency.

It is not hard to interpolate colors, but it is always good to have one stable implemented solution and use it when needed without re-implementation. So I think a module for color interpolation and something like awesome-react-motion page with list of all useful stuff for react-motion is the best solution.

Where can I find more info on the best way to animate colors with react-motion?

React motion does not operate "style" (I agree that is a misleading name for prop). It only applies function over any number you pass. This way it can stay minimal and you have all power to interpolate any number-related values.

<Motion defaultStyle={{whatever: 0}} style={{whatever: spring(1)}}>
  {({whatever}) => (
    <div style={{color: `rgb(${255 * whatever}, ${255 * whatever}, ${255 * whatever})`}}>
      Hey, I'm transitioning color!
    </div>
  )}
</Motion>

Use Motion as the way to manipulate number and then use that number to derive any other numeric value.

PS: sigh, I wish prop would not be called as style to avoid ~100000 opened issues similar to this one.

Added generic issue to cover this in README #494

Was this page helpful?
0 / 5 - 0 ratings