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

Remove unnecessary color processing in interpolateColor #6213

Merged
merged 2 commits into from
Jul 5, 2024

Conversation

szydlovsky
Copy link
Contributor

Summary

Our interpolateColor function seems to have some unnecessary color processing in it. It was added some 3-4 years ago and should not be needed by now.

Why

There is a function called rgbaColor which is used in hsvToColor (which in turn is used only in interpolateColor) as well as directly in interpolateColor. So it's safe to say it is used only there. All it does is take r,g,b,a values, runs a small check on them and then returns a rgba string.
It has a check whether we are on UI thread or not. If we were on UI, it returned a number-formatted color (formatted for native platforms) instead of the usual rgba string. The problem is, these values are then directly returned from the function. I believe it was needed back then, but now we have a function called processColorInProps which does exactly that + it doesn't interfere with returned values of interpolateColor. Taking all these things into consideration, I believe this check in rgbaColor function is not needed anymore.

Moreover, it creates problems. When interpolateColor gets called on UI thread (for example by using it inside useDerivedValue hook as shown by this issue: #6119), the user gets these number-formatted colors which don't work when passed anywhere.

Test plan

Copy App.tsx from snack linked to the mentioned issue and make sure the text stays blue. Also, check out Color Interpolation example from the example app.

Tested on iOS and Android (both Paper and Fabric) as well as Web. I've noticed neither issues nor regressions.

Copy link
Member

@tomekzaw tomekzaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but let's wait for @piaskowyk's approval

Copy link
Member

@piaskowyk piaskowyk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to my test and our runtimetests it works 🎉

@szydlovsky szydlovsky added this pull request to the merge queue Jul 5, 2024
Merged via the queue into main with commit 1a213c4 Jul 5, 2024
6 checks passed
@szydlovsky szydlovsky deleted the @szydlovsky/remove-interpolateColor-processing branch July 5, 2024 13:23
@jesse-one-app
Copy link

jesse-one-app commented Aug 6, 2024

this change has caused an issue in our project when using interpolateColor inside of a useAnimatedProps hook with an Animated.createAnimatedComponent using a react-native-svg path. The color changes briefly then resets back to black.

When i roll back to 3.13.0 that doesn't include this change the color works as expected.

@piaskowyk Can we revert this change or fix the issues it has with animated props?

@tomekzaw
Copy link
Member

tomekzaw commented Aug 7, 2024

It seems like this should be fixed with software-mansion/react-native-svg#2397

@bohdanprog
Copy link
Member

Hello @jesse-one-app,
I tried to reproduce your issue but couldn't. Could you please check that example? It should work.

import React from 'react';
import {Svg, Circle} from 'react-native-svg';
import Animated, {
  createAnimatedPropAdapter,
  processColor,
  useAnimatedProps,
  useSharedValue,
  withRepeat,
  withTiming,
  interpolateColor,
} from 'react-native-reanimated';

const AnimatedCircle = Animated.createAnimatedComponent(Circle);

const adapter = createAnimatedPropAdapter(
  props => {
    if (Object.keys(props).includes('fill')) {
      props.fill = {type: 0, payload: processColor(props.fill)};
    }
  },
  ['fill'],
);

export default function App() {
  const opacity = useSharedValue(0);

  React.useEffect(() => {
    opacity.value = withRepeat(withTiming(1), -1, true);
  }, []);

  const circleAnimatedProps = useAnimatedProps(
    () => {
      const coordinates = {cx: 50, cy: 50, r: 50};

      return {
        cx: coordinates.cx,
        cy: coordinates.cy,
        r: coordinates.r,
        fill: interpolateColor(opacity.value, [0, 1], ['red', 'green']),
        opacity: opacity.value,
        strokeWidth: 2,
      };
    },
    [],
    adapter,
  );

  return (
    <Svg width="100%" height="100%">
      <AnimatedCircle animatedProps={circleAnimatedProps} />
    </Svg>
  );
}

@jesse-one-app
Copy link

@bohdanprog we were not calling processColor in the createAnimatedPropAdapter function

thanks for the example and the help!

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

Successfully merging this pull request may close these issues.

5 participants