I have tried creating this bar graph using SfCartesianChart, and have been able to complete 95% of it, but unable to remove the middle labels.
...
Lobo,
Greetings from Syncfusion.
We have validated your query and we have achieved your requirement by using the axisLabelFormatter callback in axis. We have rendered the first and last axis labels alone using this axisLabelFormatter callback, and its invoked while rendering each axis label in the chart. Please refer the following code snippet.
Code snippet :
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Syncusion flutter charts'),
centerTitle: true,
),
body: SfCartesianChart(
primaryXAxis: CategoryAxis(
axisLabelFormatter: (AxisLabelRenderDetails details) {
String text = details.value == 0
? 'Jun 2022'
: details.value == chartData.length - 1
? 'Mar 2022'
: "";
return ChartAxisLabel(text, details.textStyle);
},
majorGridLines: const MajorGridLines(width: 0),
majorTickLines: const MajorTickLines(width: 0),
),
primaryYAxis: NumericAxis(
isVisible: false,
majorTickLines: const MajorTickLines(width: 0),
majorGridLines: const MajorGridLines(width: 0),
),
series: <ChartSeries<ChartSampleData, String>>[
ColumnSeries<ChartSampleData, String>(
dataSource: chartData,
dataLabelSettings: const DataLabelSettings(isVisible: true),
xValueMapper: (ChartSampleData sales, _) => sales.x,
yValueMapper: (ChartSampleData sales, _) => sales.y),
],
),
),
);
}
}
class ChartSampleData {
ChartSampleData(this.x, this.y);
final String? x;
final double? y;
}
final List<ChartSampleData> chartData = [
ChartSampleData('jan', 50.56),
ChartSampleData('Feb', 49.42),
ChartSampleData('Mar', 53.21),
ChartSampleData('Apr', 64.78),
ChartSampleData('May', 59.97),
];
ScreenShot:
Syncfusion Custom Axis Label
Regards,
Lokesh Palani.
Related
I'm struggling to get a graph widget to rebuild when the underlying data is changed. I have tried setState in a few different spots and can't figure it out.
Any ideas?
Data is stored in class:
class SensorReading {
SensorReading({
required this.timestamp,
required this.value,
});
DateTime timestamp;
double value;
}
class Sensor {
Sensor({
});
List<SensorReading> readings = [];
}
I'm listening to some data coming in from bluetooth and adding readings.
await c.setNotifyValue(true);
c.value.listen((value) {
setState(() {
sensor.readings.add(SensorReading(timestamp: DateTime.now(), value: value));
}
}
The main widget contains a graph widget. The graph widget will only update when I force a redraw by rotating the screen or similar.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sensor readings'),
),
body: Column(
children: <Widget>[
Expanded(
flex: 1,
child: SfCartesianChart(
primaryXAxis: CategoryAxis(),
// Chart title
title: ChartTitle(text: 'Live stream'),
// Enable legend
legend: Legend(isVisible: true),
// Enable tooltip
tooltipBehavior: TooltipBehavior(enable: false),
series: <ChartSeries<SensorReading, DateTime>>[
LineSeries<SensorReading, DateTime>(
dataSource: widget.sensor.readings,
xValueMapper: (SensorReading reading, _) => reading.timestamp,
yValueMapper: (SensorReading reading, _) => reading.value,
name: 'Temp',
// Enable data label
dataLabelSettings: DataLabelSettings(isVisible: false))
]),
),
]
)
}
how to flutter syncfusion bar chart background grid line delete?
use pub.dev // syncfusion_flutter_charts 19.4.56
https://pub.dev/packages/syncfusion_flutter_charts
< image grid line (grey color line) >
my code
return SfCartesianChart(
title: ChartTitle(text: totalTaxString, textStyle: const TextStyle(fontWeight: FontWeight.bold)),
primaryXAxis: CategoryAxis(
maximumLabelWidth: MediaQuery.of(context).size.width > 480 ? MediaQuery.of(context).size.width * 0.3 : 100,
labelStyle: const TextStyle(overflow: TextOverflow.ellipsis)
// isVisible: false
),
primaryYAxis: CategoryAxis(
isVisible: false
),
series: <BarSeries>[
BarSeries<ModelPioChartData, String>(
dataSource: listPioChartData,
pointColorMapper:(ModelPioChartData data, _) => data.color,
xValueMapper: (ModelPioChartData data, _) => data.x,
yValueMapper: (ModelPioChartData data, _) => data.y,
dataLabelMapper: (ModelPioChartData data, _) {
if(data.y.toStringAsFixed(0).length > 4) {
return "${data.y/10000}์กฐ ์";
} else {
return "${data.y.toStringAsFixed(0)}์ต ์";
}
},
dataLabelSettings: const DataLabelSettings(
isVisible: true
),
enableTooltip: true,
),
],
);
I suggest you use the majorGridLines property in the axis, you can customize the width, color, and size of the major grid line. We have attached the code snippet and UG below for your reference.
primaryXAxis:
CategoryAxis(
majorGridLines: const MajorGridLines(width: 0)
),
UG: https://help.syncfusion.com/flutter/cartesian-charts/axis-customization#grid-lines-customization
How can I set the range in x axis in charts_flutter? My data sample is like (5000, 5.0),(5001, 25.2),(5002, 100.5),(5003, 75.8).
My code is
/// Example of a simple line chart.
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SimpleLineChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
SimpleLineChart(this.seriesList, {this.animate});
/// Creates a [LineChart] with sample data and no transition.
factory SimpleLineChart.withSampleData() {
return SimpleLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
#override
Widget build(BuildContext context) {
return Container(
height: 300,
// decoration: const BoxDecoration(color: Color(0xff232d37)),
width: double.infinity,
padding:
const EdgeInsets.only(right: 18.0, left: 12.0, top: 24, bottom: 12),
child: charts.LineChart(seriesList, animate: animate),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(5000, 5.0),
LinearSales(5001, 25.2),
LinearSales(5002, 100.5),
LinearSales(5003, 75.8),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) {
return sales.year;
},
measureFn: (LinearSales sales, _) {
return sales.sales;
},
data: data,
domainLowerBoundFn: (s, _) => 5000,
domainUpperBoundFn: (s, _) => 5010,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final double sales;
LinearSales(this.year, this.sales);
}
The charts looks like
It shows a straight line but I want x axis to start at 5000 and end on 5010. I tried setting it in
domainLowerBoundFn and domainUpperBoundFn but it still starts at 0. How do I fix it?
Ref: Charts Flutter Gallery
You can set domainAxis.
How about this?
child: charts.LineChart(
seriesList,
animate: animate,
domainAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(zeroBound: false),
viewport: charts.NumericExtents(5000.0, 5005.0),
),
),
or this?
child: charts.LineChart(
seriesList,
animate: animate,
domainAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(zeroBound: false),
),
),
You can use the next code for Y-axis:
primaryMeasureAxis: charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
Full example looks like:
ScatterPlotChart(
[seriesDistorted],
animate: true,
domainAxis: const NumericAxisSpec(
tickProviderSpec: BasicNumericTickProviderSpec(
// Vertical axis every 2 ticks from 0 to 10
dataIsInWholeNumbers: true,
zeroBound: false,
desiredTickCount: 6),
),
primaryMeasureAxis: const NumericAxisSpec(
tickProviderSpec: BasicNumericTickProviderSpec(desiredTickCount: 6)),
);
I have one data type in my app which contains two lists:
class DeviceData {
List<double> frequency;
List<double> value;
DeviceData({this.frequency, this.value});
}
I don't want to separate the data types in my app into individual nums due to it being reused everywhere from displaying raw data to writing/reading from the database. I need to plot the two lists in Flutter with frequency on the y axis and value on x.
All the libraries/packages I found on pub.dev use a data model containing pure int/double values to plot the data which they then convert into a list of that data model. I want to use lists containing all of x and all of y data, not one containing one x frequency corresponding to one y value. How does one do that? What if I want to use a map to plot the data?
An example:
SfCartesianChart(
plotAreaBorderWidth: 0,
primaryXAxis: NumericAxis(
edgeLabelPlacement: EdgeLabelPlacement.shift,
interval: 2,
majorGridLines: MajorGridLines(width: 0)),
primaryYAxis: NumericAxis(
labelFormat: '{value}',
axisLine: AxisLine(width: 0),
majorTickLines: MajorTickLines(color: Colors.transparent)),
series: <LineSeries<DeviceData, List<num>>>[
LineSeries<DeviceData, List<num>>(
animationDuration: 1500,
dataSource: _result, //Contains List<DeviceData>
xValueMapper: (DeviceData data, _) => data.frequency,
yValueMapper: (DeviceData data, _) => data.value,
width: 2,
markerSettings: MarkerSettings(isVisible: true))
],
tooltipBehavior: TooltipBehavior(enable: true),
);
What am I doing wrong here?
You could easily map your current devideData into a List<SingleDeviceData>:
dataSource: List.generate(
deviceData.frequency.length,
(index) => SingleDeviceData(
frequency: deviceData.frequency[index],
value: deviceData.value[index],
),
).toList(),
Full source code for easy copy-paste:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: Scaffold(
body: MyWidget(),
),
),
);
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SfCartesianChart(
plotAreaBorderWidth: 0,
primaryXAxis: NumericAxis(
edgeLabelPlacement: EdgeLabelPlacement.shift,
interval: 2,
majorGridLines: MajorGridLines(width: 0)),
primaryYAxis: NumericAxis(
labelFormat: '{value}',
axisLine: AxisLine(width: 0),
majorTickLines: MajorTickLines(color: Colors.transparent)),
series: dataList
.map((deviceData) => LineSeries<SingleDeviceData, double>(
animationDuration: 1500,
dataSource: List.generate(
deviceData.frequency.length,
(index) => SingleDeviceData(
frequency: deviceData.frequency[index],
value: deviceData.value[index],
),
).toList(),
xValueMapper: (SingleDeviceData data, _) => data.frequency,
yValueMapper: (SingleDeviceData data, _) => data.value,
width: 2,
markerSettings: MarkerSettings(isVisible: true)))
.toList(),
tooltipBehavior: TooltipBehavior(enable: true),
);
}
}
class DeviceData {
List<double> frequency;
List<double> value;
DeviceData({this.frequency, this.value});
}
class SingleDeviceData {
final double frequency;
final double value;
SingleDeviceData({this.frequency, this.value});
}
final Random random = Random();
final List<DeviceData> dataList = List.generate(
10,
(_) => DeviceData(
frequency: List.generate(100, (_) => random.nextDouble() * 100)..sort(),
value: List.generate(100, (_) => random.nextDouble() * 10 - 3)
.fold([0], (prev, curr) => prev..add(prev.last + curr)),
),
);
I'm currently trying to restyle a design layout. I got most of it through try and error. The only part which I can't figure out are:
1.) The black axis on the left and bottom. So that only those are black
2.) The light grey axis inside. How can I apply opacity on the color or use my own color? I can only use charts.MaterialPalette and I can't figure out how to define my own.
3.) Also how to add the light grey axis in the middle. I only got the vertical ones.
4.) Is there a way to add a corner radius for the lines?
This is what it looks like right now:
This is what I want to achieve:
Here's my code so far:
/// Example of a line chart rendered with dash patterns.
class DashPatternLineChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
DashPatternLineChart(this.seriesList, {this.animate});
/// Creates a [LineChart] with sample data and no transition.
factory DashPatternLineChart.withSampleData() {
return new DashPatternLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
#override
Widget build(BuildContext context) {
return new charts.LineChart(seriesList,
animate: animate,
layoutConfig: charts.LayoutConfig(
leftMarginSpec: charts.MarginSpec.fixedPixel(0),
topMarginSpec: charts.MarginSpec.fixedPixel(75),
rightMarginSpec: charts.MarginSpec.fixedPixel(0),
bottomMarginSpec: charts.MarginSpec.fixedPixel(175)
),
flipVerticalAxis: false,
defaultInteractions: false,
domainAxis: new charts.NumericAxisSpec(
renderSpec: charts.GridlineRendererSpec(
lineStyle: charts.LineStyleSpec(
color: charts.MaterialPalette.white,
thickness: 1,
)
),
tickProviderSpec: new charts.StaticNumericTickProviderSpec(
// Create the ticks to be used the domain axis.
<charts.TickSpec<num>>[
new charts.TickSpec(0, label: '0', style: charts.TextStyleSpec(fontSize: 14)),
new charts.TickSpec(50, label: '50', style: charts.TextStyleSpec(fontSize: 14)),
new charts.TickSpec(100, label: '100', style: charts.TextStyleSpec(fontSize: 14)),
],
)),
primaryMeasureAxis: new charts.NumericAxisSpec(
renderSpec: charts.GridlineRendererSpec(
labelOffsetFromAxisPx: -20,
labelAnchor: charts.TickLabelAnchor.after,
lineStyle: charts.LineStyleSpec(
color: charts.MaterialPalette.transparent,
thickness: 0,
)
),
tickProviderSpec: new charts.StaticNumericTickProviderSpec(
// Create the ticks to be used the domain axis.
<charts.TickSpec<num>>[
new charts.TickSpec(100, label: '100%', style: charts.TextStyleSpec(fontSize: 14)),
],
)
));
}
/// Create three series with sample hard coded data.
/// Create three series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
new LinearSales(0, 100),
new LinearSales(25, 85),
new LinearSales(30, 80),
new LinearSales(45, 60),
new LinearSales(30, 40),
new LinearSales(25, 20),
new LinearSales(0, 0),
];
return [
new charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.white,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
domainUpperBoundFn: (LinearSales sales, _) => sales.domainUpper,
domainLowerBoundFn: (LinearSales sales, _) => sales.domainLower,
measureUpperBoundFn: (LinearSales sales, _) => sales.measureUpper,
measureLowerBoundFn: (LinearSales sales, _) => sales.measureLower,
strokeWidthPxFn: (_, __) => 4,
data: myFakeDesktopData,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
final int domainUpper = 100;
final int domainLower = 0;
final int measureUpper = 100;
final int measureLower = 0;
LinearSales(this.year, this.sales);
}
I don't have an answer for all your questions, but I was able to supply my own colors this way:
charts.Color.fromHex(code: "#ff0000")
or semitransparent like this:
charts.Color(r: 255, g: 0, b: 0, a: 128)