3D Column Chart In Flutter
![3D Column Chart In Flutter](https://i0.wp.com/flutterexperts.com/wp-content/uploads/2025/02/3D-Column-Chart-In-Flutter.jpg?fit=2160%2C1244&ssl=1)
In this article, we will explore the 3D Column Chart In Flutter. We will implement a demo program and show you how to create a visually striking 3D Column Chart using the Syncfusion Flutter Charts in your Flutter applications.
If you’re looking for the best Flutter app development company for your mobile application then feel free to contact us at — support@flutterdevs.com.
For Syncfusion Flutter Charts:
syncfusion_flutter_charts 28.1.33 | Flutter package
A Flutter Charts library which includes data visualization widgets such as cartesian and circular charts, to create…pub.dev
Table Of Contents::
![](https://i0.wp.com/flutterexperts.com/wp-content/uploads/2025/02/giphy-1.gif?resize=480%2C270&ssl=1)
Introduction:
A Column Chart is a compelling strategy for addressing categorical information utilizing vertical bars. It is great for contrasting information across various gatherings, for this situation, the mobile application development by various framework.
This demo video shows how to create a 3D column chart in Flutter and how a 3D column chart will work using theSyncfusion Flutter Charts in your Flutter applications. We will show a user that we will make a 3d impact for the column track and utilizing a custom series renderer, you can characterize a custom painter to render 3D components that add profundity and interactivity to your chart. It will be shown on your device.
Demo Module::
![](https://i0.wp.com/flutterexperts.com/wp-content/uploads/2025/02/GIF.gif?resize=640%2C914&ssl=1)
Implementation:
Step 1: Add the dependencies
Add dependencies to pubspec — yaml file.
dependencies:
flutter:
sdk: flutter
syncfusion_flutter_charts: ^28.1.33
Step 2: Import
import 'package:syncfusion_flutter_charts/charts.dart';
Step 3: Run flutter packages get in the root directory of your app.
Code Implement:
You need to implement it in your code respectively:
Create a new dart file called main.dart
inside the lib
folder.
In the main. dart file, we will initialize the data for the chart. Now, create a language data model that represents the framework’s name and language in percentages.
class LanguageData {
LanguageData(this.framework, this.languagePercent);
final String framework;
final double languagePercent;
}
Next, a list will be initialized to hold the framework’s language data, adding color data for the oval shape at the top and language data for each framework.
late List<LanguageData> _languageData;
late Map<String, Color> _cylinderColors;
late Map<String, Color> _topOvalColors;
@override
void initState() {
_languageData = <LanguageData>[
LanguageData('Flutter', 80.87),
LanguageData('React', 75.56),
LanguageData('Ionic', 60.92),
LanguageData('Xamarin', 55.22),
LanguageData('Angular', 45.22),
LanguageData('JQuery', 39.25),
];
_cylinderColors = {
'Flutter': const Color.fromARGB(255, 178, 52, 43),
'React': const Color.fromARGB(255, 125, 31, 142),
'Ionic': const Color.fromARGB(255, 8, 133, 120),
'Xamarin': const Color.fromARGB(255, 25, 108, 176),
'Angular': const Color.fromARGB(255, 92, 63, 53),
'JQuery': const Color.fromARGB(255, 139, 126, 4)
};
_topOvalColors = {
'Flutter': const Color.fromARGB(255, 210, 83, 74),
'React': const Color.fromARGB(255, 145, 56, 160),
'Ionic': const Color.fromARGB(255, 47, 150, 140),
'Xamarin': const Color.fromARGB(255, 59, 128, 185),
'Angular': const Color.fromARGB(255, 117, 80, 67),
'JQuery': const Color.fromARGB(255, 179, 163, 15)
};
super.initState();
}
In the body part, we will deliver a Flutter Column Chart with a track, a single ColumnSeries is utilized to envision language information close by a noticeable foundation track. The X-axis is set to CategoryAxis, addressing categorical information like framework names, while the Y-axis is set to NumericAxis for numeric values to show the language utilized in percentage.
How about we utilize the ChartTitle widget to add and alter the chart title. The title is aligned to the center utilizing the alignment property, and we’ve set the ChartAlignment value as the center. The text property is utilized to set the chart’s title.
The onDataLabelRender callback is utilized to change the appearance of data labels. The text property is updated to incorporate a percentage symbol close to the shown value. We should empower the TooltipBehavior to show the extra data when hovering over data points. The onTooltipRender callback modifies the tooltip text by splitting it into an organized header and value.
body: SfCartesianChart(
plotAreaBorderWidth: 0,
title: const ChartTitle(
alignment: ChartAlignment.center,
text:
'Percentage Mobile Application Development Framework',
),
tooltipBehavior: TooltipBehavior(enable: true),
onTooltipRender: (TooltipArgs tooltipArgs) {
List<String> tooltipText = tooltipArgs.text!.split(' : ');
tooltipArgs.header = tooltipText[0];
tooltipArgs.text = '${tooltipText[1]}%';
},
onDataLabelRender: (DataLabelRenderArgs dataLabelArgs) {
dataLabelArgs.text = '${dataLabelArgs.text}%';
},
primaryXAxis: CategoryAxis(
majorGridLines: const MajorGridLines(width: 0),
majorTickLines: const MajorTickLines(width: 0),
axisLine: const AxisLine(width: 0),
axisLabelFormatter: (axisLabelRenderArgs) {
final String countryName = axisLabelRenderArgs.text;
TextStyle textStyle = Theme.of(context)
.textTheme
.titleSmall!
.copyWith(color: _cylinderColors[countryName]);
return ChartAxisLabel(countryName, textStyle);
},
labelPosition: ChartDataLabelPosition.inside,
),
primaryYAxis: const NumericAxis(
isVisible: true,
plotOffsetStart: 50,
),
series: <CartesianSeries<LanguageData, String>>[
ColumnSeries(
dataSource: _languageData,
xValueMapper: (LanguageData data, index) => data.framework,
yValueMapper: (LanguageData data, index) =>
data.languagePercent,
pointColorMapper: (LanguageData data, index) =>
_cylinderColors[data.framework],
animationDuration: 2000,
isTrackVisible: true,
trackColor: const Color.fromARGB(255, 191, 188, 188),
dataLabelSettings: const DataLabelSettings(
isVisible: true,
labelAlignment: ChartDataLabelAlignment.middle),
onCreateRenderer: (ChartSeries series) {
return CustomColumn3DSeries(_topOvalColors);
},
),
],
)
For the primaryXAxis, we’ll utilize a CategoryAxis to address frameworks. We’ll alter the appearance by eliminating the majorGridLines, majorTickLines, and axisLine. We’ll likewise customize the labelPosition to show it inside the chart.
For the primaryYAxis, we will involve a NumericAxis to address the language-involved values in a percentage format. We’ll set the isVisible property to false to conceal the Y-axis labels. Additionally, we’ll change the plotOffsetStart values to 50 to add padding at the beginning of the plot area, enhancing the chart’s visual allure.
This series overlays the language information onto the track. The yValueMapper is utilized to map the percentage of language to the Y-axis, while the pointColorMapper progressively assigns colors to the columns based on the framework name. This guarantees every data point is outwardly particular and simple to interpret. Furthermore, the animationDuration property is set to 2000 milliseconds, which animates the column series smoothly over 2 seconds when the chart is rendered.
Now we will create the CustomColumn3DSeries class extends the ColumnSeriesRenderer to make a custom 3D representation for the column series given on the LanguageData model. The createSegment technique is overridden to return a custom column segment, _CustomColumn3DPaint, which handles drawing 3D impacts for every column.
class CustomColumn3DSeries
extends ColumnSeriesRenderer<LanguageData, String> {
CustomColumn3DSeries(this.topOvalColors);
final Map<String, Color> topOvalColors;
@override
ColumnSegment<LanguageData, String> createSegment() {
return _CustomColumn3DPaint(topOvalColors);
}
}
class _CustomColumn3DPaint extends ColumnSegment<LanguageData, String> {
_CustomColumn3DPaint(this.topOvalColors);
final Map<String, Color> topOvalColors;
@override
void onPaint(Canvas canvas) {
final String countryName = series.xRawValues[currentSegmentIndex]!;
final double trackerTop = series.pointToPixelY(0, 100);
final Rect trackerTopOval = _ovalRect(trackerTop);
final Rect bottomOval = _ovalRect(segmentRect!.bottom);
final Rect animatedTopOval = _ovalRect(segmentRect!.bottom -
((segmentRect!.bottom - segmentRect!.top) * animationFactor));
super.onPaint(canvas);
canvas.drawOval(trackerTopOval,
Paint()..color = const Color.fromARGB(255, 204, 201, 201));
canvas.drawOval(bottomOval, Paint()..color = fillPaint.color);
canvas.drawOval(
animatedTopOval, Paint()..color = topOvalColors[countryName]!);
}
Rect _ovalRect(double ovalCenterY) {
const double ovalRadius = 15;
return Rect.fromLTRB(segmentRect!.left, ovalCenterY - ovalRadius,
segmentRect!.right, ovalCenterY + ovalRadius);
}
}
The __CustomColumn3DPaint class extends ColumnSegment and carries out the onPaint method to add a custom 3D paint. Inside the onPaint method. The ovalRect helper technique produces a rectangular bounding box for the ovals. It takes the center Y-coordinate and works out the aspects utilizing a fixed radius of 15. The subsequent 3D series impact gives the columns an outwardly distinct appearance and makes the data portrayal more engaging and instinctive.
When we run the application, we ought to get the screen’s output like the underneath screen capture.
![](https://i0.wp.com/flutterexperts.com/wp-content/uploads/2025/02/Clone-1.png?resize=640%2C914&ssl=1)
Code File:
import 'package:flutter/material.dart';
import 'package:fluttre_3d_column_chart/splash_screen.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
void main() {
runApp(
const MaterialApp(
home: Splash(),
debugShowCheckedModeBanner: false,
),
);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late List<LanguageData> _languageData;
late Map<String, Color> _cylinderColors;
late Map<String, Color> _topOvalColors;
@override
void initState() {
_languageData = <LanguageData>[
LanguageData('Flutter', 80.87),
LanguageData('React', 75.56),
LanguageData('Ionic', 60.92),
LanguageData('Xamarin', 55.22),
LanguageData('Angular', 45.22),
LanguageData('JQuery', 39.25),
];
_cylinderColors = {
'Flutter': const Color.fromARGB(255, 178, 52, 43),
'React': const Color.fromARGB(255, 125, 31, 142),
'Ionic': const Color.fromARGB(255, 8, 133, 120),
'Xamarin': const Color.fromARGB(255, 25, 108, 176),
'Angular': const Color.fromARGB(255, 92, 63, 53),
'JQuery': const Color.fromARGB(255, 139, 126, 4)
};
_topOvalColors = {
'Flutter': const Color.fromARGB(255, 210, 83, 74),
'React': const Color.fromARGB(255, 145, 56, 160),
'Ionic': const Color.fromARGB(255, 47, 150, 140),
'Xamarin': const Color.fromARGB(255, 59, 128, 185),
'Angular': const Color.fromARGB(255, 117, 80, 67),
'JQuery': const Color.fromARGB(255, 179, 163, 15)
};
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.tealAccent.shade100,
title: const Text("Flutter 3D Column Chart Demo"),
centerTitle: true,
automaticallyImplyLeading: false,
),
body: SfCartesianChart(
plotAreaBorderWidth: 0,
title: const ChartTitle(
alignment: ChartAlignment.center,
text:
'Percentage Mobile Application Development Framework',
),
tooltipBehavior: TooltipBehavior(enable: true),
onTooltipRender: (TooltipArgs tooltipArgs) {
List<String> tooltipText = tooltipArgs.text!.split(' : ');
tooltipArgs.header = tooltipText[0];
tooltipArgs.text = '${tooltipText[1]}%';
},
onDataLabelRender: (DataLabelRenderArgs dataLabelArgs) {
dataLabelArgs.text = '${dataLabelArgs.text}%';
},
primaryXAxis: CategoryAxis(
majorGridLines: const MajorGridLines(width: 0),
majorTickLines: const MajorTickLines(width: 0),
axisLine: const AxisLine(width: 0),
axisLabelFormatter: (axisLabelRenderArgs) {
final String countryName = axisLabelRenderArgs.text;
TextStyle textStyle = Theme.of(context)
.textTheme
.titleSmall!
.copyWith(color: _cylinderColors[countryName]);
return ChartAxisLabel(countryName, textStyle);
},
labelPosition: ChartDataLabelPosition.inside,
),
primaryYAxis: const NumericAxis(
isVisible: true,
plotOffsetStart: 50,
),
series: <CartesianSeries<LanguageData, String>>[
ColumnSeries(
dataSource: _languageData,
xValueMapper: (LanguageData data, index) => data.framework,
yValueMapper: (LanguageData data, index) =>
data.languagePercent,
pointColorMapper: (LanguageData data, index) =>
_cylinderColors[data.framework],
animationDuration: 2000,
isTrackVisible: true,
trackColor: const Color.fromARGB(255, 191, 188, 188),
dataLabelSettings: const DataLabelSettings(
isVisible: true,
labelAlignment: ChartDataLabelAlignment.middle),
onCreateRenderer: (ChartSeries series) {
return CustomColumn3DSeries(_topOvalColors);
},
),
],
),
),
);
}
}
class CustomColumn3DSeries
extends ColumnSeriesRenderer<LanguageData, String> {
CustomColumn3DSeries(this.topOvalColors);
final Map<String, Color> topOvalColors;
@override
ColumnSegment<LanguageData, String> createSegment() {
return _CustomColumn3DPaint(topOvalColors);
}
}
class _CustomColumn3DPaint extends ColumnSegment<LanguageData, String> {
_CustomColumn3DPaint(this.topOvalColors);
final Map<String, Color> topOvalColors;
@override
void onPaint(Canvas canvas) {
final String countryName = series.xRawValues[currentSegmentIndex]!;
final double trackerTop = series.pointToPixelY(0, 100);
final Rect trackerTopOval = _ovalRect(trackerTop);
final Rect bottomOval = _ovalRect(segmentRect!.bottom);
final Rect animatedTopOval = _ovalRect(segmentRect!.bottom -
((segmentRect!.bottom - segmentRect!.top) * animationFactor));
super.onPaint(canvas);
canvas.drawOval(trackerTopOval,
Paint()..color = const Color.fromARGB(255, 204, 201, 201));
canvas.drawOval(bottomOval, Paint()..color = fillPaint.color);
canvas.drawOval(
animatedTopOval, Paint()..color = topOvalColors[countryName]!);
}
Rect _ovalRect(double ovalCenterY) {
const double ovalRadius = 15;
return Rect.fromLTRB(segmentRect!.left, ovalCenterY - ovalRadius,
segmentRect!.right, ovalCenterY + ovalRadius);
}
}
class LanguageData {
LanguageData(this.framework, this.languagePercent);
final String framework;
final double languagePercent;
}
Conclusion:
In the article, I have explained the 3D Column Chart in a flutter; you can modify this code according to your choice. This was a small introduction to 3D Column Chart On User Interaction from my side, and it’s working using Flutter.
I hope this blog will provide you with sufficient information on Trying the 3D Column Chart in your flutter projects. We will show you what the Introduction is. Make a demo program for working on a 3D Column Chart Using the Syncfusion Flutter Charts package in your Flutter applications. So please try it.
❤ ❤ Thanks for reading this article ❤❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
Feel free to connect with us:
And read more articles from FlutterDevs.com.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter-related queries.
We welcome feedback and hope you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.
![](https://i0.wp.com/flutterexperts.com/wp-content/uploads/2024/12/0sDg9epxafARP-CG0-3.png?resize=640%2C256&ssl=1)