首页 > 解决方案 > 如何创建具有均匀间距的虚线圆圈?

问题描述

我想用 CSS 制作一个虚线圆圈,并使用以下过程创建它。

虽然通过这个过程可以显示虚线圆圈,但是虚线的末端和起点之间的间隙变窄了,并且间隙不均匀。

.c {
  width: 500px;
  height: 500px;
  border-width: 15px;
  border-style: dashed;
  border-radius: 600px;
}
<div class="c"></div>

有没有办法使间隙均匀?我们还可以控制破折号之间的间隙吗?

如果单独使用 CSS 无法做到这一点,我们正在考虑使用 JavaScript 或类似的东西。

标签: javascripthtmlcss

解决方案


这是conic-gradient()解决方案的优化版本,您可以轻松控制破折号的数量和之间的空间

.box {
  --d:4deg; /* distance between dashes */
  --n:30;   /* number of dashes */
  --c:#000; /* color of dashes */
  width: 180px;
  display:inline-block;
  border-radius:50%;
  border:2px solid transparent; /* control the thickness of border*/
  background: 
    linear-gradient(#fff,#fff) padding-box padding-box,
    repeating-conic-gradient(
        var(--c)    0 calc(360deg/var(--n) - var(--d)), 
        transparent 0 calc(360deg/var(--n)) 
    ) border-box;
}

/* keep the element square */
.box:before {
  content:"";
  display:block;
  padding-top:100%;
}
<div class="box"></div>

<div class="box" style="--n:20;border-width:5px;width:150px"></div>

<div class="box" style="--n:8;--d:20deg;border-width:5px;width:150px"></div>

<div class="box" style="--n:10;--d:15deg;border-width:3px;width:100px"></div>

<div class="box" style="--n:10;--d:20deg;border-width:3px;width:100px"></div>

为了完全透明,我们考虑mask

.box {
  --d:4deg; /* distance between dashes */
  --n:30;   /* number of dashes */
  --c:#000; /* color of dashes */
  --b:2px;   /* control the thickness of border*/
  
  width: 180px;
  display:inline-block;
  border-radius:50%;
  background: 
    repeating-conic-gradient(
        var(--c)    0 calc(360deg/var(--n) - var(--d)), 
        transparent 0 calc(360deg/var(--n)));
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px));
          mask:radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px));
}

/* keep the element square */
.box:before {
  content:"";
  display:block;
  padding-top:100%;
}


body {
  background:linear-gradient(to right,yellow,pink);
}
<div class="box"></div>

<div class="box" style="--n:20;--b:5px;width:150px;--c:blue"></div>

<div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;--c:red"></div>

<div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;--c:green"></div>

<div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;--c:purple"></div>

具有均匀空间的 CSS 虚线圆

为了让事情变得有趣,我们甚至可以考虑对破折号进行更复杂的着色:

.box {
  --d:4deg; /* distance between dashes */
  --n:30;   /* number of dashes */
  --b:2px;   /* control the thickness of border*/
  
  width: 180px;
  display:inline-block;
  border-radius:50%;
  background:linear-gradient(red,blue);
  -webkit-mask:
      radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
      repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
  -webkit-mask-composite: source-in;
          mask:
      radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
      repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
          mask-composite: intersect;
}

/* keep the element square */
.box:before {
  content:"";
  display:block;
  padding-top:100%;
}


body {
  background:linear-gradient(to right,yellow,pink);
}
<div class="box"></div>

<div class="box" style="--n:20;--b:5px;width:150px;background:conic-gradient(green,orange,black)"></div>

<div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;background:conic-gradient(black,white,black)"></div>

<div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;background:linear-gradient(60deg,red 50%,green 0)"></div>

<div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;background:#fff"></div>

带有圆锥渐变和蒙版的透明 CSS 破折号

您可能肯定想要其中的一些内容,因此最好在伪元素上应用掩码/背景以避免掩盖内容:

