SVG-Maske oder CSS-Stil, um die Mitte des SVG auszuschalten, damit es transparent ist

Dec 18 2020

Ich habe eine SVG, die im Wesentlichen eine Box mit abgerundeten Kanten und Rändern an den Ecken jeder Kante ist:

<div class="container">
</div>
<svg width="258" height="258" viewBox="0 0 258 258" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M257 211.489L257 245C257 251.627 251.627 257 245 257L211.489 257" stroke="white" stroke-width="2" />
  <path d="M211.489 0.999998L245 0.999999C251.627 1 257 6.37258 257 13L257 46.5111" stroke="white" stroke-width="2" />
  <path d="M46.5111 257L13 257C6.37258 257 1 251.627 1 245L1.00001 211.489" stroke="white" stroke-width="2" />
  <path d="M1 46.5111V13C1 6.37258 6.37258 1 13 1H46.5111" stroke="white" stroke-width="2" />
</svg>

Es ist über einem Container div mit einem farbigen Hintergrund platziert:

body{background: white}
.container {
  margin-top: 70px;
  height: 400px;
  margin: 0 auto;
  background-color: black;
  opacity: 0.55;
}

svg {
  position: absolute;
  top: 50px;
  left: 300px;
}

Ich möchte, dass die Mitte der SVG (der gesamte mittlere Bereich innerhalb der weiß umrandeten Ränder) transparent ist. In diesem Beispiel sehen Sie also den weißen Hintergrund des Körpers.

Hier ist ein CodePen davon: https://codepen.io/lance-p/pen/mdrwyyN

Mir wurde gesagt, dass ich eine Maske verwenden könnte, um dies zu erreichen, aber ich konnte sie nicht zum Laufen bringen. Anregungen (mit oder ohne Maske) wäre willkommen!

Antworten

3 enxaneta Dec 18 2020 at 17:23

Dies ist eine alternative Lösung, bei der ich anstelle des .containerHintergrunds einen sehr breiten Schatten verwende .

Ich habe auch das SVG vereinfacht, aber Sie können Ihren Code hier behalten.

*{margin:0;padding:0}

body {
  background: white;
}
.container {
  margin-top: 70px;
  height: 400px;
  margin: 0 auto;
  overflow: hidden;
  opacity: 0.55;
}

#hole {/*I want the hole to be slightly smaller than the svg element hence the calc*/
  width:calc(258px - 8px);
  height:calc(258px - 8px);
  border-radius:20px;
  position: relative;
  top: calc(50px + 4px);
  left: calc(300px + 4px);
  background:transparent;
  box-shadow:0 0 0 200vmax #000;
}

svg{
  width:258px;
  height:258px;
  position: absolute;
  top: 50px;
  left: 300px;
}
<div class="container">
  <div id="hole"></div>
</div>

  <svg width="258" height="258" viewBox="0 0 258 258" xmlns="http://www.w3.org/2000/svg">

    <rect x="1" y="1" width="256" height="256" rx="20" id="r" stroke="white" stroke-width="2" stroke-dasharray="80 168" stroke-dashoffset="58" fill="none" />

  </svg>

@alexandr_TT kommentiert:

Kann in der Beschreibung irgendwie die Hauptlösung zum Positionieren der weißen Ecken hervorheben. Stroke-dasharray = "80 168" Stroke-dashoffset = "58"

Zuerst müssen Sie die Gesamtlänge des Rect mit abgerundeten Ecken kennen. let l = r.getTotalLength();. Sie teilen diesen Wert durch 4, um die Summe eines Strichs und einer Lücke zu ermitteln: let stroke_gap = l/4;Als Nächstes wählen Sie beispielsweise einen Wert für den Strich aus let stroke = 80. Für die Lücke, die Sie verwenden, let gap = stroke_gap - stroke;habe ich die Zahlen gerundet. Vielleicht sollte ich nicht. Dies gibt mir so etwas wie stroke-dasharray="80 168"Wenn Sie nur dies verwenden, beginnt der erste Strich in einem Abstand von 20 Einheiten (rx = "20") von der Ecke (x = "1" y = "1"). Sie benötigen ein stroke-dashoffsetbis Versetzen Sie die Striche und biegen Sie sie um die Ecken.

Sie können die Länge des Eckteils des Pfades berechnen: Es ist die Länge von 1/4 des Umfangs eines Kreises mit Radius = 20 (rx = 20): let corner = 2 * Math.PI * radius/4;Der Wert für den Strich-Strich-Versatz sollte seinlet sdo = stroke/2 + corner/2

let l = r.getTotalLength();
let radius = 20;
let stroke_gap = l/4;
let stroke = 80;
let gap = stroke_gap - stroke;

let corner = 2 * Math.PI * radius/4;
let sdo = stroke/2 + corner/2;

r.setAttribute("stroke-dasharray",`${stroke} ${gap}`)

r.setAttribute("stroke-dashoffset",sdo)
<svg viewBox="0 0 258 258" xmlns="http://www.w3.org/2000/svg">
  <rect x="1" y="1" width="256" height="256" rx="20" stroke="gold" stroke-width="5" fill="none" />

  <rect x="1" y="1" width="256" height="256" rx="20" id="r" stroke="black" stroke-width="2"  fill="none" />

  <path d="M1,21A20 20 0 0 1 21,1" stroke="red" fill="none" id="corner" />

</svg>