import * as React from 'react'; // @ts-ignore import * as RART from 'react-art'; import { ART, Platform } from 'react-native'; // @ts-ignore const { Shape, Path, Group } = Platform.OS === 'web' ? RART : ART; export interface IMDDoughnutProps { diameter: number; rotation: number; strokeWidth: number; color: string; proportion: number; } const circleRadians = Math.PI * 2; const radiansPerDegree = Math.PI / 180; export default class Doughunt extends React.Component { public static arcDegree (proportion: number) { return (360 * 0.9999 * proportion) / 100; } public render () { const { diameter, rotation, strokeWidth, color, proportion } = this.props; if (!proportion) { return null; } const arcProportion = this.extractProportion(proportion); const arcStart = rotation; const arcEnd = Doughunt.arcDegree(arcProportion) + rotation; const arcPath = this.createArcPath( arcStart, arcEnd, diameter / 2 - strokeWidth / 2, diameter / 2 - strokeWidth / 2 ); return ( ); } private createArcPath ( startAngle: number, endAngle: number, outRadius: number, inRadius: number ) { const path = new Path(); // angles in radians const startAng = this.degreesToRadians(startAngle); const endAng = this.degreesToRadians(endAngle); // central arc angle in radians const centralAng = startAng > endAng ? circleRadians - startAng + endAng : endAng - startAng; // cached sine and cosine values const startSin = Math.sin(startAng); const endSin = Math.sin(endAng); const startCos = Math.cos(startAng); const endCos = Math.cos(endAng); // cached differences const diffSin = endSin - startSin; const diffCos = endCos - startCos; const diffRadius = inRadius - outRadius; // if the angle is over pi radians (180 degrees) // we will need to let the drawing method know. const large = centralAng > Math.PI; path .move( outRadius + outRadius * startSin + this.props.strokeWidth / 2, outRadius - outRadius * startCos + this.props.strokeWidth / 2 ) // move to starting point .arc( outRadius * diffSin, outRadius * -diffCos, outRadius, outRadius, large ) // outer arc .line(diffRadius * endSin, diffRadius * -endCos); // width of arc or wedge if (inRadius) { path.counterArc( inRadius * -diffSin, inRadius * diffCos, inRadius, inRadius, large ); // inner arc } return path; } private degreesToRadians (degrees: number) { if (degrees !== 0 && degrees % 360 === 0) { // 360, 720, etc. return circleRadians; } else { return (degrees * radiansPerDegree) % circleRadians; } } private extractProportion = (arcProportion: number) => Math.min(100, Math.max(0, arcProportion)) }