-
Notifications
You must be signed in to change notification settings - Fork 725
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added new component - PieChart * Add null return for PieChart component when Svg or Path is not available
- Loading branch information
Showing
8 changed files
with
281 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import React from 'react'; | ||
import {ScrollView} from 'react-native'; | ||
import {View, PieChart, Card, Text, Badge, PieChartSegmentProps, Colors} from 'react-native-ui-lib'; | ||
|
||
const SEGMENTS: PieChartSegmentProps[] = [ | ||
{ | ||
percentage: 40, | ||
color: Colors.blue30 | ||
}, | ||
{ | ||
percentage: 30, | ||
color: Colors.red30 | ||
}, | ||
{ | ||
percentage: 20, | ||
color: Colors.green30 | ||
}, | ||
{ | ||
percentage: 10, | ||
color: Colors.purple30 | ||
} | ||
]; | ||
|
||
const MONOCHROME_SEGMENTS: PieChartSegmentProps[] = [ | ||
{ | ||
percentage: 40, | ||
color: Colors.blue70 | ||
}, | ||
{ | ||
percentage: 30, | ||
color: Colors.blue50 | ||
}, | ||
{ | ||
percentage: 20, | ||
color: Colors.blue30 | ||
}, | ||
{ | ||
percentage: 10, | ||
color: Colors.blue10 | ||
} | ||
]; | ||
|
||
const NOT_FULL_PIECHART: PieChartSegmentProps[] = [ | ||
{ | ||
percentage: 30, | ||
color: Colors.blue30 | ||
}, | ||
{ | ||
percentage: 40, | ||
color: Colors.red30 | ||
} | ||
]; | ||
|
||
const PieChartScreen = () => { | ||
const renderSegmentLabel = (segment: PieChartSegmentProps, text: string) => { | ||
const {percentage, color} = segment; | ||
return ( | ||
<View row gap-s1 marginB-s1 key={text}> | ||
<Badge size={10} containerStyle={{justifyContent: 'center'}} backgroundColor={color}/> | ||
<View> | ||
<Text>{text}</Text> | ||
<Text marginL-s1>{percentage}%</Text> | ||
</View> | ||
</View> | ||
); | ||
}; | ||
|
||
const renderPieChartCard = (segments: PieChartSegmentProps[]) => { | ||
return ( | ||
<Card row spread paddingL-s2 paddingR-s10 paddingV-s2> | ||
<View centerV> | ||
<PieChart segments={segments} diameter={150}/> | ||
</View> | ||
<View height={'100%'} gap-s1> | ||
{segments.map((segment, index) => renderSegmentLabel(segment, `Value ${index + 1}`))} | ||
</View> | ||
</Card> | ||
); | ||
}; | ||
|
||
return ( | ||
<ScrollView> | ||
<View padding-page gap-s2> | ||
<Text text50L marginB-s2> | ||
PieChart | ||
</Text> | ||
{renderPieChartCard(SEGMENTS)} | ||
<Text text50L marginV-s2> | ||
Monochrome colors | ||
</Text> | ||
{renderPieChartCard(MONOCHROME_SEGMENTS)} | ||
<Text text50L marginV-s2> | ||
Not Full PieChart | ||
</Text> | ||
{renderPieChartCard(NOT_FULL_PIECHART)} | ||
</View> | ||
</ScrollView> | ||
); | ||
}; | ||
|
||
export default PieChartScreen; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "PieChart", | ||
"category": "charts", | ||
"description": "Pie Chart", | ||
"example": "https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/PieChartScreen.tsx", | ||
"props": [ | ||
{"name": "segments", "type": "PieChartSegmentProps[]", "description": "Pie chart segments array"}, | ||
{"name": "diameter", "type": "number", "description": "Pie chart diameter"}, | ||
{"name": "dividerWidth", "type": "number", "description": "The width of the divider between the segments"}, | ||
{"name": "dividerColor", "type": "ColorValue", "description": "The color of the divider between the segments"} | ||
], | ||
"snippet": [ | ||
"<PieChart segments={[{percentage: 50, color: Colors.blue30}, {percentage: 30, color: Colors.red30}, {percentage: 20, color: Colors.green30}]} diameter={144}/>" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import React from 'react'; | ||
import {ColorValue, StyleSheet} from 'react-native'; | ||
import View from '../view'; | ||
import {SvgPackage} from '../../optionalDependencies'; | ||
import {Colors} from '../../style'; | ||
const {Svg, Path} = SvgPackage; | ||
|
||
export type PieSegmentProps = { | ||
/** | ||
* The percentage of pie the segment should cover | ||
*/ | ||
percentage: number; | ||
/** | ||
* The radius of the containing pie | ||
*/ | ||
radius: number; | ||
/** | ||
* The color of the segment | ||
*/ | ||
color: string; | ||
/** | ||
* The start angle of the segment | ||
*/ | ||
startAngle?: number; | ||
/** | ||
* The padding between the segments and the container of the pie. | ||
*/ | ||
padding?: number; | ||
/** | ||
* The width of the divider between the segments | ||
*/ | ||
dividerWidth?: number; | ||
/** | ||
* The color of the divider between the segments | ||
*/ | ||
dividerColor?: ColorValue; | ||
}; | ||
|
||
const PieSegment = (props: PieSegmentProps) => { | ||
const { | ||
percentage, | ||
radius, | ||
color, | ||
startAngle = 0, | ||
padding = 0, | ||
dividerWidth = 4, | ||
dividerColor = Colors.$backgroundDefault | ||
} = props; | ||
|
||
const actualRadius = radius - padding; | ||
const centerXAndY = radius; | ||
const amountToCover = (percentage / 100) * 360; | ||
const angleFromTop = startAngle - 90; | ||
|
||
const startRad = (angleFromTop * Math.PI) / 180; | ||
const endRad = startRad + (amountToCover * Math.PI) / 180; | ||
|
||
const startX = centerXAndY + Math.cos(startRad) * actualRadius; | ||
const startY = centerXAndY + Math.sin(startRad) * actualRadius; | ||
const endX = centerXAndY + Math.cos(endRad) * actualRadius; | ||
const endY = centerXAndY + Math.sin(endRad) * actualRadius; | ||
|
||
const largeArcFlag = amountToCover > 180 ? 1 : 0; | ||
const sweepFlag = 1; | ||
|
||
const arcPath = ` | ||
M ${centerXAndY} ${centerXAndY} | ||
L ${startX} ${startY} | ||
A ${actualRadius} ${actualRadius} 0 ${largeArcFlag} ${sweepFlag} ${endX} ${endY} | ||
Z | ||
`; | ||
const startBorderLine = `M ${centerXAndY} ${centerXAndY} L ${startX} ${startY}`; | ||
const endBorderLine = `M ${centerXAndY} ${centerXAndY} L ${endX} ${endY}`; | ||
|
||
const arc = <Path d={arcPath} fill={color}/>; | ||
const borders = ( | ||
<Path | ||
d={`${startBorderLine} ${endBorderLine}`} | ||
fill="none" | ||
stroke={dividerColor} | ||
strokeWidth={dividerWidth / 2} | ||
strokeLinejoin="round" | ||
/> | ||
); | ||
const totalSize = radius * 2 + padding; | ||
|
||
return ( | ||
<View style={styles.container}> | ||
<Svg width={totalSize} height={totalSize} viewBox={`0 0 ${totalSize} ${totalSize}`} style={styles.svg}> | ||
{arc} | ||
{borders} | ||
</Svg> | ||
</View> | ||
); | ||
}; | ||
|
||
export default PieSegment; | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
position: 'absolute' | ||
}, | ||
svg: { | ||
position: 'absolute' | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import React from 'react'; | ||
import View from '../view'; | ||
import PieSegment, {PieSegmentProps} from './PieSegment'; | ||
import {SvgPackage} from '../../optionalDependencies'; | ||
const {Svg, Path} = SvgPackage; | ||
|
||
export type PieChartSegmentProps = Pick<PieSegmentProps, 'percentage' | 'color'>; | ||
|
||
export type PieChartProps = { | ||
/** | ||
* Pie chart segments array | ||
*/ | ||
segments: PieChartSegmentProps[]; | ||
/** | ||
* Pie chart diameter | ||
*/ | ||
diameter?: number; | ||
} & Pick<PieSegmentProps, 'dividerWidth' | 'dividerColor'>; | ||
|
||
const DEFAULT_DIAMETER = 144; | ||
|
||
const PieChart = (props: PieChartProps) => { | ||
const {segments, diameter = DEFAULT_DIAMETER, ...others} = props; | ||
|
||
if (!Svg || !Path) { | ||
console.error(`RNUILib PieChart requires installing "@react-native-svg" dependency`); | ||
return null; | ||
} | ||
|
||
const renderPieSegments = () => { | ||
let currentStartAngle = 0; | ||
|
||
return segments.map((segment, index) => { | ||
const startAngle = currentStartAngle; | ||
currentStartAngle += (segment.percentage / 100) * 360; | ||
return ( | ||
<PieSegment key={index} {...segment} {...others} startAngle={startAngle} radius={diameter / 2}/> | ||
); | ||
}); | ||
}; | ||
return ( | ||
<View width={diameter} height={diameter}> | ||
{renderPieSegments()} | ||
</View> | ||
); | ||
}; | ||
|
||
export default PieChart; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters