如何使用 svg 或 css 创建混合直线/曲线截面边界?
P粉920835423
2023-09-02 11:35:13
<p>对于我的应用程序,我正在创建一个具有非标准部分边界的注册页面。您可以在这里看到我试图实现的效果:
这不是一个简单的圆弧——它有两条直线,而且中间还有一个圆弧。</p>
<p>据我所知,实现此类目标的最佳方法是使用 SVG。问题是,白色区域将有一个图像覆盖整个区域。出于演示目的,我将使用浅蓝色。如果您使用带有 <code>background-image</code> 属性的标准 <code>div</code>,则 SVG 的白色不透明,因此您会得到以下结果:
</p>
<p>提示稍后阅读 <code>shape-outside</code> 和 <code>clip-path</code> 属性,这是我尝试过的最新方法(注意我正在使用与样式组件反应):</p>
<pre class="brush:php;toolbar:false;">const LeftContainer = styled(FlexContainer)`
width: 55%;
height: 100%;
background-color: lightblue;
z-index: 1;
/* background: linear-gradient(360deg, #FFFFFF 24.95%, rgba(255, 255, 255, 0) 50.95%), url(${process.env.PUBLIC_URL}/TestImage.png); */
`;
const RightContainer = styled(FlexContainer)`
width: 45%;
height: 100%;
/* background-color: ${colors.secondary600}; */
float: left;
/* background-image: url(${process.env.PUBLIC_URL}/SignUpBackground.svg); */
background-repeat: no-repeat;
background-size: cover;
background-position: center;
position: relative;
z-index: 5;
clip-path: url(${process.env.PUBLIC_URL}/SignUpBackground.svg#sidebar);
`;</pre>
<p>仍然存在间隙,但不仅如此,SVG 形状的底部三分之一被切掉了:
</p>
<p>我能够使左侧容器填充额外空间的唯一方法是使右侧容器<code>位置:绝对</code>,但这会导致我计划的登录表单出现问题添加到右侧(它似乎没有解决切断 svg 底部三分之一的问题)。</p>
<p>有没有办法让右侧容器保持在页面流中,显示 100% 的 svg,并确保左侧容器与右侧容器齐平?</p>
<p>编辑:
这是 SVG 代码:</p>
<pre class="brush:php;toolbar:false;"><svg width="708" height="1056" viewBox="0 0 708 1056" fill="none" xmlns="http://www.w3.org/2000/svg">
<clipPath id="sidebar">
<path d="M144.5 0H799.5V1056H144.5L23.4254 775.169C0.402533 721.768 -5.09917 662.442 7.71089 605.718L144.5 0Z" fill="#16979A"/>
</clipPath>
</svg></pre>
<p>这是到目前为止的 React 组件(如您所见,构建的早期阶段):</p>
<pre class="brush:php;toolbar:false;">const SignUpPage = (props) => {
return (
<Container>
<LeftContainer>
{/* Site logo and marketing copy, promo bubbles to go here. This side should be the one to shrink */}
</LeftContainer>
<RightContainer flexDirection="column" justify="center">
{/* Signup/Login form to go here */}
</RightContainer>
</Container>
);
}</pre>
<p>编辑2:
我已尝试实施以下答案中的解决方案,但到目前为止,每个解决方案都至少存在一个问题。从 ccprog 的建议开始,我有点不确定,因为代码似乎与方法的描述不匹配,但我尝试实现它并得到了这个结果:(首先是代码,然后是结果图像)</ p>
<pre class="brush:php;toolbar:false;">const Container = styled(FlexContainer)`
height: 523px;
background-image: linear-gradient(360deg, #FFFFFF 24.95%, rgba(255, 255, 255, 0) 50.95%), url(${process.env.PUBLIC_URL}/SignUpImage.jpg);
background-position: top right 282px;
background-size: cover;
background-repeat: no-repeat;
`;
const LeftContainer = styled(FlexContainer)`
flex-grow: 1;
`
const RightContainer = styled(FlexContainer)`
width: 354px;
background-image: url('data:image/svg+xml,<svg viewBox="0 0 708 1056" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M144.5 0H799.5V1056H144.5L23.4254 775.169C0.402533 721.768 -5.09917 662.442 7.71089 605.718L144.5 0Z" fill="%2316979A"/></svg>');
background-size: 100% 100%;
`</pre>
<p>正如您所看到的,这实际上并没有填充屏幕的整个高度,即使在右侧也是如此,并且左侧图像确实被切断了(左侧图像是所有解决方案中的一个问题,因为你会看到的)。</p>
<p>接下来,我尝试实施 Chrwahl 的第二个解决方案。这个有点接近(右侧看起来很棒),但左侧图像有一些问题:</p>
<pre class="brush:php;toolbar:false;">const Container = styled(FlexContainer)`
width: 100%;
height: 100vh;
background-image: url(${process.env.PUBLIC_URL}/SignUpBackground.svg),
linear-gradient(360deg, #FFFFFF 24.95%, rgba(255, 255, 255, 0) 50.95%), url(${process.env.PUBLIC_URL}/SignUpImage.jpg);
background-repeat: no-repeat;
background-position: right, left;
background-size: contain, cover;
margin-bottom: 5px;
`;</pre>
<p>我不确定它是否出现在该图像中,但屏幕的整个左侧都是空白的,因此即使位置指定为左侧,图像似乎也不是从左边缘开始。 <code>background-size: 40%, 70%</code> 的问题更严重:
</p>
首先介绍一些术语:我们将 SVG 形状顶部和底部覆盖的区域的宽度称为“右侧最小值”,将中间覆盖的宽度称为“右侧最大值”。
我理解你的问题的方式是,右侧区域 a) 具有恒定的宽度,b) 应始终显示完整的 SVG 形状。由此可见,它必须具有恒定的高度和 708 : 1056 的纵横比。这样可以轻松计算所需的尺寸,最重要的是右侧最小值与右侧最小值之间的比率右侧最大值为 564 : 708。
现在,我建议通过将左侧图像作为背景图像移动到外部容器元素来解决您的问题,其宽度确保它位于弯曲部分下方,即。 e. 100% 减去 564px(或固定分数)。包含促销内容的左侧容器元素的宽度为 100% 减去 708px,右侧容器的宽度为 708px(或固定分数)。 (为简单起见,容器通过与其组件名称匹配的类名称来标识)
您可以使用其他 px 大小值,只要保持它们之间的比例即可。
如果您不想想要显示完整的 SVG,而只想确保左侧的曲线保持完全可见,请将以下属性添加到根
当改变右侧容器的纵横比时,这将具有与 CSS
cover
相同的效果,而且viewBox
的区域始终与左边。仅当纵横比相对于宽度移动到更高的高度时,这才有效。如果纵横比宽度增加,曲线的相同部分将在顶部和底部被切除 - 但另一种选择是它的宽度不足以覆盖右侧。如果你走这条路,请记住,如果你提前设置了固定的高度,你只能知道最大和最小右侧之间区域的宽度。 CSS 无法使用元素的高度来计算宽度值。