【问题标题】:Dashes doesn't start full at the beginning in circle svg破折号在圆 svg 的开头没有完整开始
【发布时间】:2022-01-15 02:43:53
【问题描述】:

我想为成绩创建一个虚线进度圈。我想使最大等级的破折号函数的长度。 (例如:如果成绩为 3.5/5,则破折号的长度为 24px)。

问题是第一个破折号(右上角的那个)不是想要的长度。

<svg xmlns="http://www.w3.org/2000/svg" [attr.viewBox]="_getViewBox()">

  <!-- The grey circle plain for background-->
  <path
  #background
  fill="none"
  [style.stroke-width]="stroke"
  [style.stroke]="'#EAEAEA'"
  [attr.transform]="getPathTransform()"/>

  <!-- The blue circle plain for progress -->
  <path
  #path
  fill="none"
  [style.stroke-width]="stroke"
  [style.stroke]="resolveColor(color)"
  [attr.transform]="getPathTransform()"/>

  <!-- The white dashed circle for delimitation of dashes -->
  <path
  #dash
  fill="none"
  [style.stroke-width]="stroke"
  [style.stroke]="'#ffffff'"
  stroke-dasharray="4.3,23.7"
  [attr.transform]="getPathTransform()"/>
</svg>

请注意,如果我将此值保留在最后一条路径上 > stroke-dasharray="4.3,23.7" 我会得到:

但这只是因为我遇到了将其放置在半径为 70 的良好价值。因为如果我想更改它(例如使其成为最高等级的函数),我有这个:

我想要的是对破折号的数量和破折号的长度有一个连贯的值,我有点迷茫,我不知道该怎么办

【问题讨论】:

  • 那么,系统是什么? 3.3/5 应该是 14 个破折号,而 12/20 应该是 25 个破折号来填充圆——对吗?计算方法是什么?

标签: css svg path stroke stroke-dasharray


【解决方案1】:

在本例中,我使用遮罩来创建 stroke-dasharray。 dasharray 是根据 max-score (total) 计算的。破折号之间总是有 5 个单位的间隔(总/路径长度为 1000)。

然后将蒙版应用于两个圆圈。灰色圆圈始终是一个完整的圆圈,而 DarkTurquoise 圆圈的长度取决于分数。

两个圆都旋转了 -90 度,因此得分 0 位于 12 点处。

const c1 = document.getElementById('c1');
const c2 = document.getElementById('c2');
const t1 = document.getElementById('t1');

const update = (total, score) => {
  c1.setAttribute('stroke-dasharray', `${(1000-total*5)/total} 5`);
  c2.setAttribute('stroke-dasharray', `${1000/total*score} 1000`);
  t1.textContent = `${score}/${total}`;
};

document.forms.form01.total.addEventListener('change', e => {
  let total = parseInt(e.target.value);
  let score = parseInt(e.target.form.score.value);
  e.target.form.score.setAttribute('max', total);
  if (score >= total) score = total;
  update(total, score);
});

document.forms.form01.score.addEventListener('change', e => {
  let total = parseInt(e.target.form.total.value);
  let score = parseInt(e.target.value);
  update(total, score);
});
body {
  display: flex;
}

form {
  display: flex;
  flex-direction: column;
}
<form name="form01">
  <label>Total: <input name="total" type="range" min="5" max="30" value="10"/></label>
  <label>Score: <input name="score" type="range" min="0" max="10" value="5"/></label>
</form>
<svg viewBox="0 0 100 100" width="250" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <mask id="mask01">
      <circle id="c1" cx="50" cy="50" r="40" fill="none" stroke="white" stroke-width="10" stroke-dasharray="95 5" pathLength="1000"/>
    </mask>
  </defs>
  <g transform="rotate(-90 50 50)">
  <circle mask="url(#mask01)" cx="50" cy="50" r="40" fill="none" stroke="Gainsboro" stroke-width="10" />
  <circle id="c2" mask="url(#mask01)" cx="50" cy="50" r="40" fill="none" stroke="DarkTurquoise" stroke-width="10" stroke-dasharray="500 1000" pathLength="1000" />
  </g>
  <text id="t1" x="50" y="50" dominant-baseline="middle" text-anchor="middle" font-family="sans-serif" fill="DarkTurquoise">5/10</text>
</svg>

【讨论】:

  • 这正是我想做的!非常感谢 !!我必须对其进行测试,但我想知道如果我输入一个十进制值会发生什么。再次感谢您
  • @AG 浮点数在 SVG 中很好用。但是示例中的“破折号”是基于与它们之间的分割相匹配的值。
  • 仅作记录,它与十进制值完美配合!我正在尝试做同样的事情,但使用行进度条,但我无法使其正常工作。你使用面具的方式也可以吗?
  • @AG a &lt;line&gt; 也可以有一个破折号,所以如果你有破折号和两种颜色的相同设置,我想它可以工作。唯一的问题:它没有 pathLength 属性,所以使用直线路径可能更容易,例如:&lt;path d="M 0 0 H 60" pathLength="1000"/&gt;
  • @AG 带有路径的示例:codepen.io/chrwahl/pen/GRMaKKR
猜你喜欢
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-25
  • 2018-04-22
  • 2023-04-06
相关资源
最近更新 更多