react-native-d3-charts
Version:
Cross platform react native charting library built with d3js and react-native-svg
188 lines (168 loc) • 4.64 kB
JavaScript
import React from "react";
import PropTypes from "prop-types";
import Svg, {G, LinearGradient, Path, Defs, Stop, Text} from "react-native-svg";
import * as scale from "d3-scale";
import * as shape from "d3-shape";
const d3 = {
scale,
shape,
};
const {number, bool, string} = PropTypes;
const object = PropTypes.shape;
const CircularProgressBar = (props) => {
const {
text,
fontSize,
fontFamily,
color,
} = props.label;
const {width, height} = props.size;
const valueArcWidth = props.valueArc.arcWidth;
const valueArcStartColor = props.valueArc.arcStartColor;
const valueArcStopColor = props.valueArc.arcStopColor;
const valueArcOpacity = props.valueArc.arcOpacity;
const baseArcWidth = props.baseArc.arcWidth;
const baseArcColor = props.baseArc.arcColor;
const baseArcOpacity = props.baseArc.arcOpacity;
const dashedArcWidth = props.dashedArc.arcWidth;
const dashedArcColor = props.dashedArc.arcColor;
const dashedArcOpacity = props.dashedArc.arcOpacity;
const value = props.value;
const showDashedArc = props.showDashedArc;
const {max, min} = props.valueRange;
const shortestEdge = width < height ? width : height;
const thickestArc = valueArcWidth > baseArcWidth ? valueArcWidth : baseArcWidth;
const radius = (shortestEdge / 2) - 2 * thickestArc;
const scaleValue = scale.scaleLinear()
.domain([min, max])
.range([0, 2 * Math.PI]);
const scaledValue = scaleValue(value);
const formattedLabel = text.replace(/&value/ig, value);
const valueArc = d3.shape.arc()
.innerRadius(radius)
.outerRadius(radius)
.startAngle(0)
.endAngle(scaledValue);
const baseArc = d3.shape.arc()
.innerRadius(radius)
.outerRadius(radius)
.startAngle(0)
.endAngle(2 * Math.PI);
let dashedArc = null;
if (showDashedArc) {
const dashedArcRadius = radius - ((thickestArc / 2) + (dashedArcWidth / 2));
const dashedArcLines = d3.shape.arc()
.startAngle(0)
.endAngle(scaledValue)
.innerRadius(dashedArcRadius)
.outerRadius(dashedArcRadius);
dashedArc = (<Path
stroke={dashedArcColor}
strokeWidth={dashedArcWidth}
strokeOpacity={dashedArcOpacity}
strokeDasharray={[1,3]}
d={dashedArcLines()}/>);
}
return (
<Svg width={width} height={height} fill="none">
<Defs>
<LinearGradient id="grad" x1="0%" x2="0%" y1="0%" y2="100%">
<Stop offset="0%" stopColor={valueArcStartColor} stopOpacity="1"/>
<Stop offset="100%" stopColor={valueArcStopColor} stopOpacity="1"/>
</LinearGradient>
</Defs>
<G x={width/2} y={height/2} width="100%" height="100%">
{dashedArc}
<Path stroke={baseArcColor}
strokeWidth={baseArcWidth}
strokeOpacity={baseArcOpacity}
d={baseArc()}>
</Path>
<Path
stroke="url(#grad)"
strokeWidth={valueArcWidth}
strokeOpacity={valueArcOpacity}
strokeLinecap="round"
strokeLinejoin="round"
d={valueArc()}/>
</G>
<Text x={width / 2 - 5} y={(height / 2) + (2 * thickestArc) - fontSize}
textAnchor="middle"
fontSize={fontSize}
fontFamily={fontFamily}
stroke={color}
fill={color}>
{formattedLabel}
</Text>
</Svg>
);
};
CircularProgressBar.propTypes = {
size: object({
width: number.isRequired,
height: number.isRequired
}).isRequired,
value: number.isRequired,
valueRange: object({
max: number.isRequired,
min: number.isRequired,
}),
valueArc: object({
arcWidth: number,
arcOpacity: number,
arcStartColor: string,
arcStopColor: string
}),
baseArc: object({
arcWidth: number,
arcOpacity: number,
arcColor: string,
}),
showDashedArc: bool,
dashedArc: object({
arcOpacity: number,
arcWidth: number,
arcColor: string,
}),
label: object({
text: string,
fontSize: number,
fontFamily: string,
color: string,
}),
};
CircularProgressBar.defaultProps = {
size: {
width: 320,
height: 320
},
value: 47,
showDashedArc: true,
valueRange: {
max: 100,
min: 0
},
valueArc: {
arcWidth: 8,
arcOpacity: 1,
arcStartColor: "#f6eb12",
arcStopColor: "#1a4de6"
},
baseArc: {
arcWidth: 3,
arcOpacity: 0.1,
arcColor: "#53c4f5"
},
dashedArc: {
arcOpacity: 0.3,
arcWidth: 18,
arcColor: "#182433"
},
label: {
text: "&value%",
fontSize: 20,
fontFamily: "Helvetica",
color: "black"
}
};
export default CircularProgressBar;