我创建了this codesandbox来说明这个问题。
我有这个ResponsiveSVG组件:
export function ResponsiveSVG({
height,
width,
children,
origin = { x: 0, y: 0 },
preserveAspectRatio = "xMidYMid meet",
innerRef,
className,
...props
}: ResponsiveSVGProps): JSX.Element {
const aspect = height === 0 ? 1 : width / height;
const adjustedHeight = Math.ceil(width / aspect);
return (
<div
data-testid="cutting-svg-container"
style={{
position: 'relative',
overflow: 'visible',
height: '1px',
}}
>
<svg
style={{ overflow: 'visible' }}
className={className}
preserveAspectRatio={preserveAspectRatio}
width={width}
height={adjustedHeight}
viewBox={`${origin.x} ${origin.y} ${width} ${height}`}
ref={innerRef}
{...props}
>
{children}
</svg>
</div>
);
}
我希望我的ResponsiveSVG
组件知道如何使其内容适合容器的整个宽度,同时保持纵横比不变。
在这个例子中,我有一个circle
作为svg文档的子文档:
<ResponsiveSVG width={width} height={height}>
<circle cx={width / 2} cy={height / 2} r={radius} />
</ResponsiveSVG>
在桌面上,它看起来像这样:
但在移动的视图中,它看起来是这样的:
我的计算使viewBox
的宽度和高度与传入的实际宽度和高度相同,因此没有发生任何变化。
viewBox坐标与视口完全相同。
1条答案
按热度按时间fbcarpbf1#
将包含元素的宽度和高度传递给
viewBox
实际上是错误的方向。viewBox
定义了在其上绘制svg内容元素的画布:如果你用r="50"
画一个圆,视图框宽度值必须至少为100,否则,它将无法适合。如果中心在cx=50
,视图框x值必须不大于0,否则左边将被截断。SVG中的响应性是可以实现的,因为
viewBox
值与<svg>
元素的width
和height
之间不需要有任何关系,绘制子元素的画布总是适合父元素的尺寸。简而言之,如果你想在
<svg>
元素中拟合一个圆,选择一个任意半径r
,设置cx=cy=r
和viewBox="0 0 2r 2r"
,它就会工作,不需要知道任何关于父元素大小的显式信息。如果希望
<svg>
元素为容器的宽度,请将其设置为:width: 100%
。默认高度为auto
,所以不需要写它或preserveAspectRatio
。它会调整自己的大小,使viewBox
定义的画布适合自己。