.box {
  --d:4deg; /* distance between dashes */
  --n:30;   /* number of dashes */
  --b:2px;   /* control the thickness of border*/
  
  width: 180px;
  display:inline-flex;
  justify-content:center;
  align-items:center;
  font-size:35px;
  border-radius:50%;
  position:relative;
}
.box::after {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  z-index:-1;
  border-radius:inherit;
  background:var(--c,linear-gradient(red,blue));
  -webkit-mask:
      radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
      repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
  -webkit-mask-composite: source-in;
          mask:
      radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
      repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
          mask-composite: intersect;
  
}

/* keep the element square */
.box:before {
  content:"";
  padding-top:100%;
}


body {
  background:linear-gradient(to right,yellow,pink);
}
<div class="box">19</div>

<div class="box" style="--n:20;--b:5px;width:150px;--c:conic-gradient(green,orange,black)">17</div>

<div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;--c:conic-gradient(black,white,black)">5</div>

<div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;--c:linear-gradient(60deg,red 50%,green 0)">9</div>

<div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;--c:#fff">13</div>


获得更多 CSS 想法以实现类似结果的相关问题:CSS Only Pie Chart - How to add spacing/padding between slices? . 您会发现比conic-gradient()(实际上它不适用于 Firefox)更多受支持的方式,但您需要使用大量代码,这与上面只需要一个元素的解决方案不同。


使用 SVG 你还需要一些计算来确保你有一个统一的间距:

svg {
  width:200px;
}
<svg viewBox="-3 -3 106 106">
  <!-- 
    The circumference of the circle is 2*PI*R ~ 314.16
    if we want N dashed we use d=314.16/N
    For N = 20 we have d=15.71
    For a gap of 5 we will have "10.71,5" (d - gap,gap)
  -->
  <circle cx="50" cy="50" r="50" 
    stroke-dasharray="10.71, 5" 
    fill="transparent" 
    stroke="black" 
    stroke-width="5" />
</svg>

使用 CSS 变量我们可以让它变得更容易,但并不是所有浏览器都支持它(实际上它在 Firefox 中不起作用)

svg {
  --n:20; /* number of dashes*/
  --d:5;  /* distance */
  width:200px;
}

svg circle {
   stroke-dasharray:calc((2*3.14*50)/var(--n) - var(--d)), var(--d); 
}
<svg viewBox="-3 -3 106 106">
  <circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" />
</svg>

<svg viewBox="-3 -3 106 106" style="width:150px;--n:20;--d:10">
  <circle cx="50" cy="50" r="50" fill="transparent" stroke="red"   stroke-width="5" />
</svg>

<svg viewBox="-3 -3 106 106" style="width:100px;--n:8;--d:15">
  <circle cx="50" cy="50" r="50" fill="transparent" stroke="green" stroke-width="5" />
</svg>

SVG 统一空格破折号

我们还可以轻松地使用 SVG 作为背景,让事情变得更加灵活:

.box {
  display:inline-block;
  width:200px;
  background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-3 -3 106 106"><circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" style="stroke-dasharray:29.25, 10" /></svg>') center/contain;
}

.box:before {
  content:"";
  display:block;
  padding-top:100%;
}
<div class="box">

</div>

<div class="box" style="width:150px;">

</div>

<div class="box" style="width:100px;">

</div>

当用作背景时,您需要手动设置该值,因此每次都需要不同的背景。我们只能通过使用 SVG 作为遮罩来使颜色易于更改;

.box {
  display:inline-block;
  width:200px;
  position:relative;
}

.box:before {
  content:"";
  display:block;
  padding-top:100%;
}

.box::after {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  z-index:-1;
  background:var(--c,red);
  -webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-3 -3 106 106"><circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" style="stroke-dasharray:29.25, 10" /></svg>') center/contain;
          mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-3 -3 106 106"><circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" style="stroke-dasharray:29.25, 10" /></svg>') center/contain;
}
<div class="box">

</div>

<div class="box" style="width:150px;--c:linear-gradient(60deg,green 50%,yellow 0);">

</div>

<div class="box" style="width:100px;--c:linear-gradient(red,blue)">

</div>

具有均匀空间的 SVG 虚线边框


推荐阅读