How to add progressive (nonlinear) scale in Flutter radial gauge (SfRadialGauge)
Description
This article describes how to add the progressive axis scale such as 0, 2, 5,10,20,30,50,100, and 150 using the Flutter radial gauge widget.
Solution
You can show the progressive scale(nonlinear) using the radial gauge widget by extending a custom axis renderer from radial axis renderer class.
Step 1: Create a custom axis renderer class by extending it from radial axis renderer.
class _CustomAxisRenderer extends RadialAxisRenderer { _CustomAxisRenderer() : super(); }
Step 2: The text value of the labels can be changed as required visible labels by overriding the generateVisibleLabels method of custom axis renderer.
/// Generated the 9 non-linear interval labels from 0 to 150 /// instead of actual generated labels. @override List<CircularAxisLabel> generateVisibleLabels() { final List<CircularAxisLabel> _visibleLabels = <CircularAxisLabel>[]; for (num i = 0; i < 9; i++) { final double _value = _calculateLabelValue(i); final CircularAxisLabel label = CircularAxisLabel( this.axis.axisLabelStyle, _value.toInt().toString(), i, false); label.value = _value; _visibleLabels.add(label); } return _visibleLabels; } /// To return the label value based on interval double _calculateLabelValue(num value) { if (value == 0) { return 0; } else if (value == 1) { return 2; } else if (value == 2) { return 5; } else if (value == 3) { return 10; } else if (value == 4) { return 20; } else if (value == 5) { return 30; } else if (value == 6) { return 50; } else if (value == 7) { return 100; } else { return 150; } }
Step 3: The visible label values are converted to a factor values (from 0 to 1) on the axis range by overriding the valueToFactor method of the custom axis renderer class.
@override double valueToFactor(double value) { if (value >= 0 && value <= 2) { return (value * 0.125) / 2; } else if (value > 2 && value <= 5) { return (((value - 2) * 0.125) / (5 - 2)) + (1 * 0.125); } else if (value > 5 && value <= 10) { return (((value - 5) * 0.125) / (10 - 5)) + (2 * 0.125); } else if (value > 10 && value <= 20) { return (((value - 10) * 0.125) / (20 - 10)) + (3 * 0.125); } else if (value > 20 && value <= 30) { return (((value - 20) * 0.125) / (30 - 20)) + (4 * 0.125); } else if (value > 30 && value <= 50) { return (((value - 30) * 0.125) / (50 - 30)) + (5 * 0.125); } else if (value > 50 && value <= 100) { return (((value - 50) * 0.125) / (100 - 50)) + (6 * 0.125); } else if (value > 100 && value <= 150) { return (((value - 100) * 0.125) / (150 - 100)) + (7 * 0.125); } else { return 1; } }
Step 4: Create the radial gauge and add the radial axis by customizing the axis range as desired.
@override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Center( child: SfRadialGauge( axes: <RadialAxis>[ RadialAxis( minimum: 0, maximum: 150, ) ], ), ), ); }
Step 5: Return the custom axis renderer in the onCreateAxisRenderer event of radial axis.
axes: <RadialAxis>[ RadialAxis( minimum: 0, maximum: 150, onCreateAxisRenderer: () { final CustomAxisRenderer renderer = CustomAxisRenderer(); return renderer; }, ) ]
Step 6: Include the range pointer and needle pointer to annotate the desired value.
axes: <RadialAxis>[ RadialAxis(minimum: 0, maximum: 150, onCreateAxisRenderer: () { final CustomAxisRenderer renderer = CustomAxisRenderer(); return renderer; }, pointers: <GaugePointer>[ NeedlePointer( gradient: LinearGradient(colors: const <Color>[ Color.fromRGBO(203, 126, 223, 0.1), Color(0xFFCB7EDF) ], stops: const <double>[ 0.25, 0.75 ], begin: Alignment.bottomCenter, end: Alignment.topCenter), value: 60), RangePointer( value: 60, gradient: const SweepGradient( colors: <Color>[Color(0xFF9E40DC), Color(0xFFE63B86)], stops: <double>[0.25, 0.75]), ) ]) ],
Output
You can download the demo sample from this link.