Skip to content

Commit

Permalink
Active Shape view
Browse files Browse the repository at this point in the history
  • Loading branch information
v3gaaa committed Sep 10, 2024
1 parent 19e66e6 commit 83bbda2
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 19 deletions.
2 changes: 2 additions & 0 deletions samples/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import PieChart from './pages/PieChart';
import StraightAnglePieChart from './pages/StraightAnglePieChart';
import PieChartWithPaddingAngle from './pages/PieChartWithPaddingAngle';
import PieChartWithCustomizedLabel from './pages/PieChartWithCustomizedLabel';
import CustomActiveShapePieChart from './pages/CustomActiveShapePieChart';


const App = () => {
Expand All @@ -27,6 +28,7 @@ const App = () => {
<Route path="/straight-angle-pie" element={<StraightAnglePieChart />} />
<Route path="/pie-chart-with-padding-angle" element={<PieChartWithPaddingAngle />} />
<Route path="/pie-chart-with-customized-label" element={<PieChartWithCustomizedLabel />} />
<Route path="/custom-active-shape-pie" element={<CustomActiveShapePieChart />} />
</Routes>
</div>
</Router>
Expand Down
67 changes: 67 additions & 0 deletions samples/pages/CustomActiveShapePieChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useState } 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';
import PieChartControls from '../utils/PieChartControls';

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 CustomActiveShapePieChart: React.FC = () => {
const [pies, setPies] = useState([
{
id: 1,
innerRadius: 0,
outerRadius: 80,
cx: '50%',
cy: '50%',
showLabels: true,
startAngle: 0,
endAngle: 360,
label: 'percent',
activeShape: true,
},
]);
const [showPolarGrid, setShowPolarGrid] = useState(true);

return (
<div className="p-6">
<h1 className="text-2xl font-semibold mb-4">Custom Active Shape Pie Chart</h1>
<div className="flex gap-6">
<PieChartControls pies={pies} setPies={setPies} showPolarGrid={showPolarGrid} setShowPolarGrid={setShowPolarGrid} />
<PieChart width={730} height={250}>
{showPolarGrid && <PolarGrid />}
{pies.map((pie) => (
<Pie
key={pie.id}
data={data01}
dataKey="value"
nameKey="name"
cx={pie.cx}
cy={pie.cy}
innerRadius={pie.innerRadius}
outerRadius={pie.outerRadius}
startAngle={pie.startAngle}
endAngle={pie.endAngle}
fill="#8884d8"
label={pie.label}
activeShape={pie.activeShape}
/>
))}
<Tooltip />
<Legend />
</PieChart>
</div>
</div>
);
};

export default CustomActiveShapePieChart;
12 changes: 2 additions & 10 deletions samples/pages/PieChartWithCustomizedLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,11 @@ const PieChartWithCustomizedLabel: React.FC = () => {
showLabels: true,
startAngle: 0,
endAngle: 360,
label: ['A', 'B', 'C', 'D', 'E', 'F'], // Start with custom labels
label: ['A', 'B', 'C', 'D', 'E', 'F'],
},
]);
const [showPolarGrid, setShowPolarGrid] = useState(true);

const handleLabelToggle = (index: number, show: boolean) => {
const updatedPies = [...pies];
updatedPies[index].showLabels = show;
// Sync the label with the showLabels state
updatedPies[index].label = show ? updatedPies[index].label : false;
setPies(updatedPies);
};

