Home > OS >  How to render n slices inside svg circle?
How to render n slices inside svg circle?

Time:11-13

I am developing a reactJS app.

I need to render an svg circle and when I click it it spawns n equal slices inside.

I created the slices, here is the code

renderSlices = () => {
    let slices = [];

    const numberOfSlice = 12; //number of slices

    for (let i = 0; i < numberOfSlice; i  ) {
      slices.push({ percent: 1 / numberOfSlice, color: 'gray' });
    }

    let cumulativePercent = 0;

    let arr = [];
    arr = slices.map(slice => {
      const [startX, startY] = this.getCoordinatesForPercent(cumulativePercent.toString());
      cumulativePercent  = slice.percent;
      const [endX, endY] = this.getCoordinatesForPercent(cumulativePercent.toString());
      const largeArcFlag = slice.percent > 0.5 ? 1 : 0;
      const pathData = [
        `M ${startX} ${startY}`, // Move
        `A 1 1 0 ${largeArcFlag} 1 ${endX} ${endY}`, // Arc
        'L 0 0', // Line
      ].join(' ');
      return <path d={pathData} fill={slice.color} key={pathData} />;
    });
    return arr;
  }

  getCoordinatesForPercent(percent: string) {
    const x = Math.cos(2 * Math.PI * parseFloat(percent));
    const y = Math.sin(2 * Math.PI * parseFloat(percent));
    return [x, y];
  } 

Render method:

<div className="container">
              <svg
                height="306"
                width="306"
                viewBox="-1 -1 2 2"
              >
                {/* <circle cx="150" cy="150" r="148" stroke="black"
                  strokeWidth="2" fill={"transparent"}/> */}
                {this.renderSlices()}
              </svg>
            </div>

The problem is when I remove the comment from the circle tag and I remove the viewBox, only the circle show up, and when I comment the circle tag and put the viewBox, only the slices show up.

I would like to have the circle with a visible stroke and inside it the slices.

Any help please ?

EDIT:

<svg height="306" width="306" viewBox="0 0 306 306">
    <path d="M 1 0 A 1 1 0 0 1 0.8660254037844387 0.49999999999999994 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M 0.8660254037844387 0.49999999999999994 A 1 1 0 0 1 0.5000000000000001 0.8660254037844386 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M 0.5000000000000001 0.8660254037844386 A 1 1 0 0 1 6.123233995736766e-17 1 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M 6.123233995736766e-17 1 A 1 1 0 0 1 -0.4999999999999998 0.8660254037844387 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M -0.4999999999999998 0.8660254037844387 A 1 1 0 0 1 -0.8660254037844385 0.5000000000000003 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M -0.8660254037844385 0.5000000000000003 A 1 1 0 0 1 -1 5.66553889764798e-16 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M -1 5.66553889764798e-16 A 1 1 0 0 1 -0.866025403784439 -0.4999999999999994 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M -0.866025403784439 -0.4999999999999994 A 1 1 0 0 1 -0.5000000000000004 -0.8660254037844385 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M -0.5000000000000004 -0.8660254037844385 A 1 1 0 0 1 -1.8369701987210297e-16 -1 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M -1.8369701987210297e-16 -1 A 1 1 0 0 1 0.5000000000000001 -0.8660254037844386 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M 0.5000000000000001 -0.8660254037844386 A 1 1 0 0 1 0.8660254037844388 -0.49999999999999967 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
    <path d="M 0.8660254037844388 -0.49999999999999967 A 1 1 0 0 1 1 -2.4492935982947064e-16 L 0 0" stroke-width="2" stroke="black" fill="gray"></path>
</svg>

enter image description here

enter image description here

CodePudding user response:

getCoordinatesForPercent(percent: string, radius: number, circle: {x: number, y: number}) {
    const x = radius * Math.cos(2 * Math.PI * parseFloat(percent))   circle.x;
    const y = radius * Math.sin(2 * Math.PI * parseFloat(percent))   circle.y;
    return [x, y];
} 

Multiply with radius and add the circle coordinates

and change A 1 1 0 ${largeArcFlag} to A ${radius} ${radius} 0 ${largeArcFlag} and 'L 0 0' to 'L ${circle.x} ${circle.y}'

  • Related