react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

setting SVG fill color via useAnimatedProps fails with "Too few elements in array"

Open schiller-manuel opened this issue 4 years ago • 5 comments

Description

I try to set the fill color of an SVG element via useAnimatedProps. The color's string value seems to be interpreted as an array instead of a plain string and I get the error message ""Too few elements in array...".

If the color is set directly via the fill property (without using useAnimatedProps) the behavior is as expected.

When I use rgba(137, 41, 233, 1) instead of #8929E9, the error does not occur.

Expected behavior

Color value is set correctly.

Actual behavior & steps to reproduce

Click on "change color" button in the below example, then the following error is thrown:

Simulator Screen Shot - iPhone 12 - 2021-11-08 at 00 46 07

Snack or minimal code example

import React from 'react';
import {Button, View} from 'react-native';

import Animated, {
  useAnimatedProps,
  useSharedValue,
} from 'react-native-reanimated';
import Svg, {Rect} from 'react-native-svg';

const AnimatedRect = Animated.createAnimatedComponent(Rect);

function App() {
  const currentNumberIndex = useSharedValue(1);

  const animatedProps = useAnimatedProps(() => ({
    fill: currentNumberIndex.value === 0 ? '#8929E9' : '#C4C4C4',
  }));

  return (
    <View style={{flex: 1}}>
      <Svg width={200} height={200}>
        <AnimatedRect
          x={100}
          y={100}
          width={100}
          height={10}
          animatedProps={animatedProps}
        />
      </Svg>
      <Button
        title="change color"
        onPress={() => (currentNumberIndex.value = 0)}
      />
    </View>
  );
}

Package versions

  • React Native: 0.64.1
  • React Native Reanimated: 2.3.0-beta.3
  • react-native-svg: 12.2.0

Affected platforms

  • [x] iOS

schiller-manuel avatar Nov 07 '21 23:11 schiller-manuel

Issue validator

The issue is valid!

github-actions[bot] avatar Nov 07 '21 23:11 github-actions[bot]

Use interpolateColor Like: interpolateColor(currentNumberIndex.value, [0, 1], ['#8929E9', '#C4C4C4'])

bharatgupta99 avatar Dec 08 '21 07:12 bharatgupta99

@schiller-manuel Can you please check if interpolateColor works for you on Reanimated 2.3.1?

tomekzaw avatar Jan 28 '22 11:01 tomekzaw

@schiller-manuel Can you please check if interpolateColor works for you on Reanimated 2.3.1?

Hi @tomekzaw,

I tried interpolateColor, it did not work:

const animatedProps = useAnimatedProps(() => {
    const fill = interpolateColor(
      currentNumberIndex.value,
      [0, 1],
      ['#8929E9', '#C4C4C4'],
    );
    return {
      fill,
    };
  });

resulted in:

Attempted to assign to readonly property.

_f@/Users/app/node_modules/react-native-reanimated/src/reanimated2/Colors.ts (693:32):1:816
@[native code]
_f@/Users/app/node_modules/react-native-reanimated/src/reanimated2/Colors.ts (772:32):1:376
@[native code]
_f@/Users/app/src/BugReports.tsx (17:4):1:103
@[native code]
_f@/Users/app/node_modules/react-native-reanimated/src/reanimated2/hook/useAnimatedStyle.ts (473:18):1:83
@[native code]
styleUpdater@/Users/app/node_modules/react-native-reanimated/src/reanimated2/hook/useAnimatedStyle.ts (183:0):1:376
@[native code]
_f@/Users/app/node_modules/react-native-reanimated/src/reanimated2/hook/useAnimatedStyle.ts (498:12):1:141
@[native code]

reanimated::REAIOSErrorHandler::raiseSpec()
    REAIOSErrorHandler.mm:18
reanimated::ErrorHandler::raise()::'lambda'()::operator()()
decltype(std::__1::forward<reanimated::ErrorHandler::raise()::'lambda'()&>(fp)()) std::__1::__invoke<reanimated::ErrorHandler::raise()::'lambda'()&>(reanimated::ErrorHandler::raise()::'lambda'()&)
void std::__1::__invoke_void_return_wrapper<void, true>::__call<reanimated::ErrorHandler::raise()::'lambda'()&>(reanimated::ErrorHandler::raise()::'lambda'()&)
std::__1::__function::__alloc_func<reanimated::ErrorHandler::raise()::'lambda'(), std::__1::allocator<reanimated::ErrorHandler::raise()::'lambda'()>, void ()>::operator()()
std::__1::__function::__func<reanimated::ErrorHandler::raise()::'lambda'(), std::__1::allocator<reanimated::ErrorHandler::raise()::'lambda'()>, void ()>::operator()()
std::__1::__function::__value_func<void ()>::operator()() const
std::__1::function<void ()>::operator()() const
reanimated::REAIOSScheduler::scheduleOnUI(std::__1::function<void ()>)
reanimated::ErrorHandler::raise()
reanimated::NativeReanimatedModule::onRender(double)
reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1::operator()(double) const
decltype(std::__1::forward<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1&>(fp)(std::__1::forward<double>(fp0))) std::__1::__invoke<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1&, double>(reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1&, double&&)
void std::__1::__invoke_void_return_wrapper<void, true>::__call<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1&, double>(reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1&, double&&)
std::__1::__function::__alloc_func<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1, std::__1::allocator<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1>, void (double)>::operator()(double&&)
std::__1::__function::__func<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1, std::__1::allocator<reanimated::NativeReanimatedModule::NativeReanimatedModule(std::__1::shared_ptr<facebook::react::CallInvoker>, std::__1::shared_ptr<reanimated::Scheduler>, std::__1::shared_ptr<facebook::jsi::Runtime>, std::__1::shared_ptr<reanimated::ErrorHandler>, std::__1::function<facebook::jsi::Value (facebook::jsi::Runtime&, int, facebook::jsi::String const&)>, std::__1::shared_ptr<reanimated::LayoutAnimationsProxy>, reanimated::PlatformDepMethodsHolder)::$_1>, void (double)>::operator()(double&&)
std::__1::__function::__value_func<void (double)>::operator()(double&&) const
std::__1::function<void (double)>::operator()(double) const
invocation function for block in reanimated::createReanimatedModule(RCTBridge*, std::__1::shared_ptr<facebook::react::CallInvoker>)::$_2::operator()(std::__1::function<void (double)>, facebook::jsi::Runtime&) const
-[REANodesManager onAnimationFrame:]
CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long)
display_timer_callback(__CFMachPort*, void*, long, void*)
__CFMachPortPerform
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
__CFRunLoopDoSource1
__CFRunLoopRun
CFRunLoopRunSpecific
GSEventRunModal
-[UIApplication _run]
UIApplicationMain
main
start_sim
0x0

However, even if it did work: Why would I have to use interpolate colors if I just want to switch between to color values?

schiller-manuel avatar Jan 28 '22 18:01 schiller-manuel

The fill colour is not animated in my case and sticks to the first colour before transitioning.

lindan4 avatar Aug 05 '22 14:08 lindan4

Hi @schiller-manuel! The problem is that your rectangle expects RGBA instead of #RRGGBB for its fill colour. You don't have to convert your colors manually, you can use our function processColor.

Latropos avatar Aug 24 '23 10:08 Latropos