Search code examples
cssreactjssvgrecharts

Rotation of <text> doesn't rotate at its position


I'm trying to implement this Piechart, but I want to rotate it without rotating, and then re-rotate its text to be horizontal. Problem is that it is not centering in its position. I've tried to transform-origin center.

How it looks after rotating: How it looks after rotating:

How I want it to look How I want it to look

This is my code:

const data= [
    {
      name: props.language == "CP",
      value: 300
    },
    {
      name: props.language == "CP",
      value: 300
    }
  ];

const RADIAN = Math.PI / 180;
const renderCustomizedLabel = ({
  cx,
  cy,
  midAngle,
  innerRadius,
  outerRadius,
  percent,
  index,
  name
}) => {
  const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
  const x = cx + radius * Math.cos(-midAngle * RADIAN);
  const y = cy + radius * Math.sin(-midAngle * RADIAN);
  console.log(cx, cy, midAngle, innerRadius, outerRadius, RADIAN, radius);
  return (
    <text
       style={{ WebkitTransform: "rotate(90deg)", transformOrigin: "center" }}
      x={x}
      y={y}
      fill="white"
      textAnchor={x > cx ? "start" : "end"}
      dominantBaseline="central"
    >
      {name}
    </text>
  );
};
     <div style={{ width: "100%", height: 310 }} className="rotate">
            <ResponsiveContainer>
              <PieChart>
                <Pie
                  data={data}
                  labelLine={false}
                  label={renderCustomizedLabel}
                  fill="#0eb89a"
                  dataKey="value"
                />
                </PieChart>
            </ResponsiveContainer>

css:

.rotate {
  background-color: transparent;
  transform: rotate(270deg);
  margin: auto;
}

Solution

  • I would use svg transform the text nodes as opposed to positioning them with x and y properties.

    const { PieChart, Pie, Sector, Cell } = Recharts;
    const data = [{name: 'Group A', value: 400}, {name: 'Group B', value: 300},
                      {name: 'Group C', value: 300}, {name: 'Group D', value: 200}];
    const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042'];
    
    const RADIAN = Math.PI / 180;                    
    const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }) => {
        const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
      const x  = cx + radius * Math.cos(-midAngle * RADIAN);
      const y = cy  + radius * Math.sin(-midAngle * RADIAN);
    
      return (
        <text transform={`translate(${x},${y}) rotate(45)`}  fill="white" textAnchor={`middle`}     dominantBaseline="central">
            {`${(percent * 100).toFixed(0)}%`}
        </text>
      );
    };
    
    const SimplePieChart = React.createClass({
        render () {
        return (
            <PieChart width={800} height={400} onMouseEnter={this.onPieEnter}>
            <Pie
              data={data} 
              cx={300} 
              cy={200} 
              labelLine={false}
              label={renderCustomizedLabel}
              outerRadius={80} 
              fill="#8884d8"
            >
                {
                data.map((entry, index) => <Cell fill={COLORS[index % COLORS.length]}/>)
              }
            </Pie>
          </PieChart>
        );
      }
    })
    
    ReactDOM.render(
      <SimplePieChart />,
      document.getElementById('container')
    );
    

    Fiddle