Search code examples
reactjsrecharts

how to add Inverted triangle shape scatter in rechart


I'm using Scatter chart using rechart and I'm using shape of scatter as "triangle", My requirement is Inverted trianle. I tried using angle but it's not working .can anyone help me in this, How to draw inverted traingle.May be we can write custom shape using rect or path, but I'm new to this,please someone help me .

code:

 const {ScatterChart, Scatter, XAxis, YAxis, ZAxis, CartesianGrid, Tooltip, Legend} = Recharts;
const data01 = [{x: 100, y: 200}, {x: 120, y: 0},
                ];


const ThreeDimScatterChart = React.createClass({
    render () {
    return (
        <ScatterChart width={400} height={400} margin={{top: 20, right: 20, bottom: 20, left: 20}}>
        <XAxis type="number" dataKey={'x'} name='stature' unit='cm'/>
        <YAxis type="number" dataKey={'y'} name='weight' unit='kg'/>
     
        <CartesianGrid />
        <Tooltip cursor={{strokeDasharray: '3 3'}}/>
        <Legend />
        <Scatter name='A school' data={data01} fill='#8884d8' shape="triangle"/>

      </ScatterChart>
    );
  }
})

ReactDOM.render(
  <ThreeDimScatterChart />,
  document.getElementById('container')
);

Thanks


Solution

  • You should create a custom shape for the scatter using polygon or your own SVG.

    Example with polygon:

    <Scatter name="A school" data={data01} fill="#8884d8" shape={<TriangleShape angle={180} />} />;
    
    const TriangleShape = (props: any): JSX.Element => {
      return <polygon {...props} points={calcTrianglePoints(props.cx, props.cy, props.r * 2, props.angle || 0)} />;
    };
    /** *
     * Calc points of the triangle
     *
     * @param xCenter The X-coordinate of the center of triangle
     * @param yCenter The Y-coordinate of the center of triangle
     * @param sideLength The length of the side
     * @param angle The angle in degrees
     */
    const calcTrianglePoints = (xCenter: number, yCenter: number, sideLength: number, angle: number = 0): string => {
      const r = (Math.sqrt(3) / 3) * sideLength; // The radius of the circumscribed circle
      const h = (Math.sqrt(3) / 2) * sideLength; // The height of median
    
      const angleInRadian = (Math.PI * angle) / 180;
    
      const pointCenter: [number, number] = [xCenter, yCenter];
      const pointCenterNew: [number, number] = rotatePoint(pointCenter, angleInRadian);
    
      // 1st point
      const point1 = movePointToNewCoordinates(
        rotatePoint([xCenter, yCenter - r], angleInRadian),
        pointCenterNew,
        pointCenter
      );
      const x1 = point1[0];
      const y1 = point1[1];
    
      // 2nd point
      const point2 = movePointToNewCoordinates(
        rotatePoint([xCenter - sideLength / 2, yCenter + (h - r)], angleInRadian),
        pointCenterNew,
        pointCenter
      );
      const x2 = point2[0];
      const y2 = point2[1];
    
      // 3rd point
      const point3 = movePointToNewCoordinates(
        rotatePoint([xCenter + sideLength / 2, yCenter + (h - r)], angleInRadian),
        pointCenterNew,
        pointCenter
      );
      const x3 = point3[0];
      const y3 = point3[1];
    
      return `${x1},${y1},${x2},${y2},${x3},${y3}`;
    };
    
    /** *
     * Move point to the new coordinate regarding center
     *
     * @param point The coordinate of point
     * @param center The new center
     * @param centerOld The old center
     */
    const movePointToNewCoordinates = (
      point: [number, number],
      center: [number, number],
      centerOld: [number, number]
    ): [number, number] => {
      const x = point[0];
      const y = point[1];
      const xCenter = center[0];
      const yCenter = center[1];
      const xCenterOld = centerOld[0];
      const yCenterOld = centerOld[1];
      return [x - xCenter + xCenterOld, y - yCenter + yCenterOld];
    };
    
    /** *
     * Rotate point
     *
     * @param point The coordinate of point
     * @param center The angle in radians
     */
    const rotatePoint = (point: [number, number], angle: number): [number, number] => {
      const x = point[0];
      const y = point[1];
    
      const xNew = x * Math.cos(angle) - y * Math.sin(angle);
      const yNew = x * Math.sin(angle) + y * Math.cos(angle);
    
      return [xNew, yNew];
    };