I am a new developer in flutter. I am developing a bar graph using syncfusion_flutter_charts
in flutter. This is what I want to achieve in flutter.
Expected Graph.
And this is what I achieved after hours of struggle.
Achieved Graph
You notice that in label the text is in superscripts format. I tried to achieve this but all effort in vain and moreover there is some padding before start of bar and y-labels are on the axis line. I did a lot research but I couldn't able to replicate these things. This is a university project and any help would be appreciated. This is my code.
List<_ChartData> data= [];
int daysInMonth(DateTime date){
var firstDayThisMonth = DateTime(date.year, date.month, date.day);
var firstDayNextMonth = DateTime(firstDayThisMonth.year, firstDayThisMonth.month + 1, firstDayThisMonth.day);
return firstDayNextMonth.difference(firstDayThisMonth).inDays;
}
List<String> months = <String>[ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
String ordinal(int number) {
if(!(number >= 1 && number <= 100)) {
throw Exception('Invalid number');
}
if(number >= 11 && number <= 13) {
return 'th';
}
switch(number % 10) {
case 1: return 'st';
case 2: return 'nd';
case 3: return 'rd';
default: return 'th';
}
}
for(int i=1;i<=daysInMonth(DateTime.now());i++){
data.add(_ChartData('$i${ordinal(i)} ${months[DateTime.now().month-1]}', (Random().nextInt(11)+1).toDouble()));
}
SizedBox(
height: 25.h,
child: SfCartesianChart(
plotAreaBorderWidth: 0,
primaryXAxis: CategoryAxis(
isVisible: true,
majorGridLines: const MajorGridLines(width: 0),
interval: (daysInMonth(DateTime.now())+ ((daysInMonth(DateTime.now())-1) - 28))/2,
labelAlignment: LabelAlignment.center,
labelStyle: TextStyle(
color: lightAxisGreyColor,
fontSize: 10.sp,
),
edgeLabelPlacement: EdgeLabelPlacement.shift,
labelPlacement: LabelPlacement.onTicks,
),
primaryYAxis: NumericAxis(
minimum: 0, maximum: 12, interval: 12,
labelPosition: ChartDataLabelPosition.outside,
labelAlignment: LabelAlignment.end,
rangePadding: ChartRangePadding.additional,
labelStyle: TextStyle(
color: blackBlueText,
fontSize: 10.sp
),
axisLine: const AxisLine(width: 0)),
tooltipBehavior: TooltipBehavior(
enable: true,
),
series: <ChartSeries<_ChartData, String>>[
ColumnSeries<_ChartData, String>(
dataSource: data,
xValueMapper: (_ChartData data, _) => data.x,
yValueMapper: (_ChartData data, _) => data.y,
name: 'Open Tasks',
width: 1,
spacing: 0.05,
borderRadius: BorderRadius.only(topLeft: Radius.circular(0.25.w),topRight: Radius.circular(0.25.w)),
color: colorPurple)
]),
)
I don't know if it's the way you want it, but at least I used Unicode.
And I made it by referring to your code.
this is result.
I added the following part.
var re = RegExp(r'(%u(?<hexData>[0-9A-Fa-f]{4}))|.');
var th_sup = '%u1d57%u02b0';
var st_sup = '%u02e2%u1d57';
var nd_sup = '%u207f%u1d48';
var rd_sup = '%u02b3%u1d48';
convertedUnicodeStr(String sup) {
var matches = re.allMatches(sup);
var hexDatas = <int>[];
for (var match in matches) {
var hexData = match.namedGroup('hexData');
if (hexData != null) {
hexDatas.add(int.parse(hexData, radix: 16));
} else {
hexDatas += match.group(0)!.runes.toList();
}
}
var decodedStr = String.fromCharCodes(hexDatas);
return decodedStr;
}
and changed switch statement
switch (number % 10) {
case 1:
return convertedUnicodeStr(st_sup); // previous one : return 'st';
case 2:
return convertedUnicodeStr(nd_sup); // previous one : return 'nd';
case 3:
return convertedUnicodeStr(rd_sup); // previous one : return 'rd';
default:
return convertedUnicodeStr(th_sup); // previous one : return 'th';
}
All Codes
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class _ChartData {
final String x;
final double y;
_ChartData(this.x, this.y);
}
class ChartExample extends StatefulWidget {
const ChartExample({Key? key}) : super(key: key);
@override
State<ChartExample> createState() => _ChartExampleState();
}
class _ChartExampleState extends State<ChartExample> {
var re = RegExp(r'(%u(?<hexData>[0-9A-Fa-f]{4}))|.');
var th_sup = '%u1d57%u02b0';
var st_sup = '%u02e2%u1d57';
var nd_sup = '%u207f%u1d48';
var rd_sup = '%u02b3%u1d48';
List<_ChartData> data = [];
List<String> months = <String>[
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
int daysInMonth(DateTime date) {
var firstDayThisMonth = DateTime(date.year, date.month, date.day);
var firstDayNextMonth = DateTime(firstDayThisMonth.year,
firstDayThisMonth.month + 1, firstDayThisMonth.day);
return firstDayNextMonth.difference(firstDayThisMonth).inDays;
}
String ordinal(int number) {
if (!(number >= 1 && number <= 100)) {
throw Exception('Invalid number');
}
if (number >= 11 && number <= 13) {
return 'th';
}
switch (number % 10) {
case 1:
return convertedUnicodeStr(st_sup);
case 2:
return convertedUnicodeStr(nd_sup);
case 3:
return convertedUnicodeStr(rd_sup);
default:
// return 'th';
return convertedUnicodeStr(th_sup);
}
}
init() {
for (int i = 1; i <= daysInMonth(DateTime.now()); i++) {
data.add(_ChartData('$i${ordinal(i)} ${months[DateTime.now().month - 1]}',
(Random().nextInt(11) + 1).toDouble()));
}
}
convertedUnicodeStr(String sup) {
var matches = re.allMatches(sup);
var hexDatas = <int>[];
for (var match in matches) {
var hexData = match.namedGroup('hexData');
if (hexData != null) {
hexDatas.add(int.parse(hexData, radix: 16));
} else {
hexDatas += match.group(0)!.runes.toList();
}
}
var decodedStr = String.fromCharCodes(hexDatas);
return decodedStr;
}
@override
void initState() {
init();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 195,
child: SfCartesianChart(
plotAreaBorderWidth: 0,
primaryXAxis: CategoryAxis(
isVisible: true,
majorGridLines: const MajorGridLines(width: 0),
interval: (daysInMonth(DateTime.now()) +
((daysInMonth(DateTime.now()) - 1) - 28)) /
2,
labelAlignment: LabelAlignment.center,
labelStyle: TextStyle(
color: Colors.green,
fontSize: 10,
),
edgeLabelPlacement: EdgeLabelPlacement.shift,
labelPlacement: LabelPlacement.onTicks,
),
primaryYAxis: NumericAxis(
minimum: 0,
maximum: 12,
interval: 12,
labelPosition: ChartDataLabelPosition.outside,
labelAlignment: LabelAlignment.end,
rangePadding: ChartRangePadding.additional,
labelStyle: TextStyle(color: Colors.black, fontSize: 10),
axisLine: const AxisLine(width: 0)),
tooltipBehavior: TooltipBehavior(
enable: true,
),
series: <ChartSeries<_ChartData, String>>[
ColumnSeries<_ChartData, String>(
dataSource: data,
xValueMapper: (_ChartData data, _) => data.x,
yValueMapper: (_ChartData data, _) => data.y,
name: 'Open Tasks',
width: 1,
spacing: 0.05,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(0.25),
topRight: Radius.circular(0.25)),
color: Colors.purple)
]),
),
),
);
}
}
Lastly, I think you'd better refer to this.
I don't know if this is the answer you want. But I hope it helps.