mirror of
https://github.com/kevinsqi/react-circular-progressbar.git
synced 2026-01-25 16:03:15 +00:00
extract Path.tsx, rename the constants
This commit is contained in:
parent
d7a19730b0
commit
f65a8e56db
@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
|
||||
const MIN_PERCENTAGE = 0;
|
||||
const MAX_PERCENTAGE = 100;
|
||||
const MAX_X = 100;
|
||||
const MAX_Y = 100;
|
||||
const FULL_RADIUS = 50;
|
||||
const CENTER_X = 50;
|
||||
const CENTER_Y = 50;
|
||||
import {
|
||||
VIEWBOX_WIDTH,
|
||||
VIEWBOX_HEIGHT,
|
||||
VIEWBOX_HEIGHT_HALF,
|
||||
VIEWBOX_CENTER_X,
|
||||
VIEWBOX_CENTER_Y,
|
||||
} from './constants';
|
||||
import Path from './Path';
|
||||
|
||||
type CircularProgressbarDefaultProps = {
|
||||
strokeWidth: number;
|
||||
@ -122,7 +122,7 @@ class CircularProgressbar extends React.Component<
|
||||
getPathRadius() {
|
||||
// The radius of the path is defined to be in the middle, so in order for the path to
|
||||
// fit perfectly inside the 100x100 viewBox, need to subtract half the strokeWidth
|
||||
return FULL_RADIUS - this.props.strokeWidth / 2 - this.getBackgroundPadding();
|
||||
return VIEWBOX_HEIGHT_HALF - this.props.strokeWidth / 2 - this.getBackgroundPadding();
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -143,15 +143,15 @@ class CircularProgressbar extends React.Component<
|
||||
<svg
|
||||
className={`${classes.root} ${className}`}
|
||||
style={styles.root}
|
||||
viewBox={`0 0 ${MAX_X} ${MAX_Y}`}
|
||||
viewBox={`0 0 ${VIEWBOX_WIDTH} ${VIEWBOX_HEIGHT}`}
|
||||
>
|
||||
{this.props.background ? (
|
||||
<circle
|
||||
className={classes.background}
|
||||
style={styles.background}
|
||||
cx={CENTER_X}
|
||||
cy={CENTER_Y}
|
||||
r={FULL_RADIUS}
|
||||
cx={VIEWBOX_CENTER_X}
|
||||
cy={VIEWBOX_CENTER_Y}
|
||||
r={VIEWBOX_HEIGHT_HALF}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@ -174,7 +174,12 @@ class CircularProgressbar extends React.Component<
|
||||
/>
|
||||
|
||||
{text ? (
|
||||
<text className={classes.text} style={styles.text} x={CENTER_X} y={CENTER_Y}>
|
||||
<text
|
||||
className={classes.text}
|
||||
style={styles.text}
|
||||
x={VIEWBOX_CENTER_X}
|
||||
y={VIEWBOX_CENTER_Y}
|
||||
>
|
||||
{text}
|
||||
</text>
|
||||
) : null}
|
||||
@ -183,79 +188,4 @@ class CircularProgressbar extends React.Component<
|
||||
}
|
||||
}
|
||||
|
||||
function Path({
|
||||
className,
|
||||
counterClockwise,
|
||||
pathRadius,
|
||||
percentage,
|
||||
strokeWidth,
|
||||
style,
|
||||
}: {
|
||||
className?: string;
|
||||
counterClockwise: boolean;
|
||||
pathRadius: number;
|
||||
percentage: number;
|
||||
strokeWidth: number;
|
||||
style?: object;
|
||||
}) {
|
||||
return (
|
||||
<path
|
||||
className={className}
|
||||
style={Object.assign({}, style, getDashStyle({ pathRadius, percentage, counterClockwise }))}
|
||||
d={getPathDescription({
|
||||
pathRadius,
|
||||
counterClockwise,
|
||||
})}
|
||||
strokeWidth={strokeWidth}
|
||||
fillOpacity={0}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// SVG path description specifies how the path should be drawn
|
||||
function getPathDescription({
|
||||
pathRadius,
|
||||
counterClockwise,
|
||||
}: {
|
||||
pathRadius: number;
|
||||
counterClockwise: boolean;
|
||||
}) {
|
||||
const radius = pathRadius;
|
||||
const rotation = counterClockwise ? 1 : 0;
|
||||
|
||||
// Move to center of canvas
|
||||
// Relative move to top canvas
|
||||
// Relative arc to bottom of canvas
|
||||
// Relative arc to top of canvas
|
||||
return `
|
||||
M ${CENTER_X},${CENTER_Y}
|
||||
m 0,-${radius}
|
||||
a ${radius},${radius} ${rotation} 1 1 0,${2 * radius}
|
||||
a ${radius},${radius} ${rotation} 1 1 0,-${2 * radius}
|
||||
`;
|
||||
}
|
||||
|
||||
function getDashStyle({
|
||||
pathRadius,
|
||||
percentage,
|
||||
counterClockwise,
|
||||
}: {
|
||||
pathRadius: number;
|
||||
percentage: number;
|
||||
counterClockwise: boolean;
|
||||
}) {
|
||||
const diameter = Math.PI * 2 * pathRadius;
|
||||
|
||||
// Keep percentage within range (MIN_PERCENTAGE, MAX_PERCENTAGE)
|
||||
const truncatedPercentage = Math.min(Math.max(percentage, MIN_PERCENTAGE), MAX_PERCENTAGE);
|
||||
const gapLength = (1 - truncatedPercentage / 100) * diameter;
|
||||
|
||||
return {
|
||||
// Have dash be full diameter, and gap be full diameter
|
||||
strokeDasharray: `${diameter}px ${diameter}px`,
|
||||
// Shift dash backward by gapLength, so gap starts appearing at correct distance
|
||||
strokeDashoffset: `${counterClockwise ? -gapLength : gapLength}px`,
|
||||
};
|
||||
}
|
||||
|
||||
export default CircularProgressbar;
|
||||
|
||||
82
src/Path.tsx
Normal file
82
src/Path.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import React from 'react';
|
||||
import { VIEWBOX_CENTER_X, VIEWBOX_CENTER_Y } from './constants';
|
||||
|
||||
const MIN_PERCENTAGE = 0;
|
||||
const MAX_PERCENTAGE = 100;
|
||||
|
||||
function Path({
|
||||
className,
|
||||
counterClockwise,
|
||||
pathRadius,
|
||||
percentage,
|
||||
strokeWidth,
|
||||
style,
|
||||
}: {
|
||||
className?: string;
|
||||
counterClockwise: boolean;
|
||||
pathRadius: number;
|
||||
percentage: number;
|
||||
strokeWidth: number;
|
||||
style?: object;
|
||||
}) {
|
||||
return (
|
||||
<path
|
||||
className={className}
|
||||
style={Object.assign({}, style, getDashStyle({ pathRadius, percentage, counterClockwise }))}
|
||||
d={getPathDescription({
|
||||
pathRadius,
|
||||
counterClockwise,
|
||||
})}
|
||||
strokeWidth={strokeWidth}
|
||||
fillOpacity={0}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// SVG path description specifies how the path should be drawn
|
||||
function getPathDescription({
|
||||
pathRadius,
|
||||
counterClockwise,
|
||||
}: {
|
||||
pathRadius: number;
|
||||
counterClockwise: boolean;
|
||||
}) {
|
||||
const radius = pathRadius;
|
||||
const rotation = counterClockwise ? 1 : 0;
|
||||
|
||||
// Move to center of canvas
|
||||
// Relative move to top canvas
|
||||
// Relative arc to bottom of canvas
|
||||
// Relative arc to top of canvas
|
||||
return `
|
||||
M ${VIEWBOX_CENTER_X},${VIEWBOX_CENTER_Y}
|
||||
m 0,-${radius}
|
||||
a ${radius},${radius} ${rotation} 1 1 0,${2 * radius}
|
||||
a ${radius},${radius} ${rotation} 1 1 0,-${2 * radius}
|
||||
`;
|
||||
}
|
||||
|
||||
function getDashStyle({
|
||||
pathRadius,
|
||||
percentage,
|
||||
counterClockwise,
|
||||
}: {
|
||||
pathRadius: number;
|
||||
percentage: number;
|
||||
counterClockwise: boolean;
|
||||
}) {
|
||||
const diameter = Math.PI * 2 * pathRadius;
|
||||
|
||||
// Keep percentage within range (MIN_PERCENTAGE, MAX_PERCENTAGE)
|
||||
const truncatedPercentage = Math.min(Math.max(percentage, MIN_PERCENTAGE), MAX_PERCENTAGE);
|
||||
const gapLength = (1 - truncatedPercentage / 100) * diameter;
|
||||
|
||||
return {
|
||||
// Have dash be full diameter, and gap be full diameter
|
||||
strokeDasharray: `${diameter}px ${diameter}px`,
|
||||
// Shift dash backward by gapLength, so gap starts appearing at correct distance
|
||||
strokeDashoffset: `${counterClockwise ? -gapLength : gapLength}px`,
|
||||
};
|
||||
}
|
||||
|
||||
export default Path;
|
||||
5
src/constants.ts
Normal file
5
src/constants.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export const VIEWBOX_WIDTH = 100;
|
||||
export const VIEWBOX_HEIGHT = 100;
|
||||
export const VIEWBOX_HEIGHT_HALF = 50;
|
||||
export const VIEWBOX_CENTER_X = 50;
|
||||
export const VIEWBOX_CENTER_Y = 50;
|
||||
Loading…
x
Reference in New Issue
Block a user