如何使用 React Native SVG 管理动态填充
Posted
技术标签:
【中文标题】如何使用 React Native SVG 管理动态填充【英文标题】:How to manage dynamic fill with React Native SVG 【发布时间】:2022-01-20 02:41:58 【问题描述】:我的 React 本机 .66.1 应用程序中有一些 SVG,我已经设置了 react-native-svg
和 react-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”,颜色会保持蓝色,但我什至看不到任何调用蓝色的地方。
【问题讨论】:
【参考方案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 与本机反应。我什至不知道要具体要求什么才能得到我需要的东西。 ://以上是关于如何使用 React Native SVG 管理动态填充的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 React-Native 和 Reanimated 2 为 svg 设置动画道具变换
React Native - 如何使用本地 SVG 文件(并为其着色)
React Native 和 Expo - SVG 不会在 iOS 设备上呈现