Home > OS >  Pie chart using circle element
Pie chart using circle element

Time:01-11

I am trying to create a pie chart using circle element in svg. I am able to fill values to 60%, 30% and 10% but all the circle starting from same position.

How can I make next circle start from where previous one ended?

svg { transform: rotate(-90deg); }

circle {
  stroke-width: 3;
  stroke-opacity: 1;
  fill: none; 
}

circle.stroke-yellow {
  stroke: yellow;
  stroke-dasharray: calc(2*3.14*50*60/100),calc(2*3.14*50);    
}

circle.stroke-red {
  stroke: red;
  stroke-dasharray: calc(2*3.14*50*30/100),calc(2*3.14*50);  
}

circle.stroke-blue {
  stroke: blue;
  stroke-dasharray: calc(2*3.14*50*10/100),calc(2*3.14*50);  
}
<svg xmlns="http://www.w3.org/2000/svg" height="220">
    <circle  cy="110"  cx="110" r="50"></circle>
    <circle  cy="110" cx="110" r="50"></circle>
    <circle  cy="110" cx="110" r="50"></circle>
</svg>

Also stroke-width is not working which I mentioned in CSS.

CodePudding user response:

As @enxaneta mentioned: you will need to give each pie segment an offset by changing the dash-offset property.

Based on your code example:

svg {
  transform: rotate(-90deg);
}

circle {
  stroke-width: 3;
  stroke-opacity: 1;
  fill: none;
}

.stroke {
  stroke-width: 100;
  --circumference: 314.159
}

circle.stroke-blue {
  stroke: blue;
  stroke-dasharray: calc( var(--circumference) * 10 / 100), var(--circumference);
  stroke-dashoffset: 0;
}

circle.stroke-red {
  stroke: red;
  stroke-dasharray: calc( var(--circumference) * 30 / 100), var(--circumference);
  stroke-dashoffset: calc( 0 - var(--circumference) * 10 / 100);
}

circle.stroke-yellow {
  stroke: yellow;
  stroke-dasharray: calc( var(--circumference) * 60 / 100), var(--circumference);
  stroke-dashoffset: calc( 0 - var(--circumference) * 40 / 100);
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" height="220">
      <circle  cy="110" cx="110" r="50" />
    <circle  cy="110"  cx="110" r="50" />
    <circle  cy="110" cx="110" r="50" />
</svg>

stroke-width needs to be '100' (radius*2);

Drawbacks:

  • Firefox seems to have problems, rendering svg elements when attributes are are calculated via css calc() rendering imprecisions

    Quite likely, this issue will be fixed in future versions of chromium.

    Display pie segments
    Eitherway, you can now easily display a percentage based pie segment/slice by setting a stroke dash length value:

    Example 30% dash length; offset. 0 (since it's the first segment):

      <circle stroke-dashoffset="0" stroke-dasharray="30 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184"  />
    

    Adding pie segments:
    You'll need to decrement (as we need negative values) the dash-offset values progressively by subtracting the previous dash length (percentage):
    0, -30, -90

    Example: 60% dash length; offset. -30

      <circle stroke-dashoffset="-30" stroke-dasharray="60 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184"  />
    

    Example optimized for reusability (using css variables)

    .icon-wrp {
      position: relative;
      display: inline-block;
      width: 200px;
      vertical-align: top;
    }
    
    .chart {
      width: 1em;
      height: 1em;
      font-size: var(--chartFontSize);
    }
    
    .segment {
      stroke-dasharray: var(--percent) 100;
      stroke-dashoffset: var(--offset);
      stroke: var(--strokeColor);
    }
    
    .chartAni .segment {
      animation-name: progress;
      animation-fill-mode: forwards;
      animation-delay: 0.3s;
      animation-duration: 0.5s;
      transition: 0.3s;
      stroke-dasharray: 0 100;
    }
    
    @keyframes progress {
      from {
        stroke-dasharray: 0 100;
        stroke-dashoffset: 0;
      }
      to {
        stroke-dasharray: var(--percent) 100;
        stroke-dashoffset: var(--offset);
      }
    }
    <!-- pie asset – hidden -->
    <svg  style="display:none" viewBox="0 0 63.6619772368 63.6619772368">
      <symbol id="slice" viewBox="0 0 63.6619772368 63.6619772368">
        <circle transform="rotate(-90 31.8309886184 31.8309886184)" id="circle"  cx="31.8309886184" cy="31.8309886184" r="15.9154943092" fill="none" stroke-width="31.8309886184" />
      </symbol>
    </svg>
    
    <!-- visible pie chart -->
    <div >
      <svg id="pieChart01"  style="--chartFontSize:20vw">
        <use  href="#slice" style="--offset:-0; --percent:33.333; --strokeColor:green" />
        <use  href="#slice" style="--offset:-33.333; --percent:33.333; --strokeColor:purple" />
        <use  href="#slice" style="--offset:-66.666; --percent:33.333; --strokeColor:gray" />
      </svg>
    </div>

    CodePudding user response:

    If herrstrietzel's answer doesn't solve your issue for some reason:

    Once upon a time I started working on a blog post demonstrating how to generate simple SVG donut/pie charts in React. It's incomplete but it includes all the information you'd need to compute paths for drawing each segment in your chart.

    The post itself is React-centric, but the methodology doesn't require React.

    The snippet below was generated using the demo in that blog post.

    :root {
      --color1: #6761a8;
      --color2: #009ddc;
      --color3: #f26430;
    }
    
    svg {
      max-width: 180px;
    }
    
    path:nth-child(3n   1) {
      fill: var(--color1);
    }
    
    path:nth-child(3n   2) {
      fill: var(--color2);
    }
    
    path:nth-child(3n   3) {
      fill: var(--color3);
    }
    <svg viewBox="0 0 100 100">
       <path d="M50.99977962889557 22.51817981476399 L50.99993333466665 0.009999666671113516 A50 50 0 1 1 21.909411013411578 91.36325434956197 L34.92449717574351 72.99954813894905 A27.5 27.5 0 1 0 50.99977962889557 22.51817981476399"></path>
       <path d="M33.293128455589205 71.84331575559345 L20.27779148719977 90.20684420744341 A50 50 0 0 1 19.110270928347777 10.683023540969941 L32.65908657059322 28.656553196968876 A27.5 27.5 0 0 0 33.293128455589205 71.84331575559345"></path>
       <path d="M34.25580929035654 27.45292793069627 L20.707239127704607 9.479213229769087 A50 50 0 0 1 49.000066665333264 0.009999666671113516 L49.00022037110441 22.51817981476399 A27.5 27.5 0 0 0 34.25580929035654 27.45292793069627"></path>
    </svg>

  •  Tags:  
  • Related