SVG mask atau CSS style untuk melumpuhkan bagian tengah svg sehingga transparan

Dec 18 2020

Saya memiliki SVG yang pada dasarnya adalah sebuah kotak dengan tepi membulat dan tepi di setiap sudut:

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

Itu ditempatkan di atas div kontainer dengan latar belakang berwarna:

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

Saya ingin bagian tengah SVG (seluruh area tengah di dalam batas tepi putih) menjadi transparan. Jadi dalam contoh ini Anda akan melihat latar belakang putih tubuh.

Inilah CodePen-nya: https://codepen.io/lance-p/pen/mdrwyyN

Saya diberitahu bahwa saya dapat menggunakan topeng untuk mencapai ini tetapi belum bisa membuatnya berfungsi. Setiap saran (dengan atau tanpa topeng) akan sangat dihargai!

Jawaban

3 enxaneta Dec 18 2020 at 17:23

Ini adalah solusi alternatif di mana saya menggunakan bayangan yang sangat lebar sebagai pengganti .containerlatar belakang.

Juga saya telah menyederhanakan svg tetapi Anda dapat menyimpan kode Anda di sini.

*{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 sedang berkomentar:

Entah bagaimana dapat menyoroti dalam deskripsi solusi utama untuk memposisikan sudut putih stroke-dasharray = "80168" stroke-dashoffset = "58"

Pertama, Anda perlu mengetahui panjang total persegi dengan sudut membulat. let l = r.getTotalLength();. Anda membagi nilai ini dengan 4 untuk mengetahui total goresan dan celah: let stroke_gap = l/4;Selanjutnya Anda memilih satu nilai untuk goresan, misalnya let stroke = 80. Untuk celahnya, Anda akan menggunakan let gap = stroke_gap - stroke;saya telah membulatkan angka. Mungkin sebaiknya tidak. Ini memberi saya sesuatu seperti stroke-dasharray="80 168"Jika Anda hanya menggunakan ini pukulan pertama akan dimulai pada jarak 20 unit (rx = "20") dari sudut (x = "1" y = "1") Anda akan membutuhkan a stroke-dashoffsetuntuk offset goresan dan buat mereka bengkok di sekitar sudut.

Anda dapat menghitung panjang bagian sudut jalan: Panjangnya 1/4 keliling lingkaran dengan radius = 20 (rx = 20): let corner = 2 * Math.PI * radius/4;Nilai untuk garis-garis putus-putus haruslet 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>