我正在尝试将react-native-svg
元素放在View
内,以便以一定的固定宽高比渲染,但随后缩放到尽可能大的范围内包含视图的范围。
Svg
元素(来自react-native-svg
)似乎只接受绝对width
和height
属性(我尝试使用百分比,但没有任何渲染,并且调试确认在到达本机视图时百分比值为NSNull
。我不确定如何达到预期的效果。这是我到目前为止所尝试的内容:
// I have a component defined like this:
export default class MySvgCircle extends React.Component {
render() {
return (
<View style={[this.props.style, {alignItems: 'center', justifyContent: 'center'}]} ref="containingView">
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center', aspectRatio: 1.0}}>
<Svg.Svg width="100" height="100">
<Svg.Circle cx="50" cy="50" r="40" stroke="blue" strokeWidth="1.0" fill="transparent" />
<Svg.Circle cx="50" cy="50" r="37" stroke="red" strokeWidth="6.0" fill="transparent" />
</Svg.Svg>
</View>
</View>
);
}
}
// And then consumed like this:
<MySvgCircle style={{height: 200, width: 200, backgroundColor: "powderblue"}}/>
这就是我在渲染时所看到的。
我希望将红色和蓝色圆圈按比例放大以填充200x200区域(如果包含视图是矩形而不是正方形则保持圆形),而无需预先知道组件的消费者/用户所需的大小。
如上所述,我尝试使用百分比,如下所示(其余部分相同):
<Svg.Svg width="100%" height="100%">
但是SVG部分根本没有画画。像这样:
在控制台日志中没有错误消息或其他无效的指示。
在RN中布局后测量UI元素的方法似乎是异步的,这似乎与我尝试做的事情很不匹配。我可以使用某种缩放或转换魔法吗?
所需的输出看起来像这样(通过硬编码值获得):
如果包含的视图不是一个完美的正方形,我希望它能像这样工作:
答案 0 :(得分:3)
这里是一个行为类似于图像的组件:
import React from 'react';
import { View } from 'react-native';
import Svg, { Circle } from 'react-native-svg';
const WrappedSvg = () =>
(
<View style={{ aspectRatio: 1, backgroundColor: 'blue' }}>
<Svg height="100%" width="100%" viewBox="0 0 100 100">
<Circle r="50" cx="50" cy="50" fill="red" />
</Svg>
</View>
);
在上下文中:
const WrappedSvgTest = () => (
<View>
<View style={{
width: '100%',
height: 140,
alignItems: 'center',
backgroundColor: '#eeeeee'
}}
>
<WrappedSvg />
</View>
{/* spacer */}
<View style={{ height: 100 }} />
<View style={{
width: 120,
height: 280,
justifyContent: 'space-around',
backgroundColor: '#eeeeee'
}}
>
<WrappedSvg />
</View>
</View>
);
诀窍是将SVG元素包装在保留其宽高比的视图中,然后将SVG大小设置为100%的宽度和高度。
我相信SVG元素大小和视图框大小之间存在一些复杂的相互作用,这使得SVG渲染比您期望的要小,或者在某些情况下根本无法渲染。您可以通过将<View>
标签保持固定的长宽比并将<Svg>
标签设置为100%的宽度和高度来避免这种情况,因此视图框的长宽比始终与元素比例匹配。
请确保将aspectRatio
设置为viewbox.width / viewbox.height
。
答案 1 :(得分:2)
您必须与viewBox一起使用宽度和高度。通常,viewBox必须放置所需形状的原始尺寸。通过根据您的需要定义宽度/高度,您的形状将向下/向上缩放。
请仔细阅读本教程,其中已经非常清楚地解释了这些概念。
答案 2 :(得分:1)
preserveAspectRatio="xMinYMin slice"
您应该这样做
<Svg
height="100%"
preserveAspectRatio="xMinYMin slice"
width="100%"
viewBox="0 0 100 100"
>
答案 3 :(得分:1)
对于我的SVG,我使用的是https://material.io/resources/icons
对我来说,解决此问题的方法是确保您不会像我一样迷惑viewBox
或Paths
中的给定值,而只更改height
和width
进行填充,然后像其他答案一样使用容器:
<View style={{
height: 100, display: 'flex',
}}>
<TouchableOpacity style={{
display: 'flex', justifyContent: 'center',
alignItems: 'center', aspectRatio: 1,
}}>
<Svg fill="white" height="100%"
width="100%" viewBox="0 0 24 24">
<Path d="M0 0h24v24H0z" fill="none"/>
<Path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
</Svg>
</TouchableOpacity>
</View>