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

useAnimatedStyle does not support hsl(x y% z%) syntax for colors #5746

Closed
tomekzaw opened this issue Feb 28, 2024 · 2 comments · Fixed by #5825
Closed

useAnimatedStyle does not support hsl(x y% z%) syntax for colors #5746

tomekzaw opened this issue Feb 28, 2024 · 2 comments · Fixed by #5825
Labels
Maintainer issue Issue created by a maintainer

Comments

@tomekzaw
Copy link
Member

Description

When using hsl(x y% z%) syntax for background color in animated style, the color is not updated.

Steps to reproduce

import { StyleSheet, View } from 'react-native';

import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withRepeat,
  withTiming,
} from 'react-native-reanimated';
import React, { useEffect } from 'react';

export default function EmptyExample() {
  const sv = useSharedValue(0);

  useEffect(() => {
    sv.value = withRepeat(withTiming(1, { duration: 1000 }), -1, true);
    return () => {
      sv.value = 0;
    };
  }, [sv]);

  const animatedStyle = useAnimatedStyle(() => {
    return {
      backgroundColor: `hsl(${sv.value * 180} 100% 50%)`,
    };
  });

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.box, animatedStyle]} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  box: {
    width: 100,
    height: 100,
  },
});

Snack or a link to a repository

nope

Reanimated version

3.7.1

React Native version

0.73.4

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

Debug app & dev bundle

Device

iOS simulator

Device model

iPhone 15 Pro

Acknowledgements

Yes

@github-actions github-actions bot added Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Missing repro This issue need minimum repro scenario labels Feb 28, 2024
Copy link

Hey! 👋

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

@tomekzaw
Copy link
Member Author

Workaround

Add commas (,) between HSL components.

   const animatedStyle = useAnimatedStyle(() => {
     return {
-      backgroundColor: `hsl(${sv.value * 180} 100% 50%)`,
+      backgroundColor: `hsl(${sv.value * 180}, 100%, 50%)`,
     };
   });
``

@tomekzaw tomekzaw added Maintainer issue Issue created by a maintainer and removed Missing repro This issue need minimum repro scenario Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS labels Feb 28, 2024
github-merge-queue bot pushed a commit that referenced this issue May 15, 2024
## Summary

Fixes #5746. Not all color formats and syntax supported by RN is
supported by reanimated. This PR should align with RN implementation. An
example for rgb,rgba,hsl,hsl with comma and without (for view and
Animated.View):

|Before|After|
|-|-|
| <video
src="https://github.com/software-mansion/react-native-reanimated/assets/11800297/fe6f9b1d-a4e3-4542-baae-9d499aa6f252"
/>|<video
src="https://github.com/software-mansion/react-native-reanimated/assets/11800297/1c33d1d3-6e0b-483a-a88d-7c8eb467b859"
/>|

## Test plan

Reused [RN
tests](https://github.com/facebook/react-native/blob/main/packages/normalize-color/__tests__/normalizeColor-test.js).

<details>
<summary>Example from the video</summary>

```jsx
import { StyleSheet, View, Text } from 'react-native';

import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withRepeat,
  withTiming,
} from 'react-native-reanimated';
import React, { useEffect } from 'react';

const CompareColumnAnimated = ({
  title,
  withComma,
}: {
  title: string;
  withComma?: boolean;
}) => {
  const sv = useSharedValue(0);

  const toRgb = (value: number) => {
    'worklet';
    return Math.floor(Math.abs(value) * 255);
  };

  useEffect(() => {
    sv.value = withRepeat(withTiming(1, { duration: 1000 }), -1, true);
    return () => {
      sv.value = 0;
    };
  }, [sv]);

  return (
    <View style={{}}>
      <View style={styles.header}>
        <Text>{title}</Text>
      </View>
      <Animated.View
        style={[
          styles.box,
          useAnimatedStyle(() => ({
            backgroundColor: `rgb(${toRgb(sv.value)} 255 255)`
              .split(' ')
              .join(withComma ? ', ' : ' '),
          })),
        ]}
      />
      <Animated.View
        style={[
          styles.box,
          useAnimatedStyle(() => ({
            backgroundColor: `rgba(${toRgb(sv.value)} 255 255 0.5)`
              .split(' ')
              .join(withComma ? ', ' : ' '),
          })),
        ]}
      />
      <Animated.View
        style={[
          styles.box,
          useAnimatedStyle(() => ({
            backgroundColor: `hsl(${sv.value * 180} 100% 50%)`
              .split(' ')
              .join(withComma ? ', ' : ' '),
          })),
        ]}
      />
      <Animated.View
        style={[
          styles.box,
          useAnimatedStyle(() => ({
            backgroundColor: `hsla(${sv.value * 180} 100% 50% 0.5)`
              .split(' ')
              .join(withComma ? ', ' : ' '),
          })),
        ]}
      />
    </View>
  );
};

const CompareColumn = ({
  title,
  withComma,
}: {
  title: string;
  withComma?: boolean;
}) => (
  <View style={{}}>
    <View style={styles.header}>
      <Text>{title}</Text>
    </View>
    <View
      style={[
        styles.box,
        {
          backgroundColor: 'rgb(100 255 255)'
            .split(' ')
            .join(withComma ? ', ' : ' '),
        },
      ]}
    />
    <View
      style={[
        styles.box,
        {
          backgroundColor: 'rgba(100 255 255 0.5)'
            .split(' ')
            .join(withComma ? ', ' : ' '),
        },
      ]}
    />
    <View
      style={[
        styles.box,
        {
          backgroundColor: 'hsl(100 100% 50%)'
            .split(' ')
            .join(withComma ? ', ' : ' '),
        },
      ]}
    />
    <View
      style={[
        styles.box,
        {
          backgroundColor: 'hsla(100 100% 50% 0.5)'
            .split(' ')
            .join(withComma ? ', ' : ' '),
        },
      ]}
    />
  </View>
);

export default function EmptyExample() {
  return (
    <View style={styles.container}>
      <CompareColumnAnimated title="anim comma" withComma />
      <CompareColumn title="view comma" withComma />
      <CompareColumnAnimated title="anim no comma" />
      <CompareColumn title="view no comma" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
  },
  box: {
    width: 100,
    height: 100,
  },
  header: { justifyContent: 'center', alignSelf: 'center' },
});

```

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Maintainer issue Issue created by a maintainer
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant