SVG边框圆角与内部边框

3
我有一个带有一些设计的块:

enter image description here

我还有一些svg代码:

.box {
 position: relative;
 margin: .75em auto 0;
 max-width: 255px;
 min-height: 56px;
}

svg {
 position: absolute;
 width: 100%; height: 100%;
}
<div class='box'>
 <svg>
  <mask id='m' fill='#fff'>
   <rect id='r' width='256' height='56'/>
   <circle id='c' r='10' fill='#000'/>
   <use xlink:href='#c' x='100%'/>
   <use xlink:href='#c' y='100%'/>
   <use xlink:href='#c' x='100%' y='100%'/>
  </mask>
  
  <mask id='m2' fill='#fff'>
   <rect id='r2' width='248' height='50' x="4" y="4" />
   <circle id='c2' r='14' fill='#000' stroke='#000'/>
   <use xlink:href='#c2' x='100%' />
   <use xlink:href='#c2' y='100%'/>
   <use xlink:href='#c2' x='100%' y='100%'/>
  </mask>
  
  <use xlink:href='#r' fill='red' mask='url(#m)'/>
  <use xlink:href='#r2' fill='none' stroke="#000" mask='url(#m2)'/>
 </svg>
</div>

问题: 如何在一个块内实现相同的圆角切割,但不使用实心填充和描边?

备注: 应该保留编辑圆角半径、缩进等功能。也许可以使用CSS进行简单实现(最大跨浏览器),也能够适用。

3个回答

5

我会选择使用多重背景的纯CSS解决方案。这有点棘手,但是可以使用一些CSS变量使其易于调整:

.box {
  --th:2px; /*thickness of the transparent part*/
  --l:4px; /*height of border*/
  --r:25px; /*radius*/
  
  
  --rad:transparent calc(103% - var(--th) - var(--l) - 1px), 
         #000 calc(103% - var(--th) - var(--l))  
              calc(103% - var(--th) - 1px),
         transparent calc(103% - var(--th)) 103%,
         #000 103%;
  --rad-s:var(--r) var(--r);
  --border:#000 calc(var(--l)),transparent calc(var(--l)),transparent calc(var(--l) + var(--th));
  --w:calc(100% - 2*var(--r) + 2*var(--th));
  --h:calc(var(--l) + var(--th));
  margin:10px;
  display:inline-block;
  padding:40px 20px;
  background:
    /*The 4 borders*/
    linear-gradient(to bottom,var(--border)) top   /var(--w) var(--h),
    linear-gradient(to top   ,var(--border)) bottom/var(--w) var(--h),
    linear-gradient(to right ,var(--border)) left  /var(--h) var(--w),
    linear-gradient(to left  ,var(--border)) right /var(--h) var(--w),
    /*The 4 corners */
    radial-gradient(farthest-side at top    right,var(--rad)) top    right/var(--rad-s),
    radial-gradient(farthest-side at top    left ,var(--rad)) top    left /var(--rad-s),
    radial-gradient(farthest-side at bottom right,var(--rad)) bottom right/var(--rad-s),
    radial-gradient(farthest-side at bottom left ,var(--rad)) bottom left /var(--rad-s),
    /*The main background*/
    linear-gradient(#000,#000) center/calc(100% - 2*var(--r)) calc(100% - 2*var(--h)),
    linear-gradient(#000,#000) center/calc(100% - 2*var(--h)) calc(100% - 2*var(--r));
    
 background-repeat:no-repeat;
 
 color:#fff;
 text-align:center;
}

body {
 background:pink;
}
<div class="box">
  Some text inside
</div>

<div class="box" style="--th:3px;--r:20px">
  Some text inside
</div>

<div class="box" style="--th:4px;--r:40px;--l:8px">
  Some text inside
</div>

<div class="box" style="--th:5px;--r:30px">
  Some text inside
</div>

<div class="box" style="--th:1px;--r:15px;--l:3px">
  Some text inside
</div>

CSS transparent inner border


@HamSter 是的...再检查一下,我添加了几个像素来纠正这个问题。 - Temani Afif
https://codepen.io/semenchenko/pen/mQqZvp?editors=0100 =)) ... 嗯嗯嗯.... - SVE
@HamSter 不是那样的...你需要调整所有的值,而不仅仅是其中几个: https://jsfiddle.net/nb3ph59a/ - Temani Afif
1
@HamSter会尝试编辑以使其更易于调整,但如果您找到了好的方法,SVG会更好。 - Temani Afif
1
@HamSter 进行了一些编辑,虽然还不完美,但现在更容易处理了。 - Temani Afif

5

这样怎么样?只需更改 <div class="box"> 的尺寸,就可以适用于任何大小。

.box {
 position: relative;
 margin: .75em auto 0;
 width: 255px;
 height: 56px;
}

.box svg {
 position: absolute;
 width: 100%;
  height: 100%;
}

.size2 {
 width: 455px;
 height: 256px;
}
<div class="box">
  <svg width="100%" height="100%">
    <mask id="m" fill="#fff">
      <rect width="100%" height="100%"/>

      <rect width="100%" height="100%" fill="none" stroke="#000" stroke-width="12"/>
      <circle r="16" fill="#000"/>
      <circle cx="100%" r="16" fill="#000"/>
      <circle cy="100%" r="16" fill="#000"/>
      <circle cx="100%" cy="100%" r="16" fill="#000"/>

      <rect width="100%" height="100%" fill="none" stroke="#fff" stroke-width="8"/>
      <circle r="14" fill="#fff"/>
      <circle cx="100%" r="14" fill="#fff"/>
      <circle cy="100%" r="14" fill="#fff"/>
      <circle cx="100%" cy="100%" r="14" fill="#fff"/>

      <circle r="10" fill="#000"/>
      <circle cx="100%" r="10" fill="#000"/>
      <circle cy="100%" r="10" fill="#000"/>
      <circle cx="100%" cy="100%" r="10" fill="#000"/>
    </mask>
  
    <rect width="100%" height="100%" mask="url(#m)"/>
  </svg>
</div>


有没有一种方法可以包含一种变量来一次性调整所有相同的值? - Temani Afif
SVG2 允许您使用 CSS 设置 r。因此,您可以像 Afif 的答案中那样使用 CSS 变量和 calc()。但是,到目前为止,只有 Chrome 支持 SVG2 的这一部分。或者,您可以使用 JavaScript 调整所有半径和描边宽度。 - Paul LeBeau
你的回答比其他人都更有帮助,https://codepen.io/semenchenko/pen/BGJaVx,谢谢! - SVE

2
这是我的回答:我使用文本边界框的大小,这样您可以随意更改文本。对于切除的角,我使用弧线。此外,您可以更改“填充”即文本和边框之间的距离。

let bb = txt.getBBox();


function drawShape(path, padding){
let d = `M${bb.x},${bb.y - padding}
         L${bb.x + bb.width},${bb.y - padding}
A${padding}, ${padding} 0 0 0 ${bb.x + bb.width + padding},${bb.y}
         L${bb.x + bb.width + padding},${bb.y + bb.height}
A${padding}, ${padding} 0 0 0 ${bb.x + bb.width},${bb.y + bb.height + padding}
         L${bb.x},${bb.y + bb.height + padding}
A${padding}, ${padding} 0 0 0 ${bb.x  - padding},${bb.y + bb.height}
         L${bb.x  - padding},${bb.y}
A${padding}, ${padding} 0 0 0 ${bb.x},${bb.y - padding}z
`
path.setAttributeNS(null,"d",d)
}
drawShape(pth, 10);
drawShape(pth1, 10);
<svg viewBox="0 0 200 100">
  <path id="pth" fill="black" stroke="black" stroke-width="4" d="" />
  <path id="pth1" stroke="white" stroke-width="2" d="" />
  <text id="txt" fill="white" dominant-baseline="central" text-anchor="middle" x="100" y="50">
    some text inside
  </text>
  </svg>


如果内部边框(白边框)应该是 1px2px,我应该更改什么? - SVE
在SVG中,您需要调整#pth#pth1stroke-width,并牢记黑色描边(#pth)应该比白色描边(#pth1)更宽。 - enxaneta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接