如何仅使用stroke-dasharray而不是stroke-dashoffset绘制饼图

2022-01-19 00:00:00 frontend svg html css stroke-dasharray

我正在尝试仅使用 stroke-dasharray 和其他东西(如旋转和平移)绘制饼图,我不允许使用 stroke-dashoffset,因为 wkhtmltopdf 0.12.5 不支持它.我试图做一些类似于下面的代码

I am trying to draw a pie chart only using stroke-dasharray and other things like rotate and translate, I am not allowed to use stroke-dashoffset since it is not supported by wkhtmltopdf 0.12.5. I have tried to do something similar to the code below

<svg height="20%" width="20%" viewBox="0 0 20 20" style="border:1px solid gray; ">
  <circle r="10" cx="10" cy="10" fill="white" />
  <circle r="5" cx="10" cy="10" fill="bisque"
          stroke="tomato"
          stroke-width="10"
          stroke-dasharray="10.99 31.4"
          transform="rotate(-90) translate(-20)"/>
</svg>

其中 31.4 是圆的周长,10.99 是周长的 35%.这是绘制一个代表饼图 35% 的切片.如何在不使用 stroke-dashoffset 的情况下绘制更多切片(例如,一个代表 40%,另一个代表 13%),我无法弄清楚这一点.非常感谢大家的帮助.

Where 31.4 is the circumference of the circle and 10.99 is 35% of the circumference. This is drawing a slice representing 35% of the pie. How can I draw more slices (for example one respresenting 40% and another for 13%) after this one without using stroke-dashoffset, I could not figure this out. Thanks a lot for the help guys.

推荐答案

不建议以这种方式创建饼图.通过那种方式",我指的是制作笔画宽度与圆的半径相匹配的圆.准确地说,笔画宽度是圆半径的两倍.

Creating pie charts that way is not really recommended. By "that way", I am referring to making circles where the stroke width matches the radius of the circle. To be precise, the stroke width is double the circle radius.

某些浏览器(或浏览器版本)和渲染库在渲染这种形式的圆圈时存在错误.推荐的方法是为每个饼图段创建一个路径.

Some browsers (or browser versions) and rendering libraries have had bugs rendering circles of that form. The recommended way would be to create a path for each pie chart segment.

但是,假设您想继续使用此方法,那么您需要了解以下内容.

However, assuming you want to continue with this method, then here is what you need to know.

  • <circle> 元素上的笔划图案从 3 点钟开始呈现,并围绕圆圈顺时针方向进行.

  • Stroke patterns on <circle> elements are rendered starting at 3 o'clock, and proceed clockwise around the circle.

这就是您在上面的示例中使用 rotate(-90) 的原因.-90 旋转是将圆旋转 -90 度,以便笔划从顶部(12 点钟方向)开始.

That's why you have the rotate(-90) in your example above. The -90 rotation is rotating the circle -90deg so that the stroke starts at the top (12 o'clock).

破折号模式中的两个数字是<破折号的长度>;<间隙长度>.然后重复该模式.

The two numbers in the dash pattern are <length of dash> <length of gap>. The pattern then repeats.

好的.让我们更新您的 SVG 以添加您请求的额外片段.

Okay. Let's update your SVG to add the extra segments you requested.

首先,我建议进行一些更改:

Firstly, I would suggest a couple of changes:

  1. rotate(-90) 移动到父组,这样您在计算新切片的旋转时就不必担心它.
  2. 如果您使用带有旋转中心的 rotate() 版本,您会发现它要容易得多:rotate(angle, centerX, centerY).
  3. 我们需要将填充颜色 (fill="bisque") 添加到单独的圆圈中.否则,您添加的每个新段的填充将与之前的段重叠.
  1. Move the rotate(-90) to a parent group so that you don't have to worry about it when calculating the rotations for your new slices.
  2. You'll find it a lot easier if you use the version of rotate() that takes a centre of rotaion: rotate(angle, centreX, centreY).
  3. We need to add the fill colour (fill="bisque") to a separate circle. Otherwise the fill of each new segment you add will overlap the previous segments.

所以我们的新起点是这样的:

So our new starting point is this:

<svg height="20%" width="20%" viewBox="0 0 20 20" style="border:1px solid gray; ">
  <circle r="5" cx="10" cy="10" fill="bisque" />
  <g transform="rotate(-90, 10,10)" fill="none" stroke-width="10">
    <circle r="5" cx="10" cy="10"
            stroke="tomato"
            stroke-dasharray="10.99 31.4"/>
  </g>
</svg>

添加 40% 的细分

您需要的笔画长度将是 40% of 31.4 = 12.56.

The stroke length you need will be 40% of 31.4 = 12.56.

要旋转它以使其从第一段的末尾开始,您需要将它旋转一个等于 (10.99/31.4) * 360deg = 126deg 的角度.

To rotate it so that it starts at the end of the first segment, you'll need to rotate it by an angle equal to (10.99 / 31.4) * 360deg = 126deg.

<svg height="20%" width="20%" viewBox="0 0 20 20" style="border:1px solid gray; ">
  <circle r="5" cx="10" cy="10" fill="bisque" />
  <g transform="rotate(-90, 10,10)" fill="none" stroke-width="10">
    <circle r="5" cx="10" cy="10"
            stroke="tomato"
            stroke-dasharray="10.99 31.4"/>
    <circle r="5" cx="10" cy="10"
            stroke="goldenrod"
            stroke-dasharray="12.56 31.4"
            transform="rotate(126, 10,10)"/>
  </g>
</svg>

添加 13% 的细分

您需要的笔画长度将是 13% of 31.4 = 4.082.

The stroke length you need will be 13% of 31.4 = 4.082.

要旋转它以使其从前一段的末尾开始,您需要将前两段的长度相加,并将其转换为角度.

To rotate it so that it starts at the end of the previous segment, you'll need to sum the lengths of the first two segments, and convert that to an angle.

((10.99 + 12.56) / 31.4) * 360deg = 0.75 * 360 = 270deg`.

<svg height="20%" width="20%" viewBox="0 0 20 20" style="border:1px solid gray; ">
  <circle r="5" cx="10" cy="10" fill="bisque" />
  <g transform="rotate(-90, 10,10)" fill="none" stroke-width="10">
    <circle r="5" cx="10" cy="10"
            stroke="tomato"
            stroke-dasharray="10.99 31.4"/>
    <circle r="5" cx="10" cy="10"
            stroke="goldenrod"
            stroke-dasharray="12.56 31.4"
            transform="rotate(126, 10,10)"/>
    <circle r="5" cx="10" cy="10"
            stroke="cornflowerblue"
            stroke-dasharray="4.082 31.4"
            transform="rotate(270, 10,10)"/>
  </g>
</svg>

相关文章