【问题标题】:How to manage dynamic fill with React Native SVG如何使用 React Native SVG 管理动态填充
【发布时间】:2022-01-20 02:41:58
【问题描述】:

我的 React 本机 .66.1 应用程序中有一些 SVG,我已经设置了 react-native-svgreact-native-svg-transformer 并且设置正确。我可以将我的 SVG 作为组件导入,一切都按预期工作。

但是,我不知道如何根据我的应用程序中的表达式动态设置填充。例如,我可以在我的 SVG 中设置渐变,但我不能在状态更改时覆盖颜色。

你如何设置它来跟踪一个值,或者如何覆盖它?

我的 SVG:

<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient gradientUnits="userSpaceOnUse" x1="12.99" y1="0" x2="12.99" y2="25.92" id="gradient" gradientTransform="matrix(0.707053, -0.707161, 1.001161, 1.001008, -9.106794, 9.237734)">
      <stop offset="0" style="stop-color: rgb(161, 70, 183);"/>
      <stop offset="1" style="stop-color: rgb(0, 38, 94);"/>
    </linearGradient>
  </defs>
  <path d="M13.91.38a1.3 1.3 0 0 0-1.84 0L.33 12.14c-.4.4-.35.73-.29.89.06.16.25.44.8.44h1.32v10.45a2 2 0 0 0 1.92 2h5.95v-7.08h5.76v7.08h6.1c1.03 0 1.9-.93 1.9-2V13.47h1.36c.54 0 .73-.28.79-.44.06-.16.1-.5-.28-.9L13.9.39Z" fill-rule="evenodd" />
</svg>

我的抽屉屏幕:

<Drawer.Screen name="Home" options={{ drawerIcon: ({color, size, focused}) => <HomeIcon style={{maxWidth: 28}} fill={focused ? colors.primary.purpleMain : darkMode ? 'white' : 'black'} />}} component={Home} />

我想要什么:

我希望图标是焦点上的渐变,并且是黑色或白色,具体取决于darkMode。有任何想法吗?我尝试在 App.tsx 中设置填充,但它不跟踪。这是我尝试过的:'url(#gradient)'(渐变是我的 svg 中的线性渐变的 id)。

我的理想情况是不必在每个 SVG 中嵌入 linearGradient,而是将其“设置”到每个实体 SVG(仅 135 度紫色渐变)。

值得注意的是,如果我只使用常规颜色并在我的 SVG 中省略 fill 属性,我的动态颜色就可以工作。另外 - 如果我在我的 SVG 中使用“currentColor”,颜色会保持蓝色,但我什至看不到任何调用蓝色的地方。

【问题讨论】:

    标签: react-native svg react-native-svg


    【解决方案1】:

    我建议您使用https://icomoon.io/ 为您的图标创建字体(即:.ttf)格式,然后分别替换来自 GradientIcon 和主页的图标,

    这里我使用 react-native-vector-icons 作为图标

    工作示例:Snack Expo


    GradientIcon.tsx

    import React, { FC } from 'react';
    import {
      View,
      StyleSheet,
      StyleProp,
      ViewStyle,
      ViewProps,
    } from 'react-native';
    import IonIcon, { IconProps } from 'react-native-vector-icons/Ionicons';
    // in bare react native use. react-native-linear-gradient
    import { LinearGradient } from 'expo-linear-gradient';
    import MaskedView, {
      MaskedViewProps,
    } from '@react-native-community/masked-view';
    
    /**
     * GradientIonIconProps
     */
    type GradientIonIconProps = IconProps & {
      colors?: string[];
      containerStyle?: StyleProp<ViewStyle>;
      start?: {
        x: number;
        y: number;
      };
      end?: {
        x: number;
        y: number;
      };
    };
    
    /**
     * GradientIonIcon
     */
    const GradientIonIcon: FC<GradientIonIconProps> = (props) => {
      const {
        children,
        containerStyle,
        start = { x: 0, y: 0 },
        end = { x: 1, y: 0 },
        colors = ['#3D7BF7', '#26CCFF'],
        ...rest
      } = props;
      return (
        <MaskedView
          style={containerStyle}
          maskElement={
            <IonIcon {...rest} style={{  color: '#fff' }} color="#fff" />
          }>
          <LinearGradient {...{ colors, start, end }}>
            <IonIcon {...rest} color="transparent" />
          </LinearGradient>
        </MaskedView>
      );
    };
    
    export default GradientIonIcon;
    
    

    创建仅在大小和焦点道具更改时更新的主页图标容器

    图标容器

    const HomeIconContainer: React.FC<{ size: number; focused: boolean }> =
      React.memo(
        ({ size, focused }) => {
          console.log(focused);
          const Icon = React.useMemo(
            () => (focused ? GradientIonIcon : IonIcon),
            [focused]
          );
    
          return (
            <Icon
              containerStyle={{ width: size, height: size }}
              size={size}
              name="ios-home"
              color="purple"
            />
          );
        },
        (prev, next) => prev.size === next.size && prev.focused === next.focused
      );
    

    然后在导航选项中使用此图标

    DraerNAvigator

    <Drawer.Screen
        name="Home"
        options={{
          drawerIcon: ({ size, focused }) => (
            <HomeIconContainer {...{ size, focused }} />
          ),
        }}
      component={Home}
    />
    

    #结果

    专注

    注意力不集中

    【讨论】:

    • 字体性能不佳,我很难让它们在 iOS 和 Android 上看起来一致。另外 - got 是一种动态设置渐变填充的方法。我知道你可以定期做出反应,而且我确定必须有一种方法可以让 svgs 与本机反应。我什至不知道要具体要求什么才能得到我需要的东西。 ://
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    相关资源
    最近更新 更多