return (
<div className="p-6">
<h1 className="text-2xl font-semibold mb-4">PieChart With Customized Label</h1>
Expand All @@ -64,7 +56,7 @@ const PieChartWithCustomizedLabel: React.FC = () => {
startAngle={pie.startAngle}
endAngle={pie.endAngle}
fill="#8884d8"
label={pie.showLabels ? pie.label : false} // Sync label with showLabels state
label={pie.showLabels ? pie.label : false}
/>
))}
<Tooltip />
Expand Down
3 changes: 2 additions & 1 deletion samples/utils/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ const NavBar = () => {
{
category: 'Pie Charts',
items: [
{ name: 'Double Layer Pie Chart', path: '/double-layer-pie' },
{ name: 'Pie Chart', path: '/pie-chart' },
{ name: 'Double Layer Pie Chart', path: '/double-layer-pie' },
{ name: 'Straight Angle Pie Chart', path: '/straight-angle-pie' },
{ name: 'Pie Chart with Padding Angle', path: '/pie-chart-with-padding-angle' },
{ name: 'Pie Chart with Customized Label', path: '/pie-chart-with-customized-label' },
{ name: 'Custom Active Shape Pie Chart', path: '/custom-active-shape-pie' },
],
},
];
Expand Down
18 changes: 16 additions & 2 deletions samples/utils/PieChartControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface PieChartControlsProps {
endAngle?: number;
label?: 'percent' | string[] | boolean;
paddingAngle?: number;
activeShape?: boolean;
}>;
setPies: React.Dispatch<React.SetStateAction<Array<{
id: number;
Expand All @@ -24,6 +25,7 @@ interface PieChartControlsProps {
endAngle?: number;
label?: 'percent' | string[] | boolean;
paddingAngle?: number;
activeShape?: boolean;
}>>>;
showPolarGrid?: boolean;
setShowPolarGrid?: (show: boolean) => void;
Expand All @@ -41,12 +43,13 @@ const PieChartControls: React.FC<PieChartControlsProps> = ({ pies, setPies, show
if (value === 'percent') {
updatedPies[index].label = 'percent';
} else if (value) {
updatedPies[index].label = value.split(','); // Split string into array of labels
updatedPies[index].label = value.split(',');
} else {
updatedPies[index].label = true; // Default to showing values
updatedPies[index].label = true;
}
setPies(updatedPies);
};

return (
<div className="bg-white p-6 shadow-lg rounded-lg mb-5 max-w-md">
<h2 className="text-2xl font-semibold mb-6 text-purple-600">Chart Settings</h2>
Expand Down Expand Up @@ -167,6 +170,17 @@ const PieChartControls: React.FC<PieChartControlsProps> = ({ pies, setPies, show
/>
</div>
)}
{pie.activeShape !== undefined && (
<label className="flex items-center space-x-2 text-purple-600 hover:bg-purple-100 rounded-lg p-2 transition duration-300 ease-in-out">
<input
type="checkbox"
checked={pie.activeShape}
onChange={(e) => handlePieChange(index, 'activeShape', e.target.checked)}
className="form-checkbox h-5 w-5 text-purple-600 rounded transition duration-300 ease-in-out"
/>
<span className="text-sm">Active Shape</span>
</label>
)}
</div>
</div>
))}
Expand Down
24 changes: 18 additions & 6 deletions src/Pie/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { v4 as uuidv4 } from 'uuid';

interface PieProps {
Expand All @@ -14,6 +14,7 @@ interface PieProps {
startAngle?: number;
endAngle?: number;
paddingAngle?: number;
activeShape?: boolean;
}

const Pie: React.FC<PieProps> = ({
Expand All @@ -29,6 +30,7 @@ const Pie: React.FC<PieProps> = ({
startAngle = 0,
endAngle = 360,
paddingAngle = 0,
activeShape = false,
}) => {
const computedCx = typeof cx === 'string' && cx.endsWith('%') ? parseFloat(cx) / 100 * 730 : cx;
const computedCy = typeof cy === 'string' && cy.endsWith('%') ? parseFloat(cy) / 100 * 250 : cy;
Expand All @@ -38,6 +40,8 @@ const Pie: React.FC<PieProps> = ({

let currentAngle = startAngle + 180;

const [activeIndex, setActiveIndex] = useState<number | null>(null);

return (
<g transform={`translate(${computedCx}, ${computedCy})`}>
{data.map((entry, index) => {
Expand All @@ -62,29 +66,37 @@ const Pie: React.FC<PieProps> = ({

currentAngle = nextAngle + paddingAngle;

// Definir el texto del label basado en la propiedad `label` o usar valor como default
// Define el label
let labelText = '';
if (label === 'percent') {
labelText = `${((value / totalValue) * 100).toFixed(1)}%`;
} else if (Array.isArray(label) && label[index]) {
labelText = label[index];
} else {
// Si no hay `label` especificado, usar el valor por defecto
labelText = `${value}`;
}

// Aumentar el tamaño si el segmento está activo
const isActive = activeShape && activeIndex === index;
const adjustedOuterRadius = isActive ? outerRadius + 10 : outerRadius;

return (
<g key={uuidv4()}>
<g
key={uuidv4()}
onMouseEnter={() => setActiveIndex(index)}
onMouseLeave={() => setActiveIndex(null)}
>
<path
d={pathData}
fill={fill}
stroke="#fff"
strokeWidth={1}
style={{ transform: isActive ? 'scale(1.05)' : 'scale(1)', transition: 'transform 0.2s' }}
/>
{label && (
<text
x={Math.cos((Math.PI / 180) * (currentAngle - angle / 2)) * (outerRadius + 10)}
y={Math.sin((Math.PI / 180) * (currentAngle - angle / 2)) * (outerRadius + 10)}
x={Math.cos((Math.PI / 180) * (currentAngle - angle / 2)) * (adjustedOuterRadius + 10)}
y={Math.sin((Math.PI / 180) * (currentAngle - angle / 2)) * (adjustedOuterRadius + 10)}
textAnchor="middle"
dominantBaseline="middle"
fill={fill}
Expand Down

0 comments on commit 83bbda2

Please sign in to comment.