如何使用svg或css创建混合直线/曲线截面边界?

omvjsjqw  于 2023-05-23  发布在  其他
关注(0)|答案(2)|浏览(143)

对于我的应用程序,我创建了一个非标准区域边界的注册页面。你可以看到我在这里试图达到的效果:它不是一个简单的弧--它有两条直线,但中间还有一条弧。
从我所读到的内容来看,实现这种功能的最佳方法是使用SVG。问题是,白色区域将有一个覆盖整个东西的图像。出于演示目的,我将使用浅蓝色。如果使用带有background-image属性的标准div,则SVG的白色不是透明的,因此您会得到以下内容:

提示几个小时后阅读shape-outsideclip-path属性,这是我尝试过的最新方法(注意我使用的是带有样式组件的React):

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);
`;

仍然有一个差距,但不仅如此,SVG形状的底部三分之一被切断:

我能够让左边的容器填充额外的空间的唯一方法是让右边的容器position: absolute,但是这会导致我计划添加到右边的登录表单出现问题(而且它似乎没有解决切断svg底部三分之一的问题)。
有没有一种方法可以让右边的容器保持在页面流中,显示100%的svg,并确保左边的容器与右边的容器齐平?
编辑:以下是SVG代码:

<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>

这里是到目前为止的React组件(如您所见,构建的早期阶段):

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>
   );
}

编辑2:我已经尝试过从下面的答案中实现解决方案,但到目前为止,每一个都至少有一个问题。从ccprog的建议开始,我有点不确定,因为代码似乎与方法的描述不匹配,但我试图实现它并得出以下结果:(先编码,然后生成图像)

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%;
`

正如您所看到的,这实际上并没有填满屏幕的整个高度,即使在右侧,左侧图像也被切断了(左侧图像在所有解决方案中都是一个问题,正如您将看到的)。
接下来,我试着实现了chrwahl的第二个解决方案。这一个来了一点接近(右侧看起来很棒),但左侧图像有一些问题:

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;
`;

我不确定它是否出现在这张图片中,但屏幕的整个左侧都是空白的,所以即使位置被指定为左,图像似乎也不是从左边缘开始的。background-size: 40%, 70%的问题更严重:

vdzxcuhz

vdzxcuhz1#

首先是一些术语:让我们将SVG形状在顶部和底部覆盖的区域的宽度称为“右侧最小值”,将中间覆盖的宽度称为“右侧最大值”。
我理解你的问题的方式,正确的区域a)有一个恒定的宽度,B)应该总是显示完整的SVG形状。因此,它必须具有恒定的高度和708的纵横比:1056。这使得容易计算所需的大小,最重要的是右侧最小值和右侧最大值之间的比率是564:708.
现在,我建议通过将左侧图像作为背景图像移动到外部容器元素来解决您的问题,其宽度确保它位于弯曲部分i之下。即100%减去564 px(或固定分数)。包含促销内容的左边容器元素的宽度为100%减去708 px,右边容器的宽度为708 px(或固定分数)。(为简单起见,容器由与其组件名称匹配的类名标识)

.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,但只想确保左边的曲线完全可见,请将以下属性添加到根<svg>元素:

preserveAspectRatio="xMinYMid slice"

当改变右侧容器的长宽比时,这将与CSS cover具有相同的效果,加上viewBox的区域始终与左侧对齐。只有当纵横比相对于宽度移动到更高的高度时,这才有效。如果宽高比在宽度上增加,曲线的顶部和底部将被切掉相等的部分-但另一种选择是它不够宽,无法覆盖右侧。
如果你走那条路线,请记住,如果你事先设置了一个固定的高度,你只能知道最大和最小右侧之间的区域的宽度。CSS不能使用元素的高度来计算宽度值。

yuvru6vn

yuvru6vn2#

您可以将图像和SVG作为CSS中的背景。这里有三个不同的例子。首先,我和你有同样的问题。第二个将始终工作,但图像的一部分被SVG覆盖并切断。第三个是测试不同尺寸的问题。
现在,我的例子不是解决方案。Takeaway这里是:您可以在CSS中添加更多的背景图像。请注意,图像由逗号分隔。background-position和-size中的值的数量必须/可以匹配图像的数量。配置取决于图像的大小、宽高比、图像质量和目的。你需要找出什么符合你的场景。
示例中的SVG看起来像这样(注意viewBox已经更改):

<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 798 1056" 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="#16979A"/>
</svg>
.login {
  width: 400px;
  height: 200px;
  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgNzk4IDEwNTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xNDQuNSAwSDc5OS41VjEwNTZIMTQ0LjVMMjMuNDI1NCA3NzUuMTY5QzAuNDAyNTMzIDcyMS43NjggLTUuMDk5MTcgNjYyLjQ0MiA3LjcxMDg5IDYwNS43MThMMTQ0LjUgMFoiIGZpbGw9IiMxNjk3OUEiLz4KPC9zdmc+Cgo='),
  url('https://via.placeholder.com/800x600');
  background-repeat: no-repeat;
  background-position: right, left;
  margin-bottom: 5px;
}

.size1 {
  background-size: contain, contain;
}

.size2 {
  background-size: contain, cover;
}

.size3 {
  background-size: 40%, 70%;
}
<div class="login size1"></div>
<div class="login size2"></div>
<div class="login size3"></div>

相关问题