复杂的剪辑路径/元素的SVG背景

RGL*_*LSV 8 css svg css3 css-shapes

我需要创建如下图所示的内容:

在此输入图像描述

哪里:

  • 黑色背景表示页面上的元素,header例如
  • 青色背景代表黑色背景下的整体背景
  • 黑色背景元素必须像单个元素一样对待,因为它上面会有一个图案叠加,它必须保持在黑色元素的边框内,并且不会出现在它的外面

只使用一些黑色元素来创建黑色元素将非常容易,:pseudo-elements但是它上面的模式已经使整个事物陷入停顿.

我一直在读clip-path道具.但我不确定我是否能够像这样创建一个复杂的剪辑(或者对我来说似乎很复杂).

整个过程将在iOS应用程序上使用,到目前为止,这个剪辑路径属性似乎与它兼容.另外要提到的是,黑色元素将具有固定的高度,但必须是其父级的100%宽度.我认为我会svg反而使用它,但因为它需要一个固定的高度,它看起来像它的拉伸扭曲.


更新: 右侧必须保持相同的宽度,我想可能在<g>标签内使用两个svgs 并绝对定位它们,一个是流体,另一个是固定宽度.但是,我不确定是否filter会覆盖它们,或者是否filter可以在<g>svg内部对标签应用

以下SVG示例:

body {
  background: cyan;
}
svg {
  min-width: 100%;
  height: 80px;
}
Run Code Online (Sandbox Code Playgroud)
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 452 170" preserveAspectRatio="none">
  <rect x="1" y="14" width="438" height="142" />
  <path d="M0 0v170h452V0H0zM448 166H4V4h444V166z" />
  <rect y="14" width="438" height="142" />
</svg>
Run Code Online (Sandbox Code Playgroud)

任何提示或指示非常感谢!

val*_*als 6

可能是一个更好的解决方案与屏蔽?

#test {
  font-size: 100px;
  position: relative;
  display: inline-block;
  margin: 40px;
}

#test:after {
  content: "";
  position: absolute;
  left: 0px;
  right: 0px;
  top: 0px;
  bottom: 0px;
  z-index: -1;
  background: repeating-linear-gradient(45deg, lightblue, tomato 100px);
  -webkit-mask-image: linear-gradient(red, red),
                    linear-gradient(red, red), 
                    linear-gradient(red, red), 
                    linear-gradient(red, red), 
                    linear-gradient(red, red), 
                    linear-gradient(transparent, transparent);
  -webkit-mask-size: 5% 100%, 5% 100%, 100% 5%, 100% 5%, 80% 80%;
  -webkit-mask-position: left top, right top, center top, center bottom, center center ;
  -webkit-mask-repeat: no-repeat;
}

body {
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<div id="test">Transparent frame</div>
Run Code Online (Sandbox Code Playgroud)

固定宽度的方法

用固定值(以像素为单位)替换边框宽度的尺寸.使用calc作为内部矩形.

body, html {
    width: 90%;
  position: relative;
}

#test {
  font-size: 100px;
  position: relative;
  display: inline-block;
  margin: 40px;
  width: 100%;
  height: 40%;
}

#test:after {
  content: "";
  position: absolute;
  left: 0px;
  right: 0px;
  top: 0px;
  bottom: 0px;
  z-index: -1;
  background: repeating-linear-gradient(45deg, lightblue, tomato 100px);
  -webkit-mask-image: linear-gradient(red, red),
                    linear-gradient(red, red), 
                    linear-gradient(red, red), 
                    linear-gradient(red, red), 
                    linear-gradient(red, red), 
                    linear-gradient(transparent, transparent);
  -webkit-mask-size: 10px 100%, 10px 100%, 100% 10px, 100% 10px, calc(100% - 40px) calc(100% - 40px);
  -webkit-mask-position: left top, right top, center top, center bottom, center center ;
  -webkit-mask-repeat: no-repeat;
}

body {
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<div id="test">Transparent frame</div>
Run Code Online (Sandbox Code Playgroud)

一个椭圆的例子

#test {
  font-size: 100px;
  position: relative;
  display: inline-block;
  margin: 40px;
  border-radius: 50%;
}

#test:after {
  content: "";
  position: absolute;
  left: 0px;
  right: 0px;
  top: 0px;
  bottom: 0px;
  z-index: -1;
  border-radius: 50%;
  background: repeating-linear-gradient(45deg, lightblue, tomato 100px);
  -webkit-mask-image: radial-gradient(ellipse, red 55%, transparent 56%, transparent 65%, red 66%);
}

body {
  background: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<div id="test">Transparent frame</div>
Run Code Online (Sandbox Code Playgroud)


Har*_*rry 6

这可以通过在这篇CSS Tricks文章中使用Ana描述的方法来实现.

使用CSS剪辑路径:

我们需要做的就是使用polygon剪辑,如下面的代码片段,并将其应用于容器.这样的路径将在最外面的盒子和中间盒子之间的间隙中显示背景图像,在中间盒子和最里面的盒子之间隐藏或剪切背景图像.

div {
  height: 200px;
  width: 100%;
  background: url(http://lorempixel.com/800/200/abstract/6);
}
#css-pattern {
  -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0px 0px, 20px 20px, 20px calc(100% - 20px), calc(100% - 20px) calc(100% - 20px), calc(100% - 20px) 20px, 20px 20px, 40px 40px, 40px calc(100% - 40px), calc(100% - 40px) calc(100% - 40px), calc(100% - 40px) 40px, 40px 40px);
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0px 0px, 20px 20px, 20px calc(100% - 20px), calc(100% - 20px) calc(100% - 20px), calc(100% - 20px) 20px, 20px 20px, 40px 40px, 40px calc(100% - 40px), calc(100% - 40px) calc(100% - 40px), calc(100% - 40px) 40px, 40px 40px);
}

/* just for demo */

body {
  background: radial-gradient(circle at center, aliceblue, mediumslateblue);
  min-height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)
<h3>Pure CSS Clip-path with fixed width gap on all 4 sides</h3>
<div id='css-pattern'></div>
Run Code Online (Sandbox Code Playgroud)


使用SVG Clip-path:

SVG clip-path提供比CSS版本更好的浏览器支持,因为它也支持Firefox.我们需要做的就是path在下面的代码片段中创建一个类似的东西并用它来剪切容器.

svg path {
  fill: transparent;
  stroke: black;
}

/* Just for fun */

path {
  animation: draw 5s linear;
  stroke-dasharray: 4450;
}
@keyframes draw {
  from {
    stroke-dashoffset: -4450;
  }
  to {
    stroke-dashoffset: 0;
  }
}
Run Code Online (Sandbox Code Playgroud)
<svg width='600px' height='200px'>
  <path d='M0,0 600,0 600,200 0,200 0,0 20,20 20,180 580,180 580,20 20,20 40,40 40,160 560,160 560,40 40,40 z' />
</svg>
Run Code Online (Sandbox Code Playgroud)

如果容器的尺寸是静态的,SVG实现会容易得多.由于它们不是静态的,因此不能使用分数值,因为该值将根据元素的实际宽度(100%对应的任何宽度)而不同.例如,对于200px宽的元素,分数值0.2意味着40px,对于400px宽的元素意味着80px.您可以看到它如何影响代码段的第一个示例中的输出.

克服这个问题的一种方法是使用JavaScript(或您喜欢的任何其他脚本库),获取元素的实际计算宽度(以像素为单位),并根据它计算路径d属性的坐标值.下面代码段中的第二个示例使用此方法.

注意: IE不支持剪辑路径,但由于您正在创建iOS应用程序,我认为这不应成为您的主要关注点.

window.onload = function() {
  setPathCoords();
};
window.onresize = function() {
  setPathCoords();
};

function setPathCoords() {
  var output = [],
    borderWidth = '20';
  var el = document.getElementById('percentage-pattern'),
    path = document.querySelector('#clipper2 > path'),
    origPath = 'M0,0 1,0 1,1 0,1 0,0 ';
  height = el.clientHeight;
  width = el.clientWidth;

  for (var x = 1; x < 3; x++) {
    point1 = (borderWidth * x) / width + "," + (borderWidth * x) / height;
    point2 = (borderWidth * x) / width + "," + (height - (borderWidth * x)) / height;
    point3 = (width - (borderWidth * x)) / width + "," + (height - (borderWidth * x)) / height;
    point4 = (width - (borderWidth * x)) / width + "," + (borderWidth * x) / height;

    output.push(point1);
    output.push(point2);
    output.push(point3);
    output.push(point4);
    output.push(point1);
  }
  document.querySelector('#clipper2 > path').setAttribute('d', origPath + output.join(' ') + 'z');
}
Run Code Online (Sandbox Code Playgroud)
div {
  height: 200px;
  width: 100%;
  background: url(http://lorempixel.com/800/200/abstract/6);
}
#percentage-pattern {
  -webkit-clip-path: url(#clipper);
  clip-path: url(#clipper);
}
#js-pattern {
  -webkit-clip-path: url(#clipper2);
  clip-path: url(#clipper2);
}

/* just for demo */

body {
  background: radial-gradient(circle at center, aliceblue, mediumslateblue);
  min-height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)
<svg width='0' height='0'>
  <defs>
    <clipPath id='clipper' clipPathUnits='objectBoundingBox'>
      <path d='M0,0 1,0 1,1 0,1 0,0 0.1,0.1 0.1,0.9 0.9,0.9 0.9,0.1 0.1,0.1 0.2,0.2 0.2,0.8 0.8,0.8 0.8,0.2 0.2,0.2z' />
    </clipPath>
    <clipPath id='clipper2' clipPathUnits='objectBoundingBox'>
      <path d='M0,0 1,0 1,1 0,1 0,0 ' />
    </clipPath>
  </defs>
</svg>

<h3>Output with JS</h3>
<div id='js-pattern'></div>
<h3>Pure SVG Clip-path</h3>
<div id='percentage-pattern'></div>
Run Code Online (Sandbox Code Playgroud)