如何使用react-native-svg查找宽度,高度和viewBox的正确值

问题描述 投票:0回答:1

我一直在尝试做看似简单的事情,但是我已经尝试了几个小时,但找不到解决方案。

我有一个SVG,它必须位于屏幕顶部。它来自设计师,具有以下尺寸:

<Svg width="354px" height="190px" viewBox="0 0 354 190">...</Svg>

React Native中,它将进入容器内部,并且SVG需要占据屏幕的整个宽度,这是我从以下位置获取的:

Dimensions.get("window").width

我的问题是,我还没有找到一种方法来缩放SVG以占据100%的屏幕宽度,找出正确的高度(或自动设置它的方法)并保持纵横比。我已经尝试了一百万次,包括尝试使用容器的aspectRatio样式及其height(或者根本不设置height)。每当我发现某些“比例”有效时,我就会尝试在另一台屏幕宽度不同的设备上使用,但看起来效果并不好(裁剪,小于屏幕宽度等)。

我觉得SVG(react-native-svg)中的preserveAspectRatio属性在某种程度上与aspectRatio样式冲突。而且,我对preserveAspectRatio完全迷失了,我没有找到一种方法来使它不被裁剪而缩放。

有人知道如何实现吗?

这是我的最终代码,它返回一个显示SVG的HeatMap组件,但尽管高度正确,但SVG的一部分从右侧不在屏幕上(因为它太宽,因此被裁剪了:]

const windowWidth = Dimensions.get("window").width;

const getSVGRootProps = ({ width, height }) => ({
  width: "100%",
  height: "100%",
  viewBox: `0 0 ${width} ${height}`,
  preserveAspectRatio: "xMinYMin meet",
});

const FieldShape = () => {
  const width = 354; // Original width
  const height = 190; // Original height
  const aspectRatio = width / height;
  // adjusted height = <screen width> * original height / original width
  const calculatedHeight = (windowWidth * height) / width;
  const fieldStyles = {
    width: windowWidth,
    height: calculatedHeight,
    aspectRatio,
  };

  return (
    <View style={fieldStyles}>
      <Svg {...getSVGRootProps({ windowWidth, calculatedHeight })}>
      ...
      </Svg>
    </View>
  );
};

const HeatMap = () => {
  return <FieldShape />;
};

这是结果:

Result picture (pixelation intended)

css react-native svg aspect-ratio
1个回答
0
投票

我已经找到了解决方案,我把它发布在这里,以防任何人在使用react native和SVG遇到相同的问题。基本上,如果您试图获取SVG文件并将其变成具有“动态”部分的组件(例如,通过编程将颜色设置为基于数据的路径,或显示SVG文本),则可能会遇到此问题。] >

[我所做的是使用SVGR将原始SVG转换为react native组件(使用react-native-svg)。然后,我只是根据需要用变量(来自props)替换了硬编码数据。看起来不错,但组件尺寸有问题。我找不到在不同设备尺寸和分辨率下显示它的一致方法。看起来很简单,但是我尝试了几个小时,每个屏幕尺寸的结果都不同。在这里问了一个关于react-native-svg repo的问题之后,我没有答案也没有任何线索(没有怪罪任何人,只是说这可能不是很多人遇到的事情)。因此,我进行了深入研究,终于找到了this post by Lea Verou,她在其中谈到了绝对和相对SVG路径。那让我觉得也许是我试图找到理想的调整大小公式的问题太多了,因为我的路径不是相对的,而是绝对的。因此,我尝试了此jsfiddle by heyzeuss,粘贴了我的(原始)SVG代码,然后复制了结果。我将结果粘贴到了方便的SVGR playground (SVG to JS) tool中,然后我做了一些改动以实现自己的目标:

  • 我希望我的SVG占据整个屏幕的宽度,其高度相应地缩放。
  • 所以这就是我更改的内容:

// SVG's original size is 519 width, 260 height
// <Svg width="519" height="260" viewBox="0 0 519 260">...</Svg>
// I also added a container, which enforces the aspect ratio
const originalWidth = 519;
const originalHeight = 260;
const aspectRatio = originalWidth / originalHeight;
const windowWidth = Dimensions.get("window").width;
return (
    <View style={{ width: windowWidth, aspectRatio }}>
        <Svg width="100%" height="100%" viewBox="0 0 519 260">
        ...
        </Svg>
    </View>
)

例如,我在学习过程中学到了一些东西,例如,create-react-app中包含一个@svgr/cli,并且在我的本地项目中也可以使用它,而无需安装任何额外的东西,因此它也必须与原始依赖项捆绑在一起。您可以运行此命令,它将单个文件或文件夹中的所有文件从.svg转换为React组件:

npx @svgr/cli [-d out-dir] [--ignore-existing] [src-dir]

用于将绝对路径转换为亲戚的脚本是该库的一部分,名为Snap.svg,但您只需要它的1%(Snap.path.toRelative)。我正在考虑拥有一个小型工具,该工具可以将svg文件中的所有路径都包含在内,并应用此转换。老实说,我已经处理SVG文件多年了,但是我从来没有真正了解过它的内部工作方式,路径格式,坐标等,因此这非常有启发性:)

希望您在相同的情况下能对您有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.