Skip to content

Commit

Permalink
PieChart basico funcionando
Browse files Browse the repository at this point in the history
  • Loading branch information
v3gaaa committed Aug 30, 2024
1 parent f739558 commit 0cfe49e
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 0 deletions.
2 changes: 2 additions & 0 deletions samples/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import NavBar from './utils/NavBar';
import NormalBarChart from './pages/NormalBarChart';
import StackedBarChart from './pages/StackedBarChart';
import RangedBarChart from './pages/RangedBarChart';
import PieChartExample from './pages/PieChartExample'; // Importamos el nuevo componente

const App = () => {
return (
Expand All @@ -14,6 +15,7 @@ const App = () => {
<Route path="/" element={<NormalBarChart />} />
<Route path="/stacked" element={<StackedBarChart />} />
<Route path="/ranged" element={<RangedBarChart />} />
<Route path="/pie" element={<PieChartExample />} /> {/* Nueva ruta */}
</Routes>
</div>
</Router>
Expand Down
41 changes: 41 additions & 0 deletions samples/pages/PieChartExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import PieChart from '../../src/PieChart';
import Pie from '../../src/Pie';
import PolarGrid from '../../src/PolarGrid';
import Tooltip from '../../src/Tooltip';
import Legend from '../../src/Legend';

const data01 = [
{ "name": "Group A", "value": 400 },
{ "name": "Group B", "value": 300 },
{ "name": "Group C", "value": 300 },
{ "name": "Group D", "value": 200 },
{ "name": "Group E", "value": 278 },
{ "name": "Group F", "value": 189 }
];

const data02 = [
{ "name": "Group A", "value": 2400 },
{ "name": "Group B", "value": 4567 },
{ "name": "Group C", "value": 1398 },
{ "name": "Group D", "value": 9800 },
{ "name": "Group E", "value": 3908 },
{ "name": "Group F", "value": 4800 }
];

const PieChartExample: React.FC = () => {
return (
<div className="p-6">
<h1 className="text-2xl font-semibold mb-4">PieChart</h1>
<PieChart width={730} height={250}>
<PolarGrid />
<Pie data={data01} dataKey="value" nameKey="name" cx="50%" cy="50%" outerRadius={50} fill="#8884d8" />
<Pie data={data02} dataKey="value" nameKey="name" cx="50%" cy="50%" innerRadius={60} outerRadius={80} fill="#82ca9d" label />
<Tooltip />
<Legend />
</PieChart>
</div>
);
};

export default PieChartExample;
1 change: 1 addition & 0 deletions samples/utils/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const NavBar = () => {
{ name: 'Normal BarChart', path: '/' },
{ name: 'Stacked BarChart', path: '/stacked' },
{ name: 'Ranged BarChart', path: '/ranged' },
{ name: 'PieChart', path: '/pie' }, // Nuevo enlace para PieChart
];

return (
Expand Down
86 changes: 86 additions & 0 deletions src/Pie/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import { v4 as uuidv4 } from 'uuid';

interface PieProps {
data: Array<{ name: string; value: number }>;
dataKey: string;
nameKey: string;
cx: string | number;
cy: string | number;
innerRadius?: number;
outerRadius: number;
fill: string;
label?: boolean;
}

const Pie: React.FC<PieProps> = ({
data,
dataKey,
nameKey,
cx,
cy,
innerRadius = 0,
outerRadius,
fill,
label = false,
}) => {
// Convert cx and cy to numeric values if they are percentages
const computedCx = typeof cx === 'string' && cx.endsWith('%') ? parseFloat(cx) / 100 * 730 : cx;
const computedCy = typeof cy === 'string' && cy.endsWith('%') ? parseFloat(cy) / 100 * 250 : cy;

const totalValue = data.reduce((acc, item) => acc + item[dataKey], 0);

let startAngle = 0;

return (
<g transform={`translate(${computedCx}, ${computedCy})`}>
{data.map((entry, index) => {
const value = entry[dataKey];
const angle = (value / totalValue) * 360;
const endAngle = startAngle + angle;
const largeArcFlag = angle > 180 ? 1 : 0;

const outerX = Math.cos((Math.PI / 180) * endAngle) * outerRadius;
const outerY = Math.sin((Math.PI / 180) * endAngle) * outerRadius;
const innerX = Math.cos((Math.PI / 180) * endAngle) * innerRadius;
const innerY = Math.sin((Math.PI / 180) * endAngle) * innerRadius;

const pathData = `
M ${Math.cos((Math.PI / 180) * startAngle) * innerRadius} ${Math.sin((Math.PI / 180) * startAngle) * innerRadius}
L ${Math.cos((Math.PI / 180) * startAngle) * outerRadius} ${Math.sin((Math.PI / 180) * startAngle) * outerRadius}
A ${outerRadius} ${outerRadius} 0 ${largeArcFlag} 1 ${outerX} ${outerY}
L ${innerX} ${innerY}
A ${innerRadius} ${innerRadius} 0 ${largeArcFlag} 0 ${Math.cos((Math.PI / 180) * startAngle) * innerRadius} ${Math.sin((Math.PI / 180) * startAngle) * innerRadius}
Z
`;

startAngle = endAngle;

return (
<g key={uuidv4()}>
<path
d={pathData}
fill={fill}
stroke="#fff"
strokeWidth={1}
/>
{label && outerRadius > 50 && (
<text
x={Math.cos((Math.PI / 180) * (startAngle - angle / 2)) * (outerRadius + 10)}
y={Math.sin((Math.PI / 180) * (startAngle - angle / 2)) * (outerRadius + 10)}
textAnchor="middle"
dominantBaseline="middle"
fill={fill} // Usar el mismo color que el segmento del pie
fontSize="10"
>
{entry[dataKey]}
</text>
)}
</g>
);
})}
</g>
);
};

export default Pie;
23 changes: 23 additions & 0 deletions src/PieChart/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { ReactNode } from 'react';
import Pie from '../Pie';
import PolarAngleAxis from '../PolarAngleAxis';
import PolarRadiusAxis from '../PolarRadiusAxis';
import Tooltip from '../Tooltip';
import Legend from '../Legend';
import PolarGrid from '../PolarGrid';

interface PieChartProps {
width: number;
height: number;
children: ReactNode;
}

const PieChart: React.FC<PieChartProps> = ({ width, height, children }) => {
return (
<svg width={width} height={height}>
{children}
</svg>
);
};

export default PieChart;
35 changes: 35 additions & 0 deletions src/PolarAngleAxis/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';

interface PolarAngleAxisProps {
cx: string | number;
cy: string | number;
ticks?: number[];
stroke?: string;
}

const PolarAngleAxis: React.FC<PolarAngleAxisProps> = ({
cx = '50%',
cy = '50%',
ticks = [0, 90, 180, 270],
stroke = '#ccc',
}) => {
const computedCx = typeof cx === 'string' && cx.endsWith('%') ? parseFloat(cx) / 100 * 730 : cx;
const computedCy = typeof cy === 'string' && cy.endsWith('%') ? parseFloat(cy) / 100 * 250 : cy;

return (
<g transform={`translate(${computedCx}, ${computedCy})`} className="polar-angle-axis">
{ticks.map((tick, index) => (
<line
key={index}
x1="0"
y1="0"
x2={Math.cos((Math.PI / 180) * tick) * 100}
y2={Math.sin((Math.PI / 180) * tick) * 100}
stroke={stroke}
/>
))}
</g>
);
};

export default PolarAngleAxis;
50 changes: 50 additions & 0 deletions src/PolarGrid/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';

interface PolarGridProps {
cx: string | number;
cy: string | number;
radialLines?: number;
concentricCircles?: number;
stroke?: string;
}

const PolarGrid: React.FC<PolarGridProps> = ({
cx = '50%',
cy = '50%',
radialLines = 8,
concentricCircles = 4,
stroke = '#ccc',
}) => {
const computedCx = typeof cx === 'string' && cx.endsWith('%') ? parseFloat(cx) / 100 * 730 : cx;
const computedCy = typeof cy === 'string' && cy.endsWith('%') ? parseFloat(cy) / 100 * 250 : cy;

const radialAngles = Array.from({ length: radialLines }, (_, i) => (360 / radialLines) * i);
const radiusSteps = Array.from({ length: concentricCircles }, (_, i) => 100 / concentricCircles * (i + 1));

return (
<g transform={`translate(${computedCx}, ${computedCy})`} className="polar-grid">
{radialAngles.map((angle, index) => (
<line
key={`line-${index}`}
x1="0"
y1="0"
x2={Math.cos((Math.PI / 180) * angle) * 100}
y2={Math.sin((Math.PI / 180) * angle) * 100}
stroke={stroke}
/>
))}
{radiusSteps.map((radius, index) => (
<circle
key={`circle-${index}`}
cx="0"
cy="0"
r={radius}
fill="none"
stroke={stroke}
/>
))}
</g>
);
};

export default PolarGrid;
35 changes: 35 additions & 0 deletions src/PolarRadiusAxis/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';

interface PolarRadiusAxisProps {
cx: string | number;
cy: string | number;
ticks?: number[];
stroke?: string;
}

const PolarRadiusAxis: React.FC<PolarRadiusAxisProps> = ({
cx = '50%',
cy = '50%',
ticks = [20, 40, 60, 80, 100],
stroke = '#ccc',
}) => {
const computedCx = typeof cx === 'string' && cx.endsWith('%') ? parseFloat(cx) / 100 * 730 : cx;
const computedCy = typeof cy === 'string' && cy.endsWith('%') ? parseFloat(cy) / 100 * 250 : cy;

return (
<g transform={`translate(${computedCx}, ${computedCy})`} className="polar-radius-axis">
{ticks.map((tick, index) => (
<circle
key={index}
cx="0"
cy="0"
r={tick}
fill="none"
stroke={stroke}
/>
))}
</g>
);
};

export default PolarRadiusAxis;
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ export { default as YAxis } from './YAxis';
export { default as Tooltip } from './Tooltip';
export { default as Legend } from './Legend';
export { default as Bar } from './Bar';
export { default as PieChart } from './PieChart';
export { default as Pie } from './Pie';
export { default as PolarAngleAxis } from './PolarAngleAxis';
export { default as PolarRadiusAxis } from './PolarRadiusAxis';
export { default as PolarGrid } from './PolarGrid';

0 comments on commit 0cfe49e

Please sign in to comment.