如何使用 svg 或 css 建立混合直線(xiàn)/曲線(xiàn)截面邊界?
P粉920835423
2023-09-02 11:35:13
<p>對(duì)於我的應(yīng)用程序,我正在創(chuàng)建一個(gè)具有非標(biāo)準(zhǔn)部分邊界的註冊(cè)頁(yè)面。您可以在這裡看到我試圖實(shí)現(xiàn)的效果:
這不是一個(gè)簡(jiǎn)單的圓弧——它有兩條直線(xiàn),中間還有一個(gè)圓弧。 </p>
<p>據(jù)我所知,實(shí)現(xiàn)此類(lèi)目標(biāo)的最佳方法是使用 SVG。問(wèn)題是,白色區(qū)域?qū)⒂幸粋€(gè)影像覆蓋整個(gè)區(qū)域。出於演示目的,我將使用淺藍(lán)色。如果您使用帶有 <code>background-image</code> 屬性的標(biāo)準(zhǔn) <code>div</code>,則 SVG 的白色不透明,因此您會(huì)得到以下結(jié)果:
</p>
<p>提示稍後閱讀<code>shape-outside</code> 和<code>clip-path</code> 屬性,這是我嘗試過(guò)的最新方法(注意我正在使用與樣式組件反應(yīng)):</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>我能夠使左側(cè)容器填充額外空間的唯一方法是使右側(cè)容器<code>位置:絕對(duì)</code>,但這會(huì)導(dǎo)致我計(jì)劃的登錄表單出現(xiàn)問(wèn)題添加到右側(cè)(它似乎沒(méi)有解決切斷svg 底部三分之一的問(wèn)題)。</p>
<p>有沒(méi)有辦法讓右側(cè)容器保持在頁(yè)面流中,顯示 100% 的 svg,並確保左側(cè)容器與右側(cè)容器齊平? </p>
<p>編輯:
這是 SVG 程式碼:</p>
<pre class="brush:php;toolbar:false;"><svg width="708" height="1056"svg width="708" height="1056" viewBox="0 0 708 1056" ;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.710896850989&t 4042 7.71089&Ft. 79A"/>
</clipPath>
</svg></pre>
<p>這是到目前為止的 React 元件(如您所見(jiàn),構(gòu)建的早期階段):</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:
我已嘗試實(shí)施以下答案中的解決方案,但到目前為止,每個(gè)解決方案都至少存在一個(gè)問(wèn)題。從 ccprog 的建議開(kāi)始,我有點(diǎn)不確定,因?yàn)槌淌酱a似乎與方法的描述不匹配,但我嘗試實(shí)現(xiàn)它並得到了這個(gè)結(jié)果:(首先是程式碼,然後是結(jié)果圖像)</ 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.721.768 -5.09917 662.442 7.721089.71003000300030003000303030303030303000203; 16979A"/></svg>' );
background-size: 100% 100%;
`</pre>
<p>正如您所看到的,這實(shí)際上並沒(méi)有填充螢?zāi)坏恼麄€(gè)高度,即使在右側(cè)也是如此,並且左側(cè)圖像確實(shí)被切斷了(左側(cè)圖像是所有解決方案中的一個(gè)問(wèn)題,因?yàn)槟銜?huì)看到的)。 </p>
<p>接下來(lái),我嘗試實(shí)施 Chrwahl 的第二個(gè)解決方案。這個(gè)有點(diǎn)接近(右側(cè)看起來(lái)很棒),但左側(cè)圖像有一些問(wèn)題:</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>我不確定它是否出現(xiàn)在該圖像中,但螢?zāi)坏恼麄€(gè)左側(cè)都是空白的,因此即使位置指定為左側(cè),圖像似乎也不是從左邊緣開(kāi)始。 <code>background-size: 40%, 70%</code> 的問(wèn)題更嚴(yán)重:
</p>
首先介紹一些術(shù)語(yǔ):我們將 SVG 形狀頂部和底部覆蓋的區(qū)域的寬度稱(chēng)為“右側(cè)最小值”,將中間覆蓋的寬度稱(chēng)為“右側(cè)最大值”。
我理解你的問(wèn)題的方式是,右側(cè)區(qū)域 a) 具有恆定的寬度,b) 應(yīng)始終顯示完整的 SVG 形狀。由此可見(jiàn),它必須具有恆定的高度和 708 : 1056 的縱橫比。這樣可以輕鬆計(jì)算所需的尺寸,最重要的是右邊最小值與右邊最小值之間的比率右最大值為 564 : 708。
現(xiàn)在,我建議透過(guò)將左側(cè)圖像作為背景圖像移動(dòng)到外部容器元素來(lái)解決您的問(wèn)題,其寬度確保它位於彎曲部分下方,即。 e. 100% 減 564px(或固定分?jǐn)?shù))。包含促銷(xiāo)內(nèi)容的左側(cè)容器元素的寬度為 100% 減去 708px,右側(cè)容器的寬度為 708px(或固定分?jǐn)?shù))。 (為簡(jiǎn)單起見(jiàn),容器透過(guò)與其元件名稱(chēng)相符的類(lèi)別名稱(chēng)來(lái)識(shí)別)
.container {
display: flex;
flex-direction: row;
justify-items: stretch;
align-items: stretch;
height: 523px;
background-image: linear-gradient(360deg, white, red);
background-position: top right 282px;
background-size: cover;
background-repeat: no-repeat;
}
.container-left {
flex-grow: 1;
}
.container-right {
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%;
}
.child {
box-sizing: border-box;
height: 100%;
margin: 2px;
border: 2px solid blue;
}
<div class="container">
<div class="container-left">
<div class="child"></div>
</div>
<div class="container-right">
<div class="child"></div>
</div>
</div>
您可以使用其他 px 大小值,只要保持它們之間的比例即可。
如果您不想想要顯示完整的SVG,而只想確保左側(cè)的曲線(xiàn)保持完全可見(jiàn),請(qǐng)將以下屬性新增至根
preserveAspectRatio="xMinYMid slice"
當(dāng)改變右側(cè)容器的縱橫比時(shí),這將具有與 CSS cover
相同的效果,而且 viewBox
的區(qū)域始終與左邊。只有當(dāng)縱橫比相對(duì)於寬度移動(dòng)到更高的高度時(shí),這才有效。如果縱橫比寬度增加,曲線(xiàn)的相同部分將在頂部和底部被切除 - 但另一種選擇是它的寬度不足以覆蓋右側(cè)。
如果你走這條路,請(qǐng)記住,如果你提前設(shè)定了固定的高度,你只能知道最大和最小右側(cè)之間區(qū)域的寬度。 CSS 無(wú)法使用元素的高度來(lái)計(jì)算寬度值。
點(diǎn)贊 +0
P粉920835423