Drop `web/charts` sample (#1452)

pull/1476/head
Brett Morgan 3 years ago committed by GitHub
parent 73464650bf
commit ad1faad66b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,8 +0,0 @@
Examples of the [charts_flutter](https://pub.dev/packages/charts_flutter) package running on the web.
Original source at [github.com/google/charts](https://github.com/google/charts).
Copied from
[commit 35aeffe7c9](https://github.com/google/charts/commit/35aeffe7c96aa7d231c90fddd9766998545f1080).
With changes to run on the web.

@ -1,29 +0,0 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
avoid_print: false
prefer_single_quotes: true
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

@ -1,29 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'domain_a11y_explore_bar_chart.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.accessibility),
title: 'Screen reader enabled bar chart',
subtitle: 'Requires TalkBack or Voiceover turned on to work. '
'Bar chart with domain selection explore mode behavior.',
childBuilder: () => DomainA11yExploreBarChart.withRandomData(),
),
];
}

@ -1,216 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a bar chart with domain selection A11y behavior.
///
/// The OS screen reader (TalkBack / VoiceOver) setting must be turned on, or
/// the behavior does not do anything.
///
/// Note that the screenshot does not show any visual differences but when the
/// OS screen reader is enabled, the node that is being read out loud will be
/// surrounded by a rectangle.
///
/// When [DomainA11yExploreBehavior] is added to the chart, the chart will
/// listen for the gesture that triggers "explore mode".
/// "Explore mode" creates semantic nodes for each domain value in the chart
/// with a description (customizable, defaults to domain value) and a bounding
/// box that surrounds the domain.
///
/// These semantic node descriptions are read out loud by the OS screen reader
/// when the user taps within the bounding box, or when the user cycles through
/// the screen's elements (such as swiping left and right).
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class DomainA11yExploreBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const DomainA11yExploreBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory DomainA11yExploreBarChart.withSampleData() {
return DomainA11yExploreBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DomainA11yExploreBarChart.withRandomData() {
return DomainA11yExploreBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final mobileData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tabletData = [
// Purposely missing data to show that only measures that are available
// are vocalized.
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Mobile Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet Sales',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletData,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
/// An example of how to generate a customized vocalization for
/// [DomainA11yExploreBehavior] from a list of [SeriesDatum]s.
///
/// The list of series datums is for one domain.
///
/// This example vocalizes the domain, then for each series that has that
/// domain, it vocalizes the series display name and the measure and a
/// description of that measure.
String vocalizeDomainAndMeasures(List<charts.SeriesDatum> seriesDatums) {
final buffer = StringBuffer();
// The datum's type in this case is [OrdinalSales].
// So we can access year and sales information here.
buffer.write(seriesDatums.first.datum.year);
for (charts.SeriesDatum seriesDatum in seriesDatums) {
final series = seriesDatum.series;
final datum = seriesDatum.datum;
buffer.write(' ${series.displayName} '
'${datum.sales / 1000} thousand dollars');
}
return buffer.toString();
}
@override
Widget build(BuildContext context) {
return Semantics(
// Describe your chart
label: 'Yearly sales bar chart',
// Optionally provide a hint for the user to know how to trigger
// explore mode.
hint: 'Press and hold to enable explore',
child: charts.BarChart(
seriesList,
animate: animate,
// To prevent conflict with the select nearest behavior that uses the
// tap gesture, turn off default interactions when the user is using
// an accessibility service like TalkBack or VoiceOver to interact
// with the application.
defaultInteractions: !MediaQuery.of(context).accessibleNavigation,
behaviors: [
charts.DomainA11yExploreBehavior(
// Callback for generating the message that is vocalized.
// An example of how to use is in [vocalizeDomainAndMeasures].
// If none is set, the default only vocalizes the domain value.
vocalizationCallback: vocalizeDomainAndMeasures,
// The following settings are optional, but shown here for
// demonstration purchases.
// [exploreModeTrigger] Default is press and hold, can be
// changed to tap.
exploreModeTrigger: charts.ExploreModeTrigger.pressHold,
// [exploreModeEnabledAnnouncement] Optionally notify the OS
// when explore mode is enabled.
exploreModeEnabledAnnouncement: 'Explore mode enabled',
// [exploreModeDisabledAnnouncement] Optionally notify the OS
// when explore mode is disabled.
exploreModeDisabledAnnouncement: 'Explore mode disabled',
// [minimumWidth] Default and minimum is 1.0. This is the
// minimum width of the screen reader bounding box. The bounding
// box width is calculated based on the domain axis step size.
// Minimum width will be used if the step size is smaller.
minimumWidth: 1.0,
),
// Optionally include domain highlighter as a behavior.
// This behavior is included in this example to show that when an
// a11y node has focus, the chart's internal selection model is
// also updated.
charts.DomainHighlighter(charts.SelectionModelType.info),
],
));
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final mobileData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletData = [
// Purposely missing data to show that only measures that are available
// are vocalized.
OrdinalSales('2016', 25),
OrdinalSales('2017', 50),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Mobile Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet Sales',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletData,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,44 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
/// A particular configuration of the app.
class AppConfig {
final String appName;
final String appLink;
final ThemeData theme;
final bool showPerformanceOverlay;
AppConfig({
required this.appName,
required this.appLink,
required this.theme,
required this.showPerformanceOverlay,
});
}
/// The default configuration of the app.
AppConfig get defaultConfig {
return AppConfig(
appName: 'Charts Gallery',
appLink: '',
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.lightBlue,
),
showPerformanceOverlay: false,
);
}

@ -1,136 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'bar_secondary_axis.dart';
import 'bar_secondary_axis_only.dart';
import 'custom_axis_tick_formatters.dart';
import 'custom_font_size_and_color.dart';
import 'custom_measure_tick_count.dart';
import 'gridline_dash_pattern.dart';
import 'hidden_ticks_and_labels_axis.dart';
import 'horizontal_bar_secondary_axis.dart';
import 'integer_only_measure_axis.dart';
import 'line_disjoint_axis.dart';
import 'measure_axis_label_alignment.dart';
import 'numeric_initial_viewport.dart';
import 'nonzero_bound_measure_axis.dart';
import 'ordinal_initial_viewport.dart';
import 'short_tick_length_axis.dart';
import 'statically_provided_ticks.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Bar chart with Secondary Measure Axis',
subtitle: 'Bar chart with a series using a secondary measure axis',
childBuilder: () => BarChartWithSecondaryAxis.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Bar chart with Secondary Measure Axis only',
subtitle: 'Bar chart with both series using secondary measure axis',
childBuilder: () => BarChartWithSecondaryAxisOnly.withRandomData(),
),
GalleryScaffold(
listTileIcon: Transform.rotate(
angle: 1.5708, child: const Icon(Icons.insert_chart)),
title: 'Horizontal bar chart with Secondary Measure Axis',
subtitle:
'Horizontal Bar chart with a series using secondary measure axis',
childBuilder: () => HorizontalBarChartWithSecondaryAxis.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Short Ticks Axis',
subtitle: 'Bar chart with the primary measure axis having short ticks',
childBuilder: () => ShortTickLengthAxis.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Custom Axis Fonts',
subtitle: 'Bar chart with custom axis font size and color',
childBuilder: () => CustomFontSizeAndColor.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Label Alignment Axis',
subtitle: 'Bar chart with custom measure axis label alignments',
childBuilder: () => MeasureAxisLabelAlignment.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'No Axis',
subtitle: 'Bar chart with only the axis line drawn',
childBuilder: () => HiddenTicksAndLabelsAxis.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Statically Provided Ticks',
subtitle: 'Bar chart with statically provided ticks',
childBuilder: () => StaticallyProvidedTicks.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Custom Formatter',
subtitle: 'Timeseries with custom domain and measure tick formatters',
childBuilder: () => CustomAxisTickFormatters.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Custom Tick Count',
subtitle: 'Timeseries with custom measure axis tick count',
childBuilder: () => CustomMeasureTickCount.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Integer Measure Ticks',
subtitle: 'Timeseries with only whole number measure axis ticks',
childBuilder: () => IntegerOnlyMeasureAxis.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Non-zero bound Axis',
subtitle: 'Timeseries with measure axis that does not include zero',
childBuilder: () => NonzeroBoundMeasureAxis.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Ordinal axis with initial viewport',
subtitle: 'Single series with initial viewport',
childBuilder: () => OrdinalInitialViewport.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Numeric axis with initial viewport',
subtitle: 'Initial viewport is set to a subset of the data',
childBuilder: () => NumericInitialViewport.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Gridline dash pattern',
subtitle: 'Timeseries with measure gridlines that have a dash pattern',
childBuilder: () => GridlineDashPattern.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Disjoint Measure Axes',
subtitle: 'Line chart with disjoint measure axes',
childBuilder: () => DisjointMeasureAxisLineChart.withRandomData(),
),
];
}

@ -1,159 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of using a primary and secondary axis (left & right respectively)
/// for a set of grouped bars. This is useful for comparing Series that have
/// different units (revenue vs clicks by region), or different magnitudes (2017
/// revenue vs 1/1/2017 revenue by region).
///
/// The first series plots using the primary axis to position its measure
/// values (bar height). This is the default axis used if the measureAxisId is
/// not set.
///
/// The second series plots using the secondary axis due to the measureAxisId of
/// secondaryMeasureAxisId.
///
/// Note: primary and secondary may flip left and right positioning when
/// RTL.flipAxisLocations is set.
class BarChartWithSecondaryAxis extends StatelessWidget {
static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const BarChartWithSecondaryAxis(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory BarChartWithSecondaryAxis.withSampleData() {
return BarChartWithSecondaryAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory BarChartWithSecondaryAxis.withRandomData() {
return BarChartWithSecondaryAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
final losAngelesSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Los Angeles Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: losAngelesSalesData,
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
// All series that have this set will use the secondary measure axis.
// All other series will use the primary measure axis.
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// It is important when using both primary and secondary axes to choose
// the same number of ticks for both sides to get the gridlines to line
// up.
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
secondaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
final losAngelesSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Los Angeles Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: losAngelesSalesData,
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
// All series that have this set will use the secondary measure axis.
// All other series will use the primary measure axis.
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,115 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of using only a secondary axis (on the right) for a set of grouped
/// bars.
///
/// Both series plots using the secondary axis due to the measureAxisId of
/// secondaryMeasureAxisId.
///
/// Note: secondary may flip left and right positioning when
/// RTL.flipAxisLocations is set.
class BarChartWithSecondaryAxisOnly extends StatelessWidget {
static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const BarChartWithSecondaryAxisOnly(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory BarChartWithSecondaryAxisOnly.withSampleData() {
return BarChartWithSecondaryAxisOnly(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory BarChartWithSecondaryAxisOnly.withRandomData() {
return BarChartWithSecondaryAxisOnly(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
)
// Set series to use the secondary measure axis.
..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 500),
OrdinalSales('2015', 2500),
OrdinalSales('2016', 1000),
OrdinalSales('2017', 7500),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
)
// Set series to use the secondary measure axis.
..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,145 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of timeseries chart with custom measure and domain formatters.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class CustomAxisTickFormatters extends StatelessWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const CustomAxisTickFormatters(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory CustomAxisTickFormatters.withSampleData() {
return CustomAxisTickFormatters(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory CustomAxisTickFormatters.withRandomData() {
return CustomAxisTickFormatters(_createRandomData());
}
/// Create random data.
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
final random = Random();
final data = [
MyRow(DateTime(2017, 9, 25), random.nextInt(100)),
MyRow(DateTime(2017, 9, 26), random.nextInt(100)),
MyRow(DateTime(2017, 9, 27), random.nextInt(100)),
MyRow(DateTime(2017, 9, 28), random.nextInt(100)),
MyRow(DateTime(2017, 9, 29), random.nextInt(100)),
MyRow(DateTime(2017, 9, 30), random.nextInt(100)),
MyRow(DateTime(2017, 10, 01), random.nextInt(100)),
MyRow(DateTime(2017, 10, 02), random.nextInt(100)),
MyRow(DateTime(2017, 10, 03), random.nextInt(100)),
MyRow(DateTime(2017, 10, 04), random.nextInt(100)),
MyRow(DateTime(2017, 10, 05), random.nextInt(100)),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
/// Formatter for numeric ticks using [NumberFormat] to format into currency
///
/// This is what is used in the [NumericAxisSpec] below.
final simpleCurrencyFormatter =
charts.BasicNumericTickFormatterSpec.fromNumberFormat(
NumberFormat.compactSimpleCurrency());
/// Formatter for numeric ticks that uses the callback provided.
///
/// Use this formatter if you need to format values that [NumberFormat]
/// cannot provide.
///
/// To see this formatter, change [NumericAxisSpec] to use this formatter.
// final customTickFormatter =
// charts.BasicNumericTickFormatterSpec((num value) => 'MyValue: $value');
return charts.TimeSeriesChart(seriesList,
animate: animate,
// Sets up a currency formatter for the measure axis.
primaryMeasureAxis:
charts.NumericAxisSpec(tickFormatterSpec: simpleCurrencyFormatter),
/// Customizes the date tick formatter. It will print the day of month
/// as the default format, but include the month and year if it
/// transitions to a new month.
///
/// minute, hour, day, month, and year are all provided by default and
/// you can override them following this pattern.
domainAxis: const charts.DateTimeAxisSpec(
tickFormatterSpec: charts.AutoDateTimeTickFormatterSpec(
day: charts.TimeFormatterSpec(
format: 'd', transitionFormat: 'MM/dd/yyyy'))));
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
MyRow(DateTime(2017, 9, 25), 6),
MyRow(DateTime(2017, 9, 26), 8),
MyRow(DateTime(2017, 9, 27), 6),
MyRow(DateTime(2017, 9, 28), 9),
MyRow(DateTime(2017, 9, 29), 11),
MyRow(DateTime(2017, 9, 30), 15),
MyRow(DateTime(2017, 10, 01), 25),
MyRow(DateTime(2017, 10, 02), 33),
MyRow(DateTime(2017, 10, 03), 27),
MyRow(DateTime(2017, 10, 04), 31),
MyRow(DateTime(2017, 10, 05), 23),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int cost;
MyRow(this.timeStamp, this.cost);
}

@ -1,137 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Custom Font Style Example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of using a custom primary measure and domain axis replacing the
/// renderSpec with one with a custom font size and a custom color.
///
/// There are many axis styling options in the SmallTickRenderer allowing you
/// to customize the font, tick lengths, and offsets.
class CustomFontSizeAndColor extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const CustomFontSizeAndColor(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory CustomFontSizeAndColor.withSampleData() {
return CustomFontSizeAndColor(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory CustomFontSizeAndColor.withRandomData() {
return CustomFontSizeAndColor(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
/// Assign a custom style for the domain axis.
///
/// This is an OrdinalAxisSpec to match up with BarChart's default
/// ordinal domain axis (use NumericAxisSpec or DateTimeAxisSpec for
/// other charts).
domainAxis: const charts.OrdinalAxisSpec(
renderSpec: charts.SmallTickRendererSpec(
// Tick and Label styling here.
labelStyle: charts.TextStyleSpec(
fontSize: 18, // size in Pts.
color: charts.MaterialPalette.black),
// Change the line colors to match text color.
lineStyle:
charts.LineStyleSpec(color: charts.MaterialPalette.black))),
/// Assign a custom style for the measure axis.
primaryMeasureAxis: const charts.NumericAxisSpec(
renderSpec: charts.GridlineRendererSpec(
// Tick and Label styling here.
labelStyle: charts.TextStyleSpec(
fontSize: 18, // size in Pts.
color: charts.MaterialPalette.black),
// Change the line colors to match text color.
lineStyle:
charts.LineStyleSpec(color: charts.MaterialPalette.black))),
);
}
/// Create series list with single series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,123 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of timeseries chart with a custom number of ticks
///
/// The tick count can be set by setting the [desiredMinTickCount] and
/// [desiredMaxTickCount] for automatically adjusted tick counts (based on
/// how 'nice' the ticks are) or [desiredTickCount] for a fixed tick count.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class CustomMeasureTickCount extends StatelessWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const CustomMeasureTickCount(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory CustomMeasureTickCount.withSampleData() {
return CustomMeasureTickCount(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory CustomMeasureTickCount.withRandomData() {
return CustomMeasureTickCount(_createRandomData());
}
/// Create random data.
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
final random = Random();
final data = [
MyRow(DateTime(2017, 9, 25), random.nextInt(100)),
MyRow(DateTime(2017, 9, 26), random.nextInt(100)),
MyRow(DateTime(2017, 9, 27), random.nextInt(100)),
MyRow(DateTime(2017, 9, 28), random.nextInt(100)),
MyRow(DateTime(2017, 9, 29), random.nextInt(100)),
MyRow(DateTime(2017, 9, 30), random.nextInt(100)),
MyRow(DateTime(2017, 10, 01), random.nextInt(100)),
MyRow(DateTime(2017, 10, 02), random.nextInt(100)),
MyRow(DateTime(2017, 10, 03), random.nextInt(100)),
MyRow(DateTime(2017, 10, 04), random.nextInt(100)),
MyRow(DateTime(2017, 10, 05), random.nextInt(100)),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.TimeSeriesChart(seriesList,
animate: animate,
/// Customize the measure axis to have 2 ticks,
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(desiredTickCount: 2)));
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
MyRow(DateTime(2017, 9, 25), 6),
MyRow(DateTime(2017, 9, 26), 8),
MyRow(DateTime(2017, 9, 27), 6),
MyRow(DateTime(2017, 9, 28), 9),
MyRow(DateTime(2017, 9, 29), 11),
MyRow(DateTime(2017, 9, 30), 15),
MyRow(DateTime(2017, 10, 01), 25),
MyRow(DateTime(2017, 10, 02), 33),
MyRow(DateTime(2017, 10, 03), 27),
MyRow(DateTime(2017, 10, 04), 31),
MyRow(DateTime(2017, 10, 05), 23),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int cost;
MyRow(this.timeStamp, this.cost);
}

@ -1,115 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of flipping the vertical measure axis direction so that larger
/// values render downward instead of the usual rendering up.
///
/// flipVerticalAxis, when set, flips the vertical axis from its default
/// direction.
///
/// Note: primary and secondary may flip left and right positioning when
/// RTL.flipAxisLocations is set.
class FlippedVerticalAxis extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const FlippedVerticalAxis(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory FlippedVerticalAxis.withSampleData() {
return FlippedVerticalAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory FlippedVerticalAxis.withRandomData() {
return FlippedVerticalAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<RunnerRank, String>> _createRandomData() {
final random = Random();
const runners = ['Smith', 'Jones', 'Brown', 'Doe'];
// Randomly assign runners, but leave the order of the places.
final raceData = [
RunnerRank(runners.removeAt(random.nextInt(runners.length)), 1),
RunnerRank(runners.removeAt(random.nextInt(runners.length)), 2),
RunnerRank(runners.removeAt(random.nextInt(runners.length)), 3),
RunnerRank(runners.removeAt(random.nextInt(runners.length)), 4),
];
return [
charts.Series<RunnerRank, String>(
id: 'Race Results',
domainFn: (RunnerRank row, _) => row.name,
measureFn: (RunnerRank row, _) => row.place,
data: raceData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
// Known Issue, the bar chart cannot render negative direction bars at this
// time so the result is an empty chart.
// TODO: Remove this comment
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
flipVerticalAxis: true,
);
}
/// Create series list with multiple series
static List<charts.Series<RunnerRank, String>> _createSampleData() {
final raceData = [
RunnerRank('Smith', 1),
RunnerRank('Jones', 2),
RunnerRank('Brown', 3),
RunnerRank('Doe', 4),
];
return [
charts.Series<RunnerRank, String>(
id: 'Race Results',
domainFn: (RunnerRank row, _) => row.name,
measureFn: (RunnerRank row, _) => row.place,
data: raceData),
];
}
}
/// Datum/Row for the chart.
class RunnerRank {
final String name;
final int place;
RunnerRank(this.name, this.place);
}

@ -1,121 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of timeseries chart with gridlines that have a dash pattern.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class GridlineDashPattern extends StatelessWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const GridlineDashPattern(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory GridlineDashPattern.withSampleData() {
return GridlineDashPattern(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GridlineDashPattern.withRandomData() {
return GridlineDashPattern(_createRandomData());
}
/// Create random data.
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
final random = Random();
final data = [
MyRow(DateTime(2017, 9, 25), random.nextInt(100)),
MyRow(DateTime(2017, 9, 26), random.nextInt(100)),
MyRow(DateTime(2017, 9, 27), random.nextInt(100)),
MyRow(DateTime(2017, 9, 28), random.nextInt(100)),
MyRow(DateTime(2017, 9, 29), random.nextInt(100)),
MyRow(DateTime(2017, 9, 30), random.nextInt(100)),
MyRow(DateTime(2017, 10, 01), random.nextInt(100)),
MyRow(DateTime(2017, 10, 02), random.nextInt(100)),
MyRow(DateTime(2017, 10, 03), random.nextInt(100)),
MyRow(DateTime(2017, 10, 04), random.nextInt(100)),
MyRow(DateTime(2017, 10, 05), random.nextInt(100)),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.TimeSeriesChart(seriesList,
animate: animate,
/// Customize the gridlines to use a dash pattern.
primaryMeasureAxis: const charts.NumericAxisSpec(
renderSpec: charts.GridlineRendererSpec(
lineStyle: charts.LineStyleSpec(
dashPattern: [4, 4],
))));
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
MyRow(DateTime(2017, 9, 25), 6),
MyRow(DateTime(2017, 9, 26), 8),
MyRow(DateTime(2017, 9, 27), 6),
MyRow(DateTime(2017, 9, 28), 9),
MyRow(DateTime(2017, 9, 29), 11),
MyRow(DateTime(2017, 9, 30), 15),
MyRow(DateTime(2017, 10, 01), 25),
MyRow(DateTime(2017, 10, 02), 33),
MyRow(DateTime(2017, 10, 03), 27),
MyRow(DateTime(2017, 10, 04), 31),
MyRow(DateTime(2017, 10, 05), 23),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int cost;
MyRow(this.timeStamp, this.cost);
}

@ -1,119 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// No Axis Example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of hiding both axis.
class HiddenTicksAndLabelsAxis extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const HiddenTicksAndLabelsAxis(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory HiddenTicksAndLabelsAxis.withSampleData() {
return HiddenTicksAndLabelsAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory HiddenTicksAndLabelsAxis.withRandomData() {
return HiddenTicksAndLabelsAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
/// Assign a custom style for the measure axis.
///
/// The NoneRenderSpec can still draw an axis line with
/// showAxisLine=true.
primaryMeasureAxis:
const charts.NumericAxisSpec(renderSpec: charts.NoneRenderSpec()),
/// This is an OrdinalAxisSpec to match up with BarChart's default
/// ordinal domain axis (use NumericAxisSpec or DateTimeAxisSpec for
/// other charts).
domainAxis: const charts.OrdinalAxisSpec(
// Make sure that we draw the domain axis line.
showAxisLine: true,
// But don't draw anything else.
renderSpec: charts.NoneRenderSpec()),
);
}
/// Create series list with single series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,162 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of using a primary and secondary axis (left & right respectively)
/// for a set of grouped bars. This is useful for comparing Series that have
/// different units (revenue vs clicks by region), or different magnitudes (2017
/// revenue vs 1/1/2017 revenue by region).
///
/// The first series plots using the primary axis to position its measure
/// values (bar height). This is the default axis used if the measureAxisId is
/// not set.
///
/// The second series plots using the secondary axis due to the measureAxisId of
/// secondaryMeasureAxisId.
///
/// Note: primary and secondary may flip left and right positioning when
/// RTL.flipAxisLocations is set.
class HorizontalBarChartWithSecondaryAxis extends StatelessWidget {
static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const HorizontalBarChartWithSecondaryAxis(this.seriesList,
{this.animate, Key? key})
: super(key: key);
factory HorizontalBarChartWithSecondaryAxis.withSampleData() {
return HorizontalBarChartWithSecondaryAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory HorizontalBarChartWithSecondaryAxis.withRandomData() {
return HorizontalBarChartWithSecondaryAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
final losAngelesSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Los Angeles Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: losAngelesSalesData,
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
// All series that have this set will use the secondary measure axis.
// All other series will use the primary measure axis.
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// For horizontal bar charts, set the [vertical] flag to false.
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
vertical: false,
// It is important when using both primary and secondary axes to choose
// the same number of ticks for both sides to get the gridlines to line
// up.
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
secondaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
final losAngelesSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Los Angeles Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: losAngelesSalesData,
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
// All series that have this set will use the secondary measure axis.
// All other series will use the primary measure axis.
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,130 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of timeseries chart forcing the measure axis to have whole number
/// ticks. This is useful if the measure units don't make sense to present as
/// fractional.
///
/// This is done by customizing the measure axis and setting
/// [dataIsInWholeNumbers] on the tick provider.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class IntegerOnlyMeasureAxis extends StatelessWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const IntegerOnlyMeasureAxis(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory IntegerOnlyMeasureAxis.withSampleData() {
return IntegerOnlyMeasureAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory IntegerOnlyMeasureAxis.withRandomData() {
return IntegerOnlyMeasureAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
final random = Random();
final data = [
MyRow(DateTime(2017, 9, 25), random.nextDouble().round()),
MyRow(DateTime(2017, 9, 26), random.nextDouble().round()),
MyRow(DateTime(2017, 9, 27), random.nextDouble().round()),
MyRow(DateTime(2017, 9, 28), random.nextDouble().round()),
MyRow(DateTime(2017, 9, 29), random.nextDouble().round()),
MyRow(DateTime(2017, 9, 30), random.nextDouble().round()),
MyRow(DateTime(2017, 10, 01), random.nextDouble().round()),
MyRow(DateTime(2017, 10, 02), random.nextDouble().round()),
MyRow(DateTime(2017, 10, 03), random.nextDouble().round()),
MyRow(DateTime(2017, 10, 04), random.nextDouble().round()),
MyRow(DateTime(2017, 10, 05), random.nextDouble().round()),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Headcount',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.headcount,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.TimeSeriesChart(
seriesList,
animate: animate,
// Provides a custom axis ensuring that the ticks are in whole numbers.
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec: charts.BasicNumericTickProviderSpec(
// Make sure we don't have values less than 1 as ticks
// (ie: counts).
dataIsInWholeNumbers: true,
// Fixed tick count to highlight the integer only behavior
// generating ticks [0, 1, 2, 3, 4].
desiredTickCount: 5)),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
MyRow(DateTime(2017, 9, 25), 0),
MyRow(DateTime(2017, 9, 26), 0),
MyRow(DateTime(2017, 9, 27), 0),
MyRow(DateTime(2017, 9, 28), 0),
MyRow(DateTime(2017, 9, 29), 0),
MyRow(DateTime(2017, 9, 30), 0),
MyRow(DateTime(2017, 10, 01), 1),
MyRow(DateTime(2017, 10, 02), 1),
MyRow(DateTime(2017, 10, 03), 1),
MyRow(DateTime(2017, 10, 04), 1),
MyRow(DateTime(2017, 10, 05), 1),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Headcount',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.headcount,
data: data,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int headcount;
MyRow(this.timeStamp, this.headcount);
}

@ -1,270 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of using disjoint measure axes to render 4 series of lines with
/// separate scales. The general use case for this type of chart is to show
/// differences in the trends of the data, without comparing their absolute
/// values.
///
/// Disjoint measure axes will be used to scale the series associated with them,
/// but they will not render any tick elements on either side of the chart.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:collection' show LinkedHashMap;
import 'dart:math';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class DisjointMeasureAxisLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const DisjointMeasureAxisLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory DisjointMeasureAxisLineChart.withSampleData() {
return DisjointMeasureAxisLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DisjointMeasureAxisLineChart.withRandomData() {
return DisjointMeasureAxisLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearClicks, num>> _createRandomData() {
final random = Random();
// The first three series contain similar data with different magnitudes.
// This demonstrates the ability to graph the trends in each series relative
// to each other, without the largest magnitude series compressing the
// smallest.
final myFakeDesktopData = [
LinearClicks(0, clickCount: random.nextInt(100)),
LinearClicks(1, clickCount: random.nextInt(100)),
LinearClicks(2, clickCount: random.nextInt(100)),
LinearClicks(3, clickCount: random.nextInt(100)),
];
final myFakeTabletData = [
LinearClicks(0, clickCount: random.nextInt(100) * 100),
LinearClicks(1, clickCount: random.nextInt(100) * 100),
LinearClicks(2, clickCount: random.nextInt(100) * 100),
LinearClicks(3, clickCount: random.nextInt(100) * 100),
];
final myFakeMobileData = [
LinearClicks(0, clickCount: random.nextInt(100) * 1000),
LinearClicks(1, clickCount: random.nextInt(100) * 1000),
LinearClicks(2, clickCount: random.nextInt(100) * 1000),
LinearClicks(3, clickCount: random.nextInt(100) * 1000),
];
// The fourth series renders with decimal values, representing a very
// different sort ratio-based data. If this was on the same axis as any of
// the other series, it would be squashed near zero.
final myFakeClickRateData = [
LinearClicks(0, clickRate: .25),
LinearClicks(1, clickRate: .65),
LinearClicks(2, clickRate: .50),
LinearClicks(3, clickRate: .30),
];
return [
// We render an empty series on the primary measure axis to ensure that
// the axis itself gets rendered. This helps us draw the gridlines on the
// chart.
charts.Series<LinearClicks, int>(
id: 'Fake Series',
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: []),
charts.Series<LinearClicks, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeDesktopData,
)
// Set the 'Desktop' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 1'),
charts.Series<LinearClicks, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeTabletData,
)
// Set the 'Tablet' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 2'),
charts.Series<LinearClicks, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeMobileData,
)
// Set the 'Mobile' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 3'),
charts.Series<LinearClicks, int>(
id: 'Click Rate',
colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeClickRateData,
)
// Set the 'Click Rate' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 4'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
animate: animate,
// Configure a primary measure axis that will render gridlines across
// the chart. This axis uses fake ticks with no labels to ensure that we
// get 5 grid lines.
//
// We do this because disjoint measure axes do not draw any tick
// elements on the chart.
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec: charts.StaticNumericTickProviderSpec(
// Create the ticks to be used the domain axis.
[
charts.TickSpec(0, label: ''),
charts.TickSpec(1, label: ''),
charts.TickSpec(2, label: ''),
charts.TickSpec(3, label: ''),
charts.TickSpec(4, label: ''),
],
)),
// Create one disjoint measure axis per series on the chart.
//
// Disjoint measure axes will be used to scale the rendered data,
// without drawing any tick elements on either side of the chart.
disjointMeasureAxes:
LinkedHashMap<String, charts.NumericAxisSpec>.from({
'axis 1': const charts.NumericAxisSpec(),
'axis 2': const charts.NumericAxisSpec(),
'axis 3': const charts.NumericAxisSpec(),
'axis 4': const charts.NumericAxisSpec(),
}));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearClicks, int>> _createSampleData() {
// The first three series contain similar data with different magnitudes.
// This demonstrates the ability to graph the trends in each series relative
// to each other, without the largest magnitude series compressing the
// smallest.
final myFakeDesktopData = [
LinearClicks(0, clickCount: 25),
LinearClicks(1, clickCount: 125),
LinearClicks(2, clickCount: 920),
LinearClicks(3, clickCount: 375),
];
final myFakeTabletData = [
LinearClicks(0, clickCount: 375),
LinearClicks(1, clickCount: 1850),
LinearClicks(2, clickCount: 9700),
LinearClicks(3, clickCount: 5000),
];
final myFakeMobileData = [
LinearClicks(0, clickCount: 5000),
LinearClicks(1, clickCount: 25000),
LinearClicks(2, clickCount: 100000),
LinearClicks(3, clickCount: 75000),
];
// The fourth series renders with decimal values, representing a very
// different sort ratio-based data. If this was on the same axis as any of
// the other series, it would be squashed near zero.
final myFakeClickRateData = [
LinearClicks(0, clickRate: .25),
LinearClicks(1, clickRate: .65),
LinearClicks(2, clickRate: .50),
LinearClicks(3, clickRate: .30),
];
return [
// We render an empty series on the primary measure axis to ensure that
// the axis itself gets rendered. This helps us draw the gridlines on the
// chart.
charts.Series<LinearClicks, int>(
id: 'Fake Series',
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: []),
charts.Series<LinearClicks, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeDesktopData,
)
// Set the 'Desktop' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 1'),
charts.Series<LinearClicks, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeTabletData,
)
// Set the 'Tablet' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 2'),
charts.Series<LinearClicks, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
data: myFakeMobileData,
)
// Set the 'Mobile' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 3'),
charts.Series<LinearClicks, int>(
id: 'Click Rate',
colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault,
domainFn: (LinearClicks clickCount, _) => clickCount.year,
measureFn: (LinearClicks clickCount, _) => clickCount.clickRate,
data: myFakeClickRateData,
)
// Set the 'Click Rate' series to use a disjoint axis.
..setAttribute(charts.measureAxisIdKey, 'axis 4'),
];
}
}
/// Sample linear data type.
class LinearClicks {
final int year;
final int? clickCount;
final double? clickRate;
LinearClicks(this.year, {this.clickCount, this.clickRate});
}

@ -1,123 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Custom Tick Label Alignment Example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of using a custom primary measure replacing the renderSpec with one
/// that aligns the text under the tick and left justifies.
class MeasureAxisLabelAlignment extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const MeasureAxisLabelAlignment(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory MeasureAxisLabelAlignment.withSampleData() {
return MeasureAxisLabelAlignment(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory MeasureAxisLabelAlignment.withRandomData() {
return MeasureAxisLabelAlignment(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
/// Customize the primary measure axis using a small tick renderer.
/// Use String instead of num for ordinal domain axis
/// (typically bar charts).
primaryMeasureAxis: const charts.NumericAxisSpec(
renderSpec: charts.GridlineRendererSpec(
// Display the measure axis labels below the gridline.
//
// 'Before' & 'after' follow the axis value direction.
// Vertical axes draw 'before' below & 'after' above the tick.
// Horizontal axes draw 'before' left & 'after' right the tick.
labelAnchor: charts.TickLabelAnchor.before,
// Left justify the text in the axis.
//
// Note: outside means that the secondary measure axis would right
// justify.
labelJustification: charts.TickLabelJustification.outside,
)),
);
}
/// Create series list with single series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,120 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of timeseries chart that has a measure axis that does NOT include
/// zero. It starts at 100 and goes to 140.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class NonzeroBoundMeasureAxis extends StatelessWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const NonzeroBoundMeasureAxis(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory NonzeroBoundMeasureAxis.withSampleData() {
return NonzeroBoundMeasureAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory NonzeroBoundMeasureAxis.withRandomData() {
return NonzeroBoundMeasureAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
final random = Random();
final data = [
MyRow(DateTime(2017, 9, 25), random.nextInt(100) + 100),
MyRow(DateTime(2017, 9, 26), random.nextInt(100) + 100),
MyRow(DateTime(2017, 9, 27), random.nextInt(100) + 100),
MyRow(DateTime(2017, 9, 28), random.nextInt(100) + 100),
MyRow(DateTime(2017, 9, 29), random.nextInt(100) + 100),
MyRow(DateTime(2017, 9, 30), random.nextInt(100) + 100),
MyRow(DateTime(2017, 10, 01), random.nextInt(100) + 100),
MyRow(DateTime(2017, 10, 02), random.nextInt(100) + 100),
MyRow(DateTime(2017, 10, 03), random.nextInt(100) + 100),
MyRow(DateTime(2017, 10, 04), random.nextInt(100) + 100),
MyRow(DateTime(2017, 10, 05), random.nextInt(100) + 100),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Headcount',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.headcount,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.TimeSeriesChart(seriesList,
animate: animate,
// Provide a tickProviderSpec which does NOT require that zero is
// included.
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(zeroBound: false)));
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
MyRow(DateTime(2017, 9, 25), 106),
MyRow(DateTime(2017, 9, 26), 108),
MyRow(DateTime(2017, 9, 27), 106),
MyRow(DateTime(2017, 9, 28), 109),
MyRow(DateTime(2017, 9, 29), 111),
MyRow(DateTime(2017, 9, 30), 115),
MyRow(DateTime(2017, 10, 01), 125),
MyRow(DateTime(2017, 10, 02), 133),
MyRow(DateTime(2017, 10, 03), 127),
MyRow(DateTime(2017, 10, 04), 131),
MyRow(DateTime(2017, 10, 05), 123),
];
return [
charts.Series<MyRow, DateTime>(
id: 'Headcount',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.headcount,
data: data,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int headcount;
MyRow(this.timeStamp, this.headcount);
}

@ -1,134 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of setting an initial viewport for ordinal axis.
///
/// This allows for specifying the specific range of data to show that differs
/// from what was provided in the series list.
///
/// In this example, the series list has numeric data from 0 to 10, but we
/// want to show from 3 to 7.
/// We can do this by specifying an [NumericExtents] in [NumericAxisSpec].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class NumericInitialViewport extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const NumericInitialViewport(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory NumericInitialViewport.withSampleData() {
return NumericInitialViewport(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory NumericInitialViewport.withRandomData() {
return NumericInitialViewport(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
LinearSales(4, random.nextInt(100)),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
LinearSales(7, random.nextInt(100)),
LinearSales(8, random.nextInt(100)),
LinearSales(9, random.nextInt(100)),
LinearSales(10, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(
seriesList,
animate: animate,
domainAxis: const charts.NumericAxisSpec(
// Set the initial viewport by providing a new AxisSpec with the
// desired viewport, in NumericExtents.
viewport: charts.NumericExtents(3.0, 7.0)),
// Optionally add a pan or pan and zoom behavior.
// If pan/zoom is not added, the viewport specified remains the viewport.
behaviors: [charts.PanAndZoomBehavior()],
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
LinearSales(4, 55),
LinearSales(5, 66),
LinearSales(6, 110),
LinearSales(7, 70),
LinearSales(8, 20),
LinearSales(9, 25),
LinearSales(10, 45),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,146 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of setting an initial viewport for ordinal axis.
///
/// This allows for specifying the specific range of data to show that differs
/// from what was provided in the series list.
///
/// In this example, the series list has ordinal data from year 2014 to 2030,
/// but we want to show starting at 2018 and we only want to show 4 values.
/// We can do this by specifying an [OrdinalViewport] in [OrdinalAxisSpec].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class OrdinalInitialViewport extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const OrdinalInitialViewport(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory OrdinalInitialViewport.withSampleData() {
return OrdinalInitialViewport(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory OrdinalInitialViewport.withRandomData() {
return OrdinalInitialViewport(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
OrdinalSales('2018', random.nextInt(100)),
OrdinalSales('2019', random.nextInt(100)),
OrdinalSales('2020', random.nextInt(100)),
OrdinalSales('2021', random.nextInt(100)),
OrdinalSales('2022', random.nextInt(100)),
OrdinalSales('2023', random.nextInt(100)),
OrdinalSales('2024', random.nextInt(100)),
OrdinalSales('2025', random.nextInt(100)),
OrdinalSales('2026', random.nextInt(100)),
OrdinalSales('2027', random.nextInt(100)),
OrdinalSales('2028', random.nextInt(100)),
OrdinalSales('2029', random.nextInt(100)),
OrdinalSales('2030', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
// Set the initial viewport by providing a new AxisSpec with the
// desired viewport: a starting domain and the data size.
domainAxis:
charts.OrdinalAxisSpec(viewport: charts.OrdinalViewport('2018', 4)),
// Optionally add a pan or pan and zoom behavior.
// If pan/zoom is not added, the viewport specified remains the viewport.
behaviors: [charts.PanAndZoomBehavior()],
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
OrdinalSales('2018', 33),
OrdinalSales('2019', 80),
OrdinalSales('2020', 21),
OrdinalSales('2021', 77),
OrdinalSales('2022', 8),
OrdinalSales('2023', 12),
OrdinalSales('2024', 42),
OrdinalSales('2025', 70),
OrdinalSales('2026', 77),
OrdinalSales('2027', 55),
OrdinalSales('2028', 19),
OrdinalSales('2029', 66),
OrdinalSales('2030', 27),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,116 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Custom Tick Style Example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of using a custom primary measure axis replacing the default
/// gridline rendering with a short tick rendering. It also turns on the axis
/// line so that the ticks have something to line up against.
///
/// There are many axis styling options in the SmallTickRenderer allowing you
/// to customize the font, tick lengths, and offsets.
class ShortTickLengthAxis extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const ShortTickLengthAxis(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory ShortTickLengthAxis.withSampleData() {
return ShortTickLengthAxis(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory ShortTickLengthAxis.withRandomData() {
return ShortTickLengthAxis(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
/// Customize the primary measure axis using a small tick renderer.
/// Note: use String instead of num for ordinal domain axis
/// (typically bar charts).
primaryMeasureAxis: const charts.NumericAxisSpec(
renderSpec: charts.SmallTickRendererSpec(
// Tick and Label styling here.
)),
);
}
/// Create series list with single series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,134 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of axis using statically provided ticks.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of specifying a custom set of ticks to be used on the domain axis.
///
/// Specifying custom set of ticks allows specifying exactly what ticks are
/// used in the axis. Each tick is also allowed to have a different style set.
///
/// For an ordinal axis, the [StaticOrdinalTickProviderSpec] is shown in this
/// example defining ticks to be used with [TickSpec] of String.
///
/// For numeric axis, the [StaticNumericTickProviderSpec] can be used by passing
/// in a list of ticks defined with [TickSpec] of num.
///
/// For datetime axis, the [StaticDateTimeTickProviderSpec] can be used by
/// passing in a list of ticks defined with [TickSpec] of datetime.
class StaticallyProvidedTicks extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const StaticallyProvidedTicks(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory StaticallyProvidedTicks.withSampleData() {
return StaticallyProvidedTicks(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StaticallyProvidedTicks.withRandomData() {
return StaticallyProvidedTicks(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2014', random.nextInt(100) * 100),
OrdinalSales('2015', random.nextInt(100) * 100),
OrdinalSales('2016', random.nextInt(100) * 100),
OrdinalSales('2017', random.nextInt(100) * 100),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// Create the ticks to be used the domain axis.
final staticTicks = [
const charts.TickSpec(
// Value must match the domain value.
'2014',
// Optional label for this tick, defaults to domain value if not set.
label: 'Year 2014',
// The styling for this tick.
style: charts.TextStyleSpec(
color: charts.Color(r: 0x4C, g: 0xAF, b: 0x50))),
// If no text style is specified - the style from renderSpec will be used
// if one is specified.
const charts.TickSpec('2015'),
const charts.TickSpec('2016'),
const charts.TickSpec('2017'),
];
return charts.BarChart(
seriesList,
animate: animate,
domainAxis: charts.OrdinalAxisSpec(
tickProviderSpec: charts.StaticOrdinalTickProviderSpec(staticTicks)),
);
}
/// Create series list with single series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2014', 5000),
OrdinalSales('2015', 25000),
OrdinalSales('2016', 100000),
OrdinalSales('2017', 750000),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,155 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'custom_rounded_bars.dart';
import 'grouped.dart';
import 'grouped_fill_color.dart';
import 'grouped_single_target_line.dart';
import 'grouped_stacked.dart';
import 'grouped_stacked_weight_pattern.dart';
import 'grouped_target_line.dart';
import 'horizontal.dart';
import 'horizontal_bar_label.dart';
import 'horizontal_bar_label_custom.dart';
import 'horizontal_pattern_forward_hatch.dart';
import 'pattern_forward_hatch.dart';
import 'simple.dart';
import 'stacked.dart';
import 'stacked_fill_color.dart';
import 'stacked_horizontal.dart';
import 'stacked_target_line.dart';
import 'spark_bar.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Simple Bar Chart',
subtitle: 'Simple bar chart with a single series',
childBuilder: () => SimpleBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Stacked Bar Chart',
subtitle: 'Stacked bar chart with multiple series',
childBuilder: () => StackedBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Grouped Bar Chart',
subtitle: 'Grouped bar chart with multiple series',
childBuilder: () => GroupedBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Grouped Stacked Bar Chart',
subtitle: 'Grouped and stacked bar chart with multiple series',
childBuilder: () => GroupedStackedBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Grouped Bar Target Line Chart',
subtitle: 'Grouped bar target line chart with multiple series',
childBuilder: () => GroupedBarTargetLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Grouped Bar Single Target Line Chart',
subtitle:
'Grouped bar target line chart with multiple series and a single target',
childBuilder: () => GroupedBarSingleTargetLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Stacked Bar Target Line Chart',
subtitle: 'Stacked bar target line chart with multiple series',
childBuilder: () => StackedBarTargetLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: Transform.rotate(
angle: 1.5708, child: const Icon(Icons.insert_chart)),
title: 'Horizontal Bar Chart',
subtitle: 'Horizontal bar chart with a single series',
childBuilder: () => HorizontalBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: Transform.rotate(
angle: 1.5708, child: const Icon(Icons.insert_chart)),
title: 'Stacked Horizontal Bar Chart',
subtitle: 'Stacked horizontal bar chart with multiple series',
childBuilder: () => StackedHorizontalBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: Transform.rotate(
angle: 1.5708, child: const Icon(Icons.insert_chart)),
title: 'Horizontal Bar Chart with Bar Labels',
subtitle: 'Horizontal bar chart with a single series and bar labels',
childBuilder: () => HorizontalBarLabelChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: Transform.rotate(
angle: 1.5708, child: const Icon(Icons.insert_chart)),
title: 'Horizontal Bar Chart with Custom Bar Labels',
subtitle: 'Bar labels with customized styling',
childBuilder: () => HorizontalBarLabelCustomChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Spark Bar Chart',
subtitle: 'Spark Bar Chart',
childBuilder: () => SparkBar.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Grouped Fill Color Bar Chart',
subtitle: 'Grouped bar chart with fill colors',
childBuilder: () => GroupedFillColorBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Stacked Fill Color Bar Chart',
subtitle: 'Stacked bar chart with fill colors',
childBuilder: () => StackedFillColorBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Pattern Forward Hatch Bar Chart',
subtitle: 'Pattern Forward Hatch Bar Chart',
childBuilder: () => PatternForwardHatchBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: Transform.rotate(
angle: 1.5708, child: const Icon(Icons.insert_chart)),
title: 'Horizontal Pattern Forward Hatch Bar Chart',
subtitle: 'Horizontal Pattern Forward Hatch Bar Chart',
childBuilder: () =>
HorizontalPatternForwardHatchBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Weight Pattern Bar Chart',
subtitle: 'Grouped and stacked bar chart with a weight pattern',
childBuilder: () => GroupedStackedWeightPatternBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Bar Chart with custom bar radius',
subtitle: 'Custom rounded bar corners',
childBuilder: () => CustomRoundedBars.withRandomData(),
),
];
}

@ -1,111 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class CustomRoundedBars extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const CustomRoundedBars(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with custom rounded bars.
factory CustomRoundedBars.withSampleData() {
return CustomRoundedBars(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory CustomRoundedBars.withRandomData() {
return CustomRoundedBars(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
defaultRenderer: charts.BarRendererConfig(
// By default, bar renderer will draw rounded bars with a constant
// radius of 30.
// To not have any rounded corners, use [NoCornerStrategy]
// To change the radius of the bars, use [ConstCornerStrategy]
cornerStrategy: const charts.ConstCornerStrategy(30)),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,155 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class GroupedBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GroupedBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory GroupedBarChart.withSampleData() {
return GroupedBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GroupedBarChart.withRandomData() {
return GroupedBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,179 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of a grouped bar chart with three series, each rendered with
/// different fill colors.
class GroupedFillColorBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GroupedFillColorBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory GroupedFillColorBarChart.withSampleData() {
return GroupedFillColorBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GroupedFillColorBarChart.withRandomData() {
return GroupedFillColorBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
// Blue bars with a lighter center color.
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
fillColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
),
// Solid red bars. Fill color will default to the series color if no
// fillColorFn is configured.
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
),
// Hollow green bars.
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
// Configure a stroke width to enable borders on the bars.
defaultRenderer: charts.BarRendererConfig(
groupingType: charts.BarGroupingType.grouped, strokeWidthPx: 2.0),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 50),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
// Blue bars with a lighter center color.
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
fillColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
),
// Solid red bars. Fill color will default to the series color if no
// fillColorFn is configured.
charts.Series<OrdinalSales, String>(
id: 'Tablet',
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
),
// Hollow green bars.
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,182 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class GroupedBarSingleTargetLineChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GroupedBarSingleTargetLineChart(this.seriesList,
{this.animate, Key? key})
: super(key: key);
factory GroupedBarSingleTargetLineChart.withSampleData() {
return GroupedBarSingleTargetLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GroupedBarSingleTargetLineChart.withRandomData() {
return GroupedBarSingleTargetLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final targetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData),
charts.Series<OrdinalSales, String>(
id: 'Desktop Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: targetLineData)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
customSeriesRenderers: [
charts.BarTargetLineRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customTargetLine',
groupingType: charts.BarGroupingType.grouped)
]);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final targetLineData = [
OrdinalSales('2014', 30),
OrdinalSales('2015', 55),
OrdinalSales('2016', 15),
OrdinalSales('2017', 25),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData),
charts.Series<OrdinalSales, String>(
id: 'Desktop Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: targetLineData)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,245 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a bar chart with grouped, stacked series oriented vertically.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class GroupedStackedBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GroupedStackedBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory GroupedStackedBarChart.withSampleData() {
return GroupedStackedBarChart(
createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GroupedStackedBarChart.withRandomData() {
return GroupedStackedBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final desktopSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataB,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.groupedStacked,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> createSampleData() {
final desktopSalesDataA = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesDataA = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesDataA = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final desktopSalesDataB = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesDataB = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesDataB = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataB,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,258 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a bar chart with grouped, stacked series oriented vertically with
/// a custom weight pattern.
///
/// This is a pattern of weights used to calculate the width of bars within a
/// bar group. If not specified, each bar in the group will have an equal width.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class GroupedStackedWeightPatternBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GroupedStackedWeightPatternBarChart(this.seriesList,
{this.animate, Key? key})
: super(key: key);
factory GroupedStackedWeightPatternBarChart.withSampleData() {
return GroupedStackedWeightPatternBarChart(
createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GroupedStackedWeightPatternBarChart.withRandomData() {
return GroupedStackedWeightPatternBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final desktopSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataB,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
// Configure the bar renderer in grouped stacked rendering mode with a
// custom weight pattern.
//
// The first stack of bars in each group is configured to be twice as wide
// as the second stack of bars in each group.
defaultRenderer: charts.BarRendererConfig(
groupingType: charts.BarGroupingType.groupedStacked,
weightPattern: [2, 1],
),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> createSampleData() {
final desktopSalesDataA = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesDataA = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesDataA = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final desktopSalesDataB = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesDataB = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesDataB = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataB,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,249 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class GroupedBarTargetLineChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GroupedBarTargetLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory GroupedBarTargetLineChart.withSampleData() {
return GroupedBarTargetLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GroupedBarTargetLineChart.withRandomData() {
return GroupedBarTargetLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final desktopTargetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableTargetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileTargetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Tablet Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Mobile Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
customSeriesRenderers: [
charts.BarTargetLineRendererConfig<String>(
// ID used to link series to this renderer.
customRendererId: 'customTargetLine',
groupingType: charts.BarGroupingType.grouped)
]);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final desktopTargetLineData = [
OrdinalSales('2014', 4),
OrdinalSales('2015', 20),
OrdinalSales('2016', 80),
OrdinalSales('2017', 65),
];
final tableTargetLineData = [
OrdinalSales('2014', 30),
OrdinalSales('2015', 55),
OrdinalSales('2016', 15),
OrdinalSales('2017', 25),
];
final mobileTargetLineData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 5),
OrdinalSales('2016', 45),
OrdinalSales('2017', 35),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Tablet Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Mobile Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,105 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Horizontal bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class HorizontalBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const HorizontalBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory HorizontalBarChart.withSampleData() {
return HorizontalBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory HorizontalBarChart.withRandomData() {
return HorizontalBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// For horizontal bar charts, set the [vertical] flag to false.
return charts.BarChart(
seriesList,
animate: animate,
vertical: false,
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,124 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Horizontal bar chart with bar label renderer example and hidden domain axis.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class HorizontalBarLabelChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const HorizontalBarLabelChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory HorizontalBarLabelChart.withSampleData() {
return HorizontalBarLabelChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory HorizontalBarLabelChart.withRandomData() {
return HorizontalBarLabelChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the bar label.
labelAccessorFn: (OrdinalSales sales, _) =>
'${sales.year}: \$${sales.sales.toString()}')
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
// [BarLabelDecorator] will automatically position the label
// inside the bar if the label will fit. If the label will not fit and the
// area outside of the bar is larger than the bar, it will draw outside of the
// bar. Labels can always display inside or outside using [LabelPosition].
//
// Text style for inside / outside can be controlled independently by setting
// [insideLabelStyleSpec] and [outsideLabelStyleSpec].
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
vertical: false,
// Set a bar label decorator.
// Example configuring different styles for inside/outside:
// barRendererDecorator: new charts.BarLabelDecorator(
// insideLabelStyleSpec: new charts.TextStyleSpec(...),
// outsideLabelStyleSpec: new charts.TextStyleSpec(...)),
barRendererDecorator: charts.BarLabelDecorator<String>(),
// Hide domain axis.
domainAxis:
const charts.OrdinalAxisSpec(renderSpec: charts.NoneRenderSpec()),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the bar label.
labelAccessorFn: (OrdinalSales sales, _) =>
'${sales.year}: \$${sales.sales.toString()}')
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,141 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Horizontal bar chart with custom style for each datum in the bar label.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class HorizontalBarLabelCustomChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const HorizontalBarLabelCustomChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
static HorizontalBarLabelCustomChart createWithSampleData() {
return HorizontalBarLabelCustomChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory HorizontalBarLabelCustomChart.withRandomData() {
return HorizontalBarLabelCustomChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the bar label.
labelAccessorFn: (OrdinalSales sales, _) =>
'${sales.year}: \$${sales.sales.toString()}',
insideLabelStyleAccessorFn: (OrdinalSales sales, _) {
final color = (sales.year == '2014')
? charts.MaterialPalette.red.shadeDefault
: charts.MaterialPalette.yellow.shadeDefault.darker;
return charts.TextStyleSpec(color: color);
},
outsideLabelStyleAccessorFn: (OrdinalSales sales, _) {
final color = (sales.year == '2014')
? charts.MaterialPalette.red.shadeDefault
: charts.MaterialPalette.yellow.shadeDefault.darker;
return charts.TextStyleSpec(color: color);
},
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
// The [BarLabelDecorator] has settings to set the text style for all labels
// for inside the bar and outside the bar. To be able to control each datum's
// style, set the style accessor functions on the series.
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
vertical: false,
barRendererDecorator: charts.BarLabelDecorator<String>(),
// Hide domain axis.
domainAxis:
const charts.OrdinalAxisSpec(renderSpec: charts.NoneRenderSpec()),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the bar label.
labelAccessorFn: (OrdinalSales sales, _) =>
'${sales.year}: \$${sales.sales.toString()}',
insideLabelStyleAccessorFn: (OrdinalSales sales, _) {
final color = (sales.year == '2014')
? charts.MaterialPalette.red.shadeDefault
: charts.MaterialPalette.yellow.shadeDefault.darker;
return charts.TextStyleSpec(color: color);
},
outsideLabelStyleAccessorFn: (OrdinalSales sales, _) {
final color = (sales.year == '2014')
? charts.MaterialPalette.red.shadeDefault
: charts.MaterialPalette.yellow.shadeDefault.darker;
return charts.TextStyleSpec(color: color);
},
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,165 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Forward pattern hatch bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Forward hatch pattern horizontal bar chart example.
///
/// The second series of bars is rendered with a pattern by defining a
/// fillPatternFn mapping function.
class HorizontalPatternForwardHatchBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const HorizontalPatternForwardHatchBarChart(this.seriesList,
{this.animate, Key? key})
: super(key: key);
factory HorizontalPatternForwardHatchBarChart.withSampleData() {
return HorizontalPatternForwardHatchBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory HorizontalPatternForwardHatchBarChart.withRandomData() {
return HorizontalPatternForwardHatchBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
fillPatternFn: (OrdinalSales sales, _) =>
charts.FillPatternType.forwardHatch,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
vertical: false,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
fillPatternFn: (OrdinalSales sales, _) =>
charts.FillPatternType.forwardHatch,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,162 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Forward hatch pattern bar chart example.
///
/// The second series of bars is rendered with a pattern by defining a
/// fillPatternFn mapping function.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class PatternForwardHatchBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const PatternForwardHatchBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory PatternForwardHatchBarChart.withSampleData() {
return PatternForwardHatchBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory PatternForwardHatchBarChart.withRandomData() {
return PatternForwardHatchBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
fillPatternFn: (OrdinalSales sales, _) =>
charts.FillPatternType.forwardHatch,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
fillPatternFn: (OrdinalSales sales, _) =>
charts.FillPatternType.forwardHatch,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,105 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SimpleBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const SimpleBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory SimpleBarChart.withSampleData() {
return SimpleBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SimpleBarChart.withRandomData() {
return SimpleBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,140 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Spark Bar Example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of a Spark Bar by hiding both axis, reducing the chart margins.
class SparkBar extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const SparkBar(this.seriesList, {this.animate, Key? key}) : super(key: key);
factory SparkBar.withSampleData() {
return SparkBar(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SparkBar.withRandomData() {
return SparkBar(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final globalSalesData = [
OrdinalSales('2007', random.nextInt(100)),
OrdinalSales('2008', random.nextInt(100)),
OrdinalSales('2009', random.nextInt(100)),
OrdinalSales('2010', random.nextInt(100)),
OrdinalSales('2011', random.nextInt(100)),
OrdinalSales('2012', random.nextInt(100)),
OrdinalSales('2013', random.nextInt(100)),
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
/// Assign a custom style for the measure axis.
///
/// The NoneRenderSpec only draws an axis line (and even that can be hidden
/// with showAxisLine=false).
primaryMeasureAxis:
const charts.NumericAxisSpec(renderSpec: charts.NoneRenderSpec()),
/// This is an OrdinalAxisSpec to match up with BarChart's default
/// ordinal domain axis (use NumericAxisSpec or DateTimeAxisSpec for
/// other charts).
domainAxis: const charts.OrdinalAxisSpec(
// Make sure that we draw the domain axis line.
showAxisLine: true,
// But don't draw anything else.
renderSpec: charts.NoneRenderSpec()),
// With a spark chart we likely don't want large chart margins.
// 1px is the smallest we can make each margin.
layoutConfig: charts.LayoutConfig(
leftMarginSpec: charts.MarginSpec.fixedPixel(0),
topMarginSpec: charts.MarginSpec.fixedPixel(0),
rightMarginSpec: charts.MarginSpec.fixedPixel(0),
bottomMarginSpec: charts.MarginSpec.fixedPixel(0)),
);
}
/// Create series list with single series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final globalSalesData = [
OrdinalSales('2007', 3100),
OrdinalSales('2008', 3500),
OrdinalSales('2009', 5000),
OrdinalSales('2010', 2500),
OrdinalSales('2011', 3200),
OrdinalSales('2012', 4500),
OrdinalSales('2013', 4400),
OrdinalSales('2014', 5000),
OrdinalSales('2015', 5000),
OrdinalSales('2016', 4500),
OrdinalSales('2017', 4300),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Global Revenue',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: globalSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,156 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class StackedBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const StackedBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a stacked [BarChart] with sample data and no transition.
factory StackedBarChart.withSampleData() {
return StackedBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedBarChart.withRandomData() {
return StackedBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.stacked,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,179 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example of a stacked bar chart with three series, each rendered with
/// different fill colors.
class StackedFillColorBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const StackedFillColorBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory StackedFillColorBarChart.withSampleData() {
return StackedFillColorBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedFillColorBarChart.withRandomData() {
return StackedFillColorBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
// Blue bars with a lighter center color.
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
fillColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
),
// Solid red bars. Fill color will default to the series color if no
// fillColorFn is configured.
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
),
// Hollow green bars.
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
// Configure a stroke width to enable borders on the bars.
defaultRenderer: charts.BarRendererConfig(
groupingType: charts.BarGroupingType.stacked, strokeWidthPx: 2.0),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 50),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
// Blue bars with a lighter center color.
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
fillColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
),
// Solid red bars. Fill color will default to the series color if no
// fillColorFn is configured.
charts.Series<OrdinalSales, String>(
id: 'Tablet',
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
),
// Hollow green bars.
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,158 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class StackedHorizontalBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const StackedHorizontalBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a stacked [BarChart] with sample data and no transition.
factory StackedHorizontalBarChart.withSampleData() {
return StackedHorizontalBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedHorizontalBarChart.withRandomData() {
return StackedHorizontalBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// For horizontal bar charts, set the [vertical] flag to false.
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.stacked,
vertical: false,
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,250 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class StackedBarTargetLineChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const StackedBarTargetLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a stacked [BarChart] with sample data and no transition.
factory StackedBarTargetLineChart.withSampleData() {
return StackedBarTargetLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedBarTargetLineChart.withRandomData() {
return StackedBarTargetLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final desktopTargetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableTargetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileTargetLineData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Tablet Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Mobile Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.stacked,
customSeriesRenderers: [
charts.BarTargetLineRendererConfig<String>(
// ID used to link series to this renderer.
customRendererId: 'customTargetLine',
groupingType: charts.BarGroupingType.stacked)
]);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final desktopTargetLineData = [
OrdinalSales('2014', 4),
OrdinalSales('2015', 20),
OrdinalSales('2016', 80),
OrdinalSales('2017', 65),
];
final tableTargetLineData = [
OrdinalSales('2014', 30),
OrdinalSales('2015', 55),
OrdinalSales('2016', 15),
OrdinalSales('2017', 25),
];
final mobileTargetLineData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 5),
OrdinalSales('2016', 45),
OrdinalSales('2017', 35),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Tablet Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
charts.Series<OrdinalSales, String>(
id: 'Mobile Target Line',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileTargetLineData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,124 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'chart_title.dart';
import 'initial_hint_animation.dart';
import 'initial_selection.dart';
import 'percent_of_domain.dart';
import 'percent_of_domain_by_category.dart';
import 'percent_of_series.dart';
import 'selection_bar_highlight.dart';
import 'selection_line_highlight.dart';
import 'selection_line_highlight_custom_shape.dart';
import 'selection_callback_example.dart';
import 'selection_scatter_plot_highlight.dart';
import 'selection_user_managed.dart';
import 'slider.dart';
import 'sliding_viewport_on_selection.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Selection Bar Highlight',
subtitle: 'Simple bar chart with tap activation',
childBuilder: () => SelectionBarHighlight.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Selection Line Highlight',
subtitle: 'Line chart with tap and drag activation',
childBuilder: () => SelectionLineHighlight.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Selection Line Highlight Custom Shape',
subtitle: 'Line chart with tap and drag activation and a custom shape',
childBuilder: () => SelectionLineHighlightCustomShape.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Selection Scatter Plot Highlight',
subtitle: 'Scatter plot chart with tap and drag activation',
childBuilder: () => SelectionScatterPlotHighlight.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Selection Callback Example',
subtitle: 'Timeseries that updates external components on selection',
childBuilder: () => SelectionCallbackExample.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'User managed selection',
subtitle:
'Example where selection can be set and cleared programmatically',
childBuilder: () => SelectionUserManaged.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Bar Chart with initial selection',
subtitle: 'Single series with initial selection',
childBuilder: () => InitialSelection.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Line Chart with Chart Titles',
subtitle: 'Line chart with four chart titles',
childBuilder: () => ChartTitleLine.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'Line Chart with Slider',
subtitle: 'Line chart with a slider behavior',
childBuilder: () => SliderLine.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Percent of Domain',
subtitle:
'Stacked bar chart with measures calculated as percent of ' 'domain',
childBuilder: () => PercentOfDomainBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Percent of Domain by Category',
subtitle: 'Grouped stacked bar chart with measures calculated as '
'percent of domain and series category',
childBuilder: () => PercentOfDomainByCategoryBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Percent of Series',
subtitle:
'Grouped bar chart with measures calculated as percent of ' 'series',
childBuilder: () => PercentOfSeriesBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Sliding viewport on domain selection',
subtitle: 'Center viewport on selected domain',
childBuilder: () => SlidingViewportOnSelection.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Initial hint animation ',
subtitle: 'Animate into final viewport',
childBuilder: () => InitialHintAnimation.withRandomData(),
),
];
}

@ -1,132 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
/// This is a line chart with a title text in every margin.
///
/// A series of [ChartTitle] behaviors are used to render titles, one per
/// margin.
class ChartTitleLine extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const ChartTitleLine(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory ChartTitleLine.withSampleData() {
return ChartTitleLine(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory ChartTitleLine.withRandomData() {
return ChartTitleLine(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(
seriesList,
animate: animate,
// Configures four [ChartTitle] behaviors to render titles in each chart
// margin. The top title has a sub-title, and is aligned to the left edge
// of the chart. The other titles are aligned with the middle of the draw
// area.
behaviors: [
charts.ChartTitle('Top title text',
subTitle: 'Top sub-title text',
behaviorPosition: charts.BehaviorPosition.top,
titleOutsideJustification: charts.OutsideJustification.start,
// Set a larger inner padding than the default (10) to avoid
// rendering the text too close to the top measure axis tick label.
// The top tick label may extend upwards into the top margin region
// if it is located at the top of the draw area.
innerPadding: 18),
charts.ChartTitle('Bottom title text',
behaviorPosition: charts.BehaviorPosition.bottom,
titleOutsideJustification:
charts.OutsideJustification.middleDrawArea),
charts.ChartTitle('Start title',
behaviorPosition: charts.BehaviorPosition.start,
titleOutsideJustification:
charts.OutsideJustification.middleDrawArea),
charts.ChartTitle('End title',
behaviorPosition: charts.BehaviorPosition.end,
titleOutsideJustification:
charts.OutsideJustification.middleDrawArea),
],
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,176 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of initial hint animation behavior.
///
/// To see the animation, please run the example app and select
/// "Initial hint animation".
///
/// This behavior is intended to be used with charts that also have pan/zoom
/// behaviors added and/or the initial viewport set in [AxisSpec].
///
/// Adding this behavior will cause the chart to animate from a scale and/or
/// offset of the desired final viewport. If the user taps the widget prior
/// to the animation being completed, animation will stop.
///
/// [maxHintScaleFactor] is the amount the domain axis will be scaled at the
/// start of te hint. By default, this is null, indicating that there will be
/// no scale factor hint. A value of 1.0 means the viewport is showing all
/// domains in the viewport. If a value is provided, it cannot be less than 1.0.
///
/// [maxHintTranslate] is the amount of ordinal values to translate the viewport
/// from the desired initial viewport. Currently only works for ordinal axis.
///
/// In this example, the series list has ordinal data from year 2014 to 2030,
/// and we have the initial viewport set to start at 2018 that shows 4 values by
/// specifying an [OrdinalViewport] in [OrdinalAxisSpec]. We can add the hint
/// animation by adding behavior [InitialHintBehavior] with [maxHintTranslate]
/// of 4. When the chart is drawn for the first time, the viewport will show
/// 2022 as the first value and the viewport will animate by panning values to
/// the right until 2018 is the first value in the viewport.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class InitialHintAnimation extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const InitialHintAnimation(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory InitialHintAnimation.withSampleData() {
return InitialHintAnimation(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory InitialHintAnimation.withRandomData() {
return InitialHintAnimation(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
OrdinalSales('2018', random.nextInt(100)),
OrdinalSales('2019', random.nextInt(100)),
OrdinalSales('2020', random.nextInt(100)),
OrdinalSales('2021', random.nextInt(100)),
OrdinalSales('2022', random.nextInt(100)),
OrdinalSales('2023', random.nextInt(100)),
OrdinalSales('2024', random.nextInt(100)),
OrdinalSales('2025', random.nextInt(100)),
OrdinalSales('2026', random.nextInt(100)),
OrdinalSales('2027', random.nextInt(100)),
OrdinalSales('2028', random.nextInt(100)),
OrdinalSales('2029', random.nextInt(100)),
OrdinalSales('2030', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
// Optionally turn off the animation that animates values up from the
// bottom of the domain axis. If animation is on, the bars will animate up
// and then animate to the final viewport.
animationDuration: Duration.zero,
// Set the initial viewport by providing a new AxisSpec with the
// desired viewport: a starting domain and the data size.
domainAxis:
charts.OrdinalAxisSpec(viewport: charts.OrdinalViewport('2018', 4)),
behaviors: [
// Add this behavior to show initial hint animation that will pan to the
// final desired viewport.
// The duration of the animation can be adjusted by pass in
// [hintDuration]. By default this is 3000ms.
charts.InitialHintBehavior(maxHintTranslate: 4.0),
// Optionally add a pan or pan and zoom behavior.
// If pan/zoom is not added, the viewport specified remains the viewport
charts.PanAndZoomBehavior(),
],
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
OrdinalSales('2018', 33),
OrdinalSales('2019', 80),
OrdinalSales('2020', 21),
OrdinalSales('2021', 77),
OrdinalSales('2022', 8),
OrdinalSales('2023', 12),
OrdinalSales('2024', 42),
OrdinalSales('2025', 70),
OrdinalSales('2026', 77),
OrdinalSales('2027', 55),
OrdinalSales('2028', 19),
OrdinalSales('2029', 66),
OrdinalSales('2030', 27),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,130 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of adding an initial selection behavior.
///
/// This example adds initial selection to a bar chart, but any chart can use
/// the initial selection behavior.
///
/// Initial selection is only set on the very first draw and will not be set
/// again in subsequent draws unless the behavior is reconfigured.
///
/// The selection will remain on the chart unless another behavior is added
/// that updates the selection.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class InitialSelection extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const InitialSelection(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with initial selection behavior.
factory InitialSelection.withSampleData() {
return InitialSelection(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory InitialSelection.withRandomData() {
return InitialSelection(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
behaviors: [
// Initial selection can be configured by passing in:
//
// A list of datum config, specified with series ID and domain value.
// A list of series config, which is a list of series ID(s).
//
// Initial selection can be applied to any chart type.
//
// [BarChart] by default includes behaviors [SelectNearest] and
// [DomainHighlighter]. So this behavior shows the initial selection
// highlighted and when another datum is tapped, the selection changes.
charts.InitialSelection(selectedDataConfig: [
charts.SeriesDatumConfig<String>('Sales', '2016')
])
],
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,168 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a percentage bar chart with stacked series oriented vertically.
///
/// Each bar stack shows the percentage of each measure out of the total measure
/// value of the stack.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class PercentOfDomainBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const PercentOfDomainBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a stacked [BarChart] with sample data and no transition.
factory PercentOfDomainBarChart.withSampleData() {
return PercentOfDomainBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory PercentOfDomainBarChart.withRandomData() {
return PercentOfDomainBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.stacked,
// Configures a [PercentInjector] behavior that will calculate measure
// values as the percentage of the total of all data that shares a
// domain value.
behaviors: [
charts.PercentInjector(
totalType: charts.PercentInjectorTotalType.domain)
],
// Configure the axis spec to show percentage values.
primaryMeasureAxis: charts.PercentAxisSpec(),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,263 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a percentage bar chart with grouped, stacked series oriented
/// vertically.
///
/// Each bar stack shows the percentage of each measure out of the total measure
/// value of the stack.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class PercentOfDomainByCategoryBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const PercentOfDomainByCategoryBarChart(this.seriesList,
{this.animate, Key? key})
: super(key: key);
factory PercentOfDomainByCategoryBarChart.withSampleData() {
return PercentOfDomainByCategoryBarChart(
createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory PercentOfDomainByCategoryBarChart.withRandomData() {
return PercentOfDomainByCategoryBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesDataA = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final desktopSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesDataB = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataB,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.groupedStacked,
// Configures a [PercentInjector] behavior that will calculate measure
// values as the percentage of the total of all data that shares both a
// domain and a series category.
//
// We use this option on a grouped stacked bar chart to ensure that the
// total value for each bar stack is 100%. A stacked bar chart that does
// not group by series category would use the "domain" option.
behaviors: [
charts.PercentInjector(
totalType: charts.PercentInjectorTotalType.domainBySeriesCategory)
],
// Configure the axis spec to show percentage values.
primaryMeasureAxis: charts.PercentAxisSpec(),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> createSampleData() {
final desktopSalesDataA = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesDataA = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesDataA = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final desktopSalesDataB = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesDataB = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesDataB = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile A',
seriesCategory: 'A',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataA,
),
charts.Series<OrdinalSales, String>(
id: 'Desktop B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesDataB,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile B',
seriesCategory: 'B',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesDataB,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,121 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a percentage bar chart which shows each bar as the percentage of
/// the total series measure value.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class PercentOfSeriesBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const PercentOfSeriesBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a stacked [BarChart] with sample data and no transition.
factory PercentOfSeriesBarChart.withSampleData() {
return PercentOfSeriesBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory PercentOfSeriesBarChart.withRandomData() {
return PercentOfSeriesBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// Configures a [PercentInjector] behavior that will calculate measure
// values as the percentage of the total of all data in its series.
behaviors: [
charts.PercentInjector(
totalType: charts.PercentInjectorTotalType.series)
],
// Configure the axis spec to show percentage values.
primaryMeasureAxis: charts.PercentAxisSpec(),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2011', 5),
OrdinalSales('2012', 25),
OrdinalSales('2013', 50),
OrdinalSales('2014', 75),
OrdinalSales('2015', 100),
OrdinalSales('2016', 125),
OrdinalSales('2017', 200),
OrdinalSales('2018', 150),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,111 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SelectionBarHighlight extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const SelectionBarHighlight(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory SelectionBarHighlight.withSampleData() {
return SelectionBarHighlight(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SelectionBarHighlight.withRandomData() {
return SelectionBarHighlight(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// This is just a simple bar chart with optional property
// [defaultInteractions] set to true to include the default
// interactions/behaviors when building the chart.
// This includes bar highlighting.
//
// Note: defaultInteractions defaults to true.
//
// [defaultInteractions] can be set to false to avoid the default
// interactions.
return charts.BarChart(
seriesList,
animate: animate,
defaultInteractions: true,
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,202 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Timeseries chart with example of updating external state based on selection.
///
/// A SelectionModelConfig can be provided for each of the different
/// [SelectionModel] (currently info and action).
///
/// [SelectionModelType.info] is the default selection chart exploration type
/// initiated by some tap event. This is a different model from
/// [SelectionModelType.action] which is typically used to select some value as
/// an input to some other UI component. This allows dual state of exploring
/// and selecting data via different touch events.
///
/// See [SelectNearest] behavior on setting the different ways of triggering
/// [SelectionModel] updates from hover & click events.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SelectionCallbackExample extends StatefulWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const SelectionCallbackExample(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [charts.TimeSeriesChart] with sample data and no transition.
factory SelectionCallbackExample.withSampleData() {
return SelectionCallbackExample(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SelectionCallbackExample.withRandomData() {
return SelectionCallbackExample(_createRandomData());
}
/// Create random data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createRandomData() {
final random = Random();
final usData = [
TimeSeriesSales(DateTime(2017, 9, 19), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 9, 26), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 3), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 10), random.nextInt(100)),
];
final ukData = [
TimeSeriesSales(DateTime(2017, 9, 19), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 9, 26), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 3), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 10), random.nextInt(100)),
];
return [
charts.Series<TimeSeriesSales, DateTime>(
id: 'US Sales',
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: usData,
),
charts.Series<TimeSeriesSales, DateTime>(
id: 'UK Sales',
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: ukData,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
// We need a Stateful widget to build the selection details with the current
// selection as the state.
@override
State<StatefulWidget> createState() => _SelectionCallbackState();
/// Create one series with sample hard coded data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
final usData = [
TimeSeriesSales(DateTime(2017, 9, 19), 5),
TimeSeriesSales(DateTime(2017, 9, 26), 25),
TimeSeriesSales(DateTime(2017, 10, 3), 78),
TimeSeriesSales(DateTime(2017, 10, 10), 54),
];
final ukData = [
TimeSeriesSales(DateTime(2017, 9, 19), 15),
TimeSeriesSales(DateTime(2017, 9, 26), 33),
TimeSeriesSales(DateTime(2017, 10, 3), 68),
TimeSeriesSales(DateTime(2017, 10, 10), 48),
];
return [
charts.Series<TimeSeriesSales, DateTime>(
id: 'US Sales',
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: usData,
),
charts.Series<TimeSeriesSales, DateTime>(
id: 'UK Sales',
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: ukData,
)
];
}
}
class _SelectionCallbackState extends State<SelectionCallbackExample> {
DateTime? _time;
Map<String?, num?>? _measures;
// Listens to the underlying selection changes, and updates the information
// relevant to building the primitive legend like information under the
// chart.
_onSelectionChanged(charts.SelectionModel model) {
final selectedDatum = model.selectedDatum;
DateTime? time;
final measures = <String?, num?>{};
// We get the model that updated with a list of [SeriesDatum] which is
// simply a pair of series & datum.
//
// Walk the selection updating the measures map, storing off the sales and
// series name for each selection point.
if (selectedDatum.isNotEmpty) {
time = selectedDatum.first.datum.time;
for (var datumPair in selectedDatum) {
measures[datumPair.series.displayName] = datumPair.datum.sales;
}
}
// Request a build.
setState(() {
_time = time;
_measures = measures;
});
}
@override
Widget build(BuildContext context) {
// The children consist of a Chart and Text widgets below to hold the info.
final children = <Widget>[
SizedBox(
height: 150.0,
child: charts.TimeSeriesChart(
widget.seriesList,
animate: widget.animate,
selectionModels: [
charts.SelectionModelConfig(
type: charts.SelectionModelType.info,
changedListener: _onSelectionChanged,
)
],
)),
];
// If there is a selection, then include the details.
if (_time != null) {
children.add(Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Text(_time.toString())));
}
_measures?.forEach((String? series, num? value) {
children.add(Text('$series: $value'));
});
return Column(children: children);
}
}
/// Sample time series data type.
class TimeSeriesSales {
final DateTime time;
final int sales;
TimeSeriesSales(this.time, this.sales);
}

@ -1,128 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SelectionLineHighlight extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SelectionLineHighlight(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory SelectionLineHighlight.withSampleData() {
return SelectionLineHighlight(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SelectionLineHighlight.withRandomData() {
return SelectionLineHighlight(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// This is just a simple line chart with a behavior that highlights the
// selected points along the lines. A point will be drawn at the selected
// datum's x,y coordinate, and a vertical follow line will be drawn through
// it.
//
// A [Charts.LinePointHighlighter] behavior is added manually to enable the
// highlighting effect.
//
// As an alternative, [defaultInteractions] can be set to true to include
// the default chart interactions, including a LinePointHighlighter.
return charts.LineChart(seriesList, animate: animate, behaviors: [
// Optional - Configures a [LinePointHighlighter] behavior with a
// vertical follow line. A vertical follow line is included by
// default, but is shown here as an example configuration.
//
// By default, the line has default dash pattern of [1,3]. This can be
// set by providing a [dashPattern] or it can be turned off by passing in
// an empty list. An empty list is necessary because passing in a null
// value will be treated the same as not passing in a value at all.
charts.LinePointHighlighter(
showHorizontalFollowLine:
charts.LinePointHighlighterFollowLineType.none,
showVerticalFollowLine:
charts.LinePointHighlighterFollowLineType.nearest),
// Optional - By default, select nearest is configured to trigger
// with tap so that a user can have pan/zoom behavior and line point
// highlighter. Changing the trigger to tap and drag allows the
// highlighter to follow the dragging gesture but it is not
// recommended to be used when pan/zoom behavior is enabled.
charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag)
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,132 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SelectionLineHighlightCustomShape extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SelectionLineHighlightCustomShape(this.seriesList,
{this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory SelectionLineHighlightCustomShape.withSampleData() {
return SelectionLineHighlightCustomShape(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SelectionLineHighlightCustomShape.withRandomData() {
return SelectionLineHighlightCustomShape(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// This is a simple line chart with a behavior that highlights hovered
// lines. A hollow rectangular shape will be drawn at the hovered datum's
// x,y coordinate, and a vertical follow line will be drawn through it.
//
// A [Charts.LinePointHighlighter] behavior is added manually to enable the
// highlighting effect.
//
// As an alternative, [defaultInteractions] can be set to true to include
// the default chart interactions, including a LinePointHighlighter.
return charts.LineChart(seriesList, animate: animate, behaviors: [
// Optional - Configures a [LinePointHighlighter] behavior with a
// vertical follow line. A vertical follow line is included by
// default, but is shown here as an example configuration.
//
// By default, the line has default dash pattern of [1,3]. This can be
// set by providing a [dashPattern] or it can be turned off by passing in
// an empty list. An empty list is necessary because passing in a null
// value will be treated the same as not passing in a value at all.
//
// The symbol renderer is configured to render a hollow shape, for
// demonstration.
charts.LinePointHighlighter(
showHorizontalFollowLine:
charts.LinePointHighlighterFollowLineType.none,
showVerticalFollowLine:
charts.LinePointHighlighterFollowLineType.nearest,
symbolRenderer: charts.RectSymbolRenderer(isSolid: false)),
// Optional - By default, select nearest is configured to trigger
// with tap so that a user can have pan/zoom behavior and line point
// highlighter. Changing the trigger to tap and drag allows the
// highlighter to follow the dragging gesture but it is not
// recommended to be used when pan/zoom behavior is enabled.
charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag)
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,234 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a scatter plot chart using custom symbols for the points and a
/// behavior that highlights selected points.
///
/// An optional [charts.LinePointHighlighter] behavior has been added to enable
/// a highlighting effect. This behavior will draw a larger symbol on top of the
/// point nearest to the point where a user taps on the chart. It will also draw
/// follow lines.
///
/// The series has been configured to draw each point as a square by default.
///
/// Some data will be drawn as a circle, indicated by defining a custom "circle"
/// value referenced by [charts.pointSymbolRendererFnKey].
///
/// Some other data have will be drawn as a hollow circle. In addition to the
/// custom renderer key, these data also have stroke and fillColor values
/// defined. Configuring a separate fillColor will cause the center of the shape
/// to be filled in, with white in these examples. The border of the shape will
/// be color with the color of the data.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SelectionScatterPlotHighlight extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SelectionScatterPlotHighlight(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [ScatterPlotChart] with sample data and no transition.
factory SelectionScatterPlotHighlight.withSampleData() {
return SelectionScatterPlotHighlight(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SelectionScatterPlotHighlight.withRandomData() {
return SelectionScatterPlotHighlight(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
makeRadius(int value) => (random.nextInt(value) + 2).toDouble();
final data = [
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
'circle', null, null),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
// Render a hollow circle, filled in with white.
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(4) + 4,
'circle', charts.MaterialPalette.white, 2.0),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
'circle', null, null),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
// Render a hollow circle, filled in with white.
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(4) + 4,
'circle', charts.MaterialPalette.white, 2.0),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6), null,
null, null),
// Render a hollow square, filled in with white.
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(4) + 4,
null, charts.MaterialPalette.white, 2.0),
];
const maxMeasure = 100;
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (LinearSales sales, _) {
// Color bucket the measure column value into 3 distinct colors.
final bucket = sales.sales / maxMeasure;
if (bucket < 1 / 3) {
return charts.MaterialPalette.blue.shadeDefault;
} else if (bucket < 2 / 3) {
return charts.MaterialPalette.red.shadeDefault;
} else {
return charts.MaterialPalette.green.shadeDefault;
}
},
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
radiusPxFn: (LinearSales sales, _) => sales.radius,
fillColorFn: (LinearSales row, _) => row.fillColor,
strokeWidthPxFn: (LinearSales row, _) => row.strokeWidth,
data: data,
)
// Accessor function that associates each datum with a symbol renderer.
..setAttribute(
charts.pointSymbolRendererFnKey, (int index) => data[index].shape)
// Default symbol renderer ID for data that have no defined shape.
..setAttribute(charts.pointSymbolRendererIdKey, 'rect')
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.ScatterPlotChart(seriesList,
animate: animate,
behaviors: [
// Optional - Configures a [LinePointHighlighter] behavior with
// horizontal and vertical follow lines. The highlighter will increase
// the size of the selected points on the chart.
//
// By default, the line has default dash pattern of [1,3]. This can be
// set by providing a [dashPattern] or it can be turned off by passing
// in an empty list. An empty list is necessary because passing in a
// null value will be treated the same as not passing in a value at
// all.
charts.LinePointHighlighter(
showHorizontalFollowLine:
charts.LinePointHighlighterFollowLineType.nearest,
showVerticalFollowLine:
charts.LinePointHighlighterFollowLineType.nearest),
// Optional - By default, select nearest is configured to trigger
// with tap so that a user can have pan/zoom behavior and line point
// highlighter. Changing the trigger to tap and drag allows the
// highlighter to follow the dragging gesture but it is not
// recommended to be used when pan/zoom behavior is enabled.
charts.SelectNearest(
eventTrigger: charts.SelectionTrigger.tapAndDrag),
],
// Configure the point renderer to have a map of custom symbol
// renderers.
defaultRenderer:
charts.PointRendererConfig<num>(customSymbolRenderers: {
'circle': charts.CircleSymbolRenderer(),
'rect': charts.RectSymbolRenderer(),
}));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5, 3.0, 'circle', null, null),
LinearSales(10, 25, 5.0, null, null, null),
LinearSales(12, 75, 4.0, null, null, null),
// Render a hollow circle, filled in with white.
LinearSales(13, 225, 5.0, 'circle', charts.MaterialPalette.white, 2.0),
LinearSales(16, 50, 4.0, null, null, null),
LinearSales(24, 75, 3.0, null, null, null),
LinearSales(25, 100, 3.0, 'circle', null, null),
LinearSales(34, 150, 5.0, null, null, null),
LinearSales(37, 10, 4.5, null, null, null),
// Render a hollow circle, filled in with white.
LinearSales(45, 300, 8.0, 'circle', charts.MaterialPalette.white, 2.0),
LinearSales(52, 15, 4.0, null, null, null),
// Render a hollow square, filled in with white.
LinearSales(56, 200, 7.0, null, charts.MaterialPalette.white, 2.0),
];
const maxMeasure = 300;
return [
charts.Series<LinearSales, int>(
id: 'Sales',
// Providing a color function is optional.
colorFn: (LinearSales sales, _) {
// Bucket the measure column value into 3 distinct colors.
final bucket = sales.sales / maxMeasure;
if (bucket < 1 / 3) {
return charts.MaterialPalette.blue.shadeDefault;
} else if (bucket < 2 / 3) {
return charts.MaterialPalette.red.shadeDefault;
} else {
return charts.MaterialPalette.green.shadeDefault;
}
},
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
radiusPxFn: (LinearSales sales, _) => sales.radius,
fillColorFn: (LinearSales row, _) => row.fillColor,
strokeWidthPxFn: (LinearSales row, _) => row.strokeWidth,
data: data,
)
// Accessor function that associates each datum with a symbol renderer.
..setAttribute(
charts.pointSymbolRendererFnKey, (int index) => data[index].shape)
// Default symbol renderer ID for data that have no defined shape.
..setAttribute(charts.pointSymbolRendererIdKey, 'rect')
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
final double radius;
final String? shape;
final charts.Color? fillColor;
final double? strokeWidth;
LinearSales(this.year, this.sales, this.radius, this.shape, this.fillColor,
this.strokeWidth);
}

@ -1,165 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of using user managed state to programmatically set selection.
///
/// In this example, clicking the "clear selection" button sets the selection
/// to an empty selection. This example also shows that initial selection
/// behavior can still be used with user managed state.
///
/// Note that the picture in this example is not interactive, please run the
/// gallery app to try out using the button to clear selection.
///
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SelectionUserManaged extends StatefulWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const SelectionUserManaged(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory SelectionUserManaged.withSampleData() {
return SelectionUserManaged(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SelectionUserManaged.withRandomData() {
return SelectionUserManaged(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
@override
SelectionUserManagedState createState() {
return SelectionUserManagedState();
}
}
class SelectionUserManagedState extends State<SelectionUserManaged> {
final _myState = charts.UserManagedState<String>();
@override
Widget build(BuildContext context) {
final chart = charts.BarChart(
widget.seriesList,
animate: false, //widget.animate,
selectionModels: [
charts.SelectionModelConfig(
type: charts.SelectionModelType.info,
updatedListener: _infoSelectionModelUpdated)
],
// Pass in the state you manage to the chart. This will be used to
// override the internal chart state.
userManagedState: _myState,
// The initial selection can still be optionally added by adding the
// initial selection behavior.
behaviors: [
charts.InitialSelection(selectedDataConfig: [
charts.SeriesDatumConfig<String>('Sales', '2016')
])
],
);
final clearSelection = MaterialButton(
onPressed: _handleClearSelection, child: const Text('Clear Selection'));
return Column(
children: [SizedBox(height: 150.0, child: chart), clearSelection]);
}
void _infoSelectionModelUpdated(charts.SelectionModel<String> model) {
// If you want to allow the chart to continue to respond to select events
// that update the selection, add an updatedListener that saves off the
// selection model each time the selection model is updated, regardless of
// if there are changes.
//
// This also allows you to listen to the selection model update events and
// alter the selection.
_myState.selectionModels[charts.SelectionModelType.info] =
charts.UserManagedSelectionModel(model: model);
}
void _handleClearSelection() {
// Call set state to request a rebuild, to pass in the modified selection.
// In this case, passing in an empty [UserManagedSelectionModel] creates a
// no selection model to clear all selection when rebuilt.
setState(() {
_myState.selectionModels[charts.SelectionModelType.info] =
charts.UserManagedSelectionModel();
});
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,195 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
/// This is just a simple line chart with a behavior that adds slider controls.
///
/// A [Slider] behavior is added manually to enable slider controls, with an
/// initial position at 1 along the domain axis.
///
/// An onChange event handler has been configured to demonstrate updating a div
/// with data from the slider's current position. An "initial" drag state event
/// will be fired when the chart is drawn because an initial domain value is
/// set.
///
/// [Slider.moveSliderToDomain] can be called to programmatically position the
/// slider. This is useful for synchronizing the slider with external elements.
class SliderLine extends StatefulWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SliderLine(this.seriesList, {this.animate, Key? key}) : super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory SliderLine.withSampleData() {
return SliderLine(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SliderLine.withRandomData() {
return SliderLine(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
// We need a Stateful widget to build the selection details with the current
// selection as the state.
@override
State<StatefulWidget> createState() => _SliderCallbackState();
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
class _SliderCallbackState extends State<SliderLine> {
num? _sliderDomainValue;
String? _sliderDragState;
Point<int>? _sliderPosition;
// Handles callbacks when the user drags the slider.
_onSliderChange(Point<int> point, dynamic domain, String roleId,
charts.SliderListenerDragState dragState) {
// Request a build.
void rebuild(_) {
setState(() {
_sliderDomainValue = (domain * 10).round() / 10;
_sliderDragState = dragState.toString();
_sliderPosition = point;
});
}
SchedulerBinding.instance.addPostFrameCallback(rebuild);
}
@override
Widget build(BuildContext context) {
// The children consist of a Chart and Text widgets below to hold the info.
final children = <Widget>[
SizedBox(
height: 150.0,
child: charts.LineChart(
widget.seriesList,
animate: widget.animate,
// Configures a [Slider] behavior.
//
// Available options include:
//
// [eventTrigger] configures the type of mouse gesture that controls
// the slider.
//
// [handleRenderer] draws a handle for the slider. Defaults to a
// rectangle.
//
// [initialDomainValue] sets the initial position of the slider in
// domain units. The default is the center of the chart.
//
// [onChangeCallback] will be called when the position of the slider
// changes during a drag event.
//
// [roleId] optional custom role ID for the slider. This can be used to
// allow multiple [Slider] behaviors on the same chart. Normally, there can
// only be one slider (per event trigger type) on a chart. This setting
// allows for configuring multiple independent sliders.
//
// [snapToDatum] configures the slider to snap snap onto the nearest
// datum (by domain distance) when dragged. By default, the slider
// can be positioned anywhere along the domain axis.
//
// [style] takes in a [SliderStyle] configuration object, and
// configures the color and sizing of the slider line and handle.
behaviors: [
charts.Slider(
initialDomainValue: 1.0, onChangeCallback: _onSliderChange),
],
)),
];
// If there is a slider change event, then include the details.
if (_sliderDomainValue != null) {
children.add(Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Text('Slider domain value: $_sliderDomainValue')));
}
if (_sliderPosition != null) {
children.add(Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Text(
'Slider position: ${_sliderPosition!.x}, ${_sliderPosition!.y}')));
}
if (_sliderDragState != null) {
children.add(Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Text('Slider drag state: $_sliderDragState')));
}
return Column(children: children);
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,145 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of the chart behavior that centers the viewport on domain selection.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SlidingViewportOnSelection extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const SlidingViewportOnSelection(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory SlidingViewportOnSelection.withSampleData() {
return SlidingViewportOnSelection(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SlidingViewportOnSelection.withRandomData() {
return SlidingViewportOnSelection(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
OrdinalSales('2018', random.nextInt(100)),
OrdinalSales('2019', random.nextInt(100)),
OrdinalSales('2020', random.nextInt(100)),
OrdinalSales('2021', random.nextInt(100)),
OrdinalSales('2022', random.nextInt(100)),
OrdinalSales('2023', random.nextInt(100)),
OrdinalSales('2024', random.nextInt(100)),
OrdinalSales('2025', random.nextInt(100)),
OrdinalSales('2026', random.nextInt(100)),
OrdinalSales('2027', random.nextInt(100)),
OrdinalSales('2028', random.nextInt(100)),
OrdinalSales('2029', random.nextInt(100)),
OrdinalSales('2030', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
behaviors: [
// Add the sliding viewport behavior to have the viewport center on the
// domain that is currently selected.
charts.SlidingViewport(),
// A pan and zoom behavior helps demonstrate the sliding viewport
// behavior by allowing the data visible in the viewport to be adjusted
// dynamically.
charts.PanAndZoomBehavior(),
],
// Set an initial viewport to demonstrate the sliding viewport behavior on
// initial chart load.
domainAxis:
charts.OrdinalAxisSpec(viewport: charts.OrdinalViewport('2018', 4)),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
OrdinalSales('2018', 33),
OrdinalSales('2019', 80),
OrdinalSales('2020', 21),
OrdinalSales('2021', 77),
OrdinalSales('2022', 8),
OrdinalSales('2023', 12),
OrdinalSales('2024', 42),
OrdinalSales('2025', 70),
OrdinalSales('2026', 77),
OrdinalSales('2027', 55),
OrdinalSales('2028', 19),
OrdinalSales('2029', 66),
OrdinalSales('2030', 27),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,57 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'date_time_line_point.dart';
import 'numeric_line_bar.dart';
import 'numeric_line_point.dart';
import 'ordinal_bar_line.dart';
import 'scatter_plot_line.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Ordinal Combo Chart',
subtitle: 'Ordinal combo chart with bars and lines',
childBuilder: () => OrdinalComboBarLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Numeric Line Bar Combo Chart',
subtitle: 'Numeric combo chart with lines and bars',
childBuilder: () => NumericComboLineBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Numeric Line Points Combo Chart',
subtitle: 'Numeric combo chart with lines and points',
childBuilder: () => NumericComboLinePointChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Time Series Combo Chart',
subtitle: 'Time series combo chart with lines and points',
childBuilder: () => DateTimeComboLinePointChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.scatter_plot),
title: 'Scatter Plot Combo Chart',
subtitle: 'Scatter plot combo chart with a line',
childBuilder: () => ScatterPlotComboLineChart.withRandomData(),
),
];
}

@ -1,184 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a combo time series chart with two series rendered as lines, and
/// a third rendered as points along the top line with a different color.
///
/// This example demonstrates a method for drawing points along a line using a
/// different color from the main series color. The line renderer supports
/// drawing points with the "includePoints" option, but those points will share
/// the same color as the line.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class DateTimeComboLinePointChart extends StatelessWidget {
final List<charts.Series<dynamic, DateTime>> seriesList;
final bool? animate;
const DateTimeComboLinePointChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory DateTimeComboLinePointChart.withSampleData() {
return DateTimeComboLinePointChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DateTimeComboLinePointChart.withRandomData() {
return DateTimeComboLinePointChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createRandomData() {
final random = Random();
final desktopSalesData = [
TimeSeriesSales(DateTime(2017, 9, 19), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 9, 26), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 3), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 10), random.nextInt(100)),
];
final tableSalesData = [
TimeSeriesSales(DateTime(2017, 9, 19), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 9, 26), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 3), random.nextInt(100)),
TimeSeriesSales(DateTime(2017, 10, 10), random.nextInt(100)),
];
final mobileSalesData = [
TimeSeriesSales(DateTime(2017, 9, 19), tableSalesData[0].sales),
TimeSeriesSales(DateTime(2017, 9, 26), tableSalesData[1].sales),
TimeSeriesSales(DateTime(2017, 10, 3), tableSalesData[2].sales),
TimeSeriesSales(DateTime(2017, 10, 10), tableSalesData[3].sales),
];
return [
charts.Series<TimeSeriesSales, DateTime>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<TimeSeriesSales, DateTime>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<TimeSeriesSales, DateTime>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: mobileSalesData)
// Configure our custom point renderer for this series.
..setAttribute(charts.rendererIdKey, 'customPoint'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.TimeSeriesChart(
seriesList,
animate: animate,
// Configure the default renderer as a line renderer. This will be used
// for any series that does not define a rendererIdKey.
//
// This is the default configuration, but is shown here for illustration.
defaultRenderer: charts.LineRendererConfig(),
// Custom renderer configuration for the point series.
customSeriesRenderers: [
charts.PointRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customPoint')
],
// Optionally pass in a [DateTimeFactory] used by the chart. The factory
// should create the same type of [DateTime] as the data provided. If none
// specified, the default creates local date time.
dateTimeFactory: const charts.LocalDateTimeFactory(),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
final desktopSalesData = [
TimeSeriesSales(DateTime(2017, 9, 19), 5),
TimeSeriesSales(DateTime(2017, 9, 26), 25),
TimeSeriesSales(DateTime(2017, 10, 3), 100),
TimeSeriesSales(DateTime(2017, 10, 10), 75),
];
final tableSalesData = [
TimeSeriesSales(DateTime(2017, 9, 19), 10),
TimeSeriesSales(DateTime(2017, 9, 26), 50),
TimeSeriesSales(DateTime(2017, 10, 3), 200),
TimeSeriesSales(DateTime(2017, 10, 10), 150),
];
final mobileSalesData = [
TimeSeriesSales(DateTime(2017, 9, 19), 10),
TimeSeriesSales(DateTime(2017, 9, 26), 50),
TimeSeriesSales(DateTime(2017, 10, 3), 200),
TimeSeriesSales(DateTime(2017, 10, 10), 150),
];
return [
charts.Series<TimeSeriesSales, DateTime>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<TimeSeriesSales, DateTime>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<TimeSeriesSales, DateTime>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: mobileSalesData)
// Configure our custom point renderer for this series.
..setAttribute(charts.rendererIdKey, 'customPoint'),
];
}
}
/// Sample time series data type.
class TimeSeriesSales {
final DateTime time;
final int sales;
TimeSeriesSales(this.time, this.sales);
}

@ -1,175 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a numeric combo chart with two series rendered as bars, and a
/// third rendered as a line.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class NumericComboLineBarChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const NumericComboLineBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory NumericComboLineBarChart.withSampleData() {
return NumericComboLineBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory NumericComboLineBarChart.withRandomData() {
return NumericComboLineBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final desktopSalesData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
final tableSalesData = [
LinearSales(0, desktopSalesData[0].sales),
LinearSales(1, desktopSalesData[1].sales),
LinearSales(2, desktopSalesData[2].sales),
LinearSales(3, desktopSalesData[3].sales),
];
final mobileSalesData = [
LinearSales(0, tableSalesData[0].sales * 2),
LinearSales(1, tableSalesData[1].sales * 2),
LinearSales(2, tableSalesData[2].sales * 2),
LinearSales(3, tableSalesData[3].sales * 2),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: desktopSalesData,
)
// Configure our custom bar renderer for this series.
..setAttribute(charts.rendererIdKey, 'customBar'),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: tableSalesData,
)
// Configure our custom bar renderer for this series.
..setAttribute(charts.rendererIdKey, 'customBar'),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: mobileSalesData),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.NumericComboChart(seriesList,
animate: animate,
// Configure the default renderer as a line renderer. This will be used
// for any series that does not define a rendererIdKey.
defaultRenderer: charts.LineRendererConfig(),
// Custom renderer configuration for the bar series.
customSeriesRenderers: [
charts.BarRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customBar')
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final desktopSalesData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
final tableSalesData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
final mobileSalesData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: desktopSalesData,
)
// Configure our custom bar renderer for this series.
..setAttribute(charts.rendererIdKey, 'customBar'),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: tableSalesData,
)
// Configure our custom bar renderer for this series.
..setAttribute(charts.rendererIdKey, 'customBar'),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: mobileSalesData),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,176 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a numeric combo chart with two series rendered as lines, and a
/// third rendered as points along the top line with a different color.
///
/// This example demonstrates a method for drawing points along a line using a
/// different color from the main series color. The line renderer supports
/// drawing points with the "includePoints" option, but those points will share
/// the same color as the line.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class NumericComboLinePointChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const NumericComboLinePointChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory NumericComboLinePointChart.withSampleData() {
return NumericComboLinePointChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory NumericComboLinePointChart.withRandomData() {
return NumericComboLinePointChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final desktopSalesData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
final tableSalesData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
final mobileSalesData = [
LinearSales(0, tableSalesData[0].sales),
LinearSales(1, tableSalesData[1].sales),
LinearSales(2, tableSalesData[2].sales),
LinearSales(3, tableSalesData[3].sales),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: mobileSalesData)
// Configure our custom point renderer for this series.
..setAttribute(charts.rendererIdKey, 'customPoint'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.NumericComboChart(seriesList,
animate: animate,
// Configure the default renderer as a line renderer. This will be used
// for any series that does not define a rendererIdKey.
defaultRenderer: charts.LineRendererConfig(),
// Custom renderer configuration for the point series.
customSeriesRenderers: [
charts.PointRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customPoint')
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final desktopSalesData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
final tableSalesData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
final mobileSalesData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: tableSalesData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: mobileSalesData)
// Configure our custom point renderer for this series.
..setAttribute(charts.rendererIdKey, 'customPoint'),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,167 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of an ordinal combo chart with two series rendered as bars, and a
/// third rendered as a line.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class OrdinalComboBarLineChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const OrdinalComboBarLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory OrdinalComboBarLineChart.withSampleData() {
return OrdinalComboBarLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory OrdinalComboBarLineChart.withRandomData() {
return OrdinalComboBarLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tableSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData)
// Configure our custom line renderer for this series.
..setAttribute(charts.rendererIdKey, 'customLine'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.OrdinalComboChart(seriesList,
animate: animate,
// Configure the default renderer as a bar renderer.
defaultRenderer: charts.BarRendererConfig(
groupingType: charts.BarGroupingType.grouped),
// Custom renderer configuration for the line series. This will be used for
// any series that does not define a rendererIdKey.
customSeriesRenderers: [
charts.LineRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customLine')
]);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tableSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 50),
OrdinalSales('2016', 200),
OrdinalSales('2017', 150),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tableSalesData),
charts.Series<OrdinalSales, String>(
id: 'Mobile ',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData)
// Configure our custom line renderer for this series.
..setAttribute(charts.rendererIdKey, 'customLine'),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,199 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a combo scatter plot chart with a second series rendered as a
/// line.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class ScatterPlotComboLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const ScatterPlotComboLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [ScatterPlotChart] with sample data and no transition.
factory ScatterPlotComboLineChart.withSampleData() {
return ScatterPlotComboLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory ScatterPlotComboLineChart.withRandomData() {
return ScatterPlotComboLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
makeRadius(int value) => (random.nextInt(value) + 2).toDouble();
final desktopSalesData = [
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6)),
];
var myRegressionData = [
LinearSales(0, desktopSalesData[0].sales, 3.5),
LinearSales(
100, desktopSalesData[desktopSalesData.length - 1].sales, 7.5),
];
const maxMeasure = 100;
return [
charts.Series<LinearSales, int>(
id: 'Sales',
// Providing a color function is optional.
colorFn: (LinearSales sales, _) {
// Bucket the measure column value into 3 distinct colors.
final bucket = sales.sales / maxMeasure;
if (bucket < 1 / 3) {
return charts.MaterialPalette.blue.shadeDefault;
} else if (bucket < 2 / 3) {
return charts.MaterialPalette.red.shadeDefault;
} else {
return charts.MaterialPalette.green.shadeDefault;
}
},
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
// Providing a radius function is optional.
radiusPxFn: (LinearSales sales, _) => sales.radius,
data: desktopSalesData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myRegressionData)
// Configure our custom line renderer for this series.
..setAttribute(charts.rendererIdKey, 'customLine'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.ScatterPlotChart(seriesList,
animate: animate,
// Configure the default renderer as a point renderer. This will be used
// for any series that does not define a rendererIdKey.
//
// This is the default configuration, but is shown here for
// illustration.
defaultRenderer: charts.PointRendererConfig(),
// Custom renderer configuration for the line series.
customSeriesRenderers: [
charts.LineRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customLine',
// Configure the regression line to be painted above the points.
//
// By default, series drawn by the point renderer are painted on
// top of those drawn by a line renderer.
layoutPaintOrder: charts.LayoutViewPaintOrder.point + 1)
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final desktopSalesData = [
LinearSales(0, 5, 3.0),
LinearSales(10, 25, 5.0),
LinearSales(12, 75, 4.0),
LinearSales(13, 225, 5.0),
LinearSales(16, 50, 4.0),
LinearSales(24, 75, 3.0),
LinearSales(25, 100, 3.0),
LinearSales(34, 150, 5.0),
LinearSales(37, 10, 4.5),
LinearSales(45, 300, 8.0),
LinearSales(52, 15, 4.0),
LinearSales(56, 200, 7.0),
];
var myRegressionData = [
LinearSales(0, 5, 3.5),
LinearSales(56, 240, 3.5),
];
const maxMeasure = 300;
return [
charts.Series<LinearSales, int>(
id: 'Sales',
// Providing a color function is optional.
colorFn: (LinearSales sales, _) {
// Bucket the measure column value into 3 distinct colors.
final bucket = sales.sales / maxMeasure;
if (bucket < 1 / 3) {
return charts.MaterialPalette.blue.shadeDefault;
} else if (bucket < 2 / 3) {
return charts.MaterialPalette.red.shadeDefault;
} else {
return charts.MaterialPalette.green.shadeDefault;
}
},
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
// Providing a radius function is optional.
radiusPxFn: (LinearSales sales, _) => sales.radius,
data: desktopSalesData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myRegressionData)
// Configure our custom line renderer for this series.
..setAttribute(charts.rendererIdKey, 'customLine'),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
final double radius;
LinearSales(this.year, this.sales, this.radius);
}

@ -1,51 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
/// A menu drawer supporting toggling theme and performance overlay.
class GalleryDrawer extends StatelessWidget {
final bool showPerformanceOverlay;
final ValueChanged<bool> onShowPerformanceOverlayChanged;
const GalleryDrawer(
{Key? key,
required this.showPerformanceOverlay,
required this.onShowPerformanceOverlayChanged})
: super(key: key);
@override
Widget build(BuildContext context) {
return Drawer(
child: ListView(children: [
// Performance overlay toggle.
ListTile(
leading: const Icon(Icons.assessment),
title: const Text('Performance Overlay'),
onTap: () {
onShowPerformanceOverlayChanged(!showPerformanceOverlay);
},
selected: showPerformanceOverlay,
trailing: Checkbox(
value: showPerformanceOverlay,
onChanged: (bool? value) {
onShowPerformanceOverlayChanged(!showPerformanceOverlay);
},
),
),
]),
);
}
}

@ -1,67 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
typedef GalleryWidgetBuilder = Widget Function();
/// Helper to build gallery.
class GalleryScaffold extends StatefulWidget {
/// The widget used for leading in a [ListTile].
final Widget? listTileIcon;
final String title;
final String subtitle;
final GalleryWidgetBuilder childBuilder;
const GalleryScaffold(
{this.listTileIcon,
required this.title,
required this.subtitle,
required this.childBuilder,
Key? key})
: super(key: key);
/// Gets the gallery
Widget buildGalleryListTile(BuildContext context) => ListTile(
leading: listTileIcon,
title: Text(title),
subtitle: Text(subtitle),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) => this));
});
@override
State<GalleryScaffold> createState() => _GalleryScaffoldState();
}
class _GalleryScaffoldState extends State<GalleryScaffold> {
void _handleButtonPress() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(children: [
SizedBox(height: 250.0, child: widget.childBuilder()),
])),
floatingActionButton: FloatingActionButton(
onPressed: _handleButtonPress, child: const Icon(Icons.refresh)),
);
}
}

@ -1,125 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'dart:developer';
import 'app_config.dart';
import 'drawer.dart';
import 'a11y/a11y_gallery.dart' as a11y show buildGallery;
import 'bar_chart/bar_gallery.dart' as bar show buildGallery;
import 'time_series_chart/time_series_gallery.dart' as time_series
show buildGallery;
import 'line_chart/line_gallery.dart' as line show buildGallery;
import 'scatter_plot_chart/scatter_plot_gallery.dart' as scatter_plot
show buildGallery;
import 'combo_chart/combo_gallery.dart' as combo show buildGallery;
import 'pie_chart/pie_gallery.dart' as pie show buildGallery;
import 'axes/axes_gallery.dart' as axes show buildGallery;
import 'behaviors/behaviors_gallery.dart' as behaviors show buildGallery;
import 'i18n/i18n_gallery.dart' as i18n show buildGallery;
import 'legends/legends_gallery.dart' as legends show buildGallery;
/// Main entry point of the gallery app.
///
/// This renders a list of all available demos.
class Home extends StatelessWidget {
final bool showPerformanceOverlay;
final ValueChanged<bool> onShowPerformanceOverlayChanged;
final a11yGalleries = a11y.buildGallery();
final barGalleries = bar.buildGallery();
final timeSeriesGalleries = time_series.buildGallery();
final lineGalleries = line.buildGallery();
final scatterPlotGalleries = scatter_plot.buildGallery();
final comboGalleries = combo.buildGallery();
final pieGalleries = pie.buildGallery();
final axesGalleries = axes.buildGallery();
final behaviorsGalleries = behaviors.buildGallery();
final i18nGalleries = i18n.buildGallery();
final legendsGalleries = legends.buildGallery();
Home(
{Key? key,
required this.showPerformanceOverlay,
required this.onShowPerformanceOverlayChanged})
: super(key: key);
@override
Widget build(BuildContext context) {
var galleries = <Widget>[];
galleries.addAll(
a11yGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example bar charts.
galleries.addAll(
barGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example time series charts.
galleries.addAll(timeSeriesGalleries
.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example line charts.
galleries.addAll(
lineGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example scatter plot charts.
galleries.addAll(scatterPlotGalleries
.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example pie charts.
galleries.addAll(
comboGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example pie charts.
galleries.addAll(
pieGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
// Add example custom axis.
galleries.addAll(
axesGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
galleries.addAll(behaviorsGalleries
.map((gallery) => gallery.buildGalleryListTile(context)));
// Add legends examples
galleries.addAll(legendsGalleries
.map((gallery) => gallery.buildGalleryListTile(context)));
// Add examples for i18n.
galleries.addAll(
i18nGalleries.map((gallery) => gallery.buildGalleryListTile(context)));
_setupPerformance();
return Scaffold(
drawer: GalleryDrawer(
showPerformanceOverlay: showPerformanceOverlay,
onShowPerformanceOverlayChanged: onShowPerformanceOverlayChanged),
appBar: AppBar(title: Text(defaultConfig.appName)),
body: ListView(padding: kMaterialListPadding, children: galleries),
);
}
void _setupPerformance() {
// Change [printPerformance] to true and set the app to release mode to
// print performance numbers to console. By default, Flutter builds in debug
// mode and this mode is slow. To build in release mode, specify the flag
// blaze-run flag "--define flutter_build_mode=release".
// The build target must also be an actual device and not the emulator.
charts.Performance.time = (String tag) => Timeline.startSync(tag);
charts.Performance.timeEnd = (_) => Timeline.finishSync();
}
}

@ -1,50 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'rtl_bar_chart.dart';
import 'rtl_line_chart.dart';
import 'rtl_line_segments.dart';
import 'rtl_series_legend.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'RTL Bar Chart',
subtitle: 'Simple bar chart in RTL',
childBuilder: () => RTLBarChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'RTL Line Chart',
subtitle: 'Simple line chart in RTL',
childBuilder: () => RTLLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'RTL Line Segments',
subtitle: 'Stacked area chart with style segments in RTL',
childBuilder: () => RTLLineSegments.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.flag),
title: 'RTL Series Legend',
subtitle: 'Series legend in RTL',
childBuilder: () => RTLSeriesLegend.withRandomData(),
),
];
}

@ -1,120 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// RTL Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class RTLBarChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const RTLBarChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory RTLBarChart.withSampleData() {
return RTLBarChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory RTLBarChart.withRandomData() {
return RTLBarChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final data = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// Charts will determine if RTL is enabled by checking the directionality by
// requesting Directionality.of(context). This returns the text direction
// from the closest instance of that encloses the context passed to build
// the chart. A [TextDirection.rtl] will be treated as a RTL chart. This
// means that the directionality widget does not have to directly wrap each
// chart. It is show here as an example only.
//
// By default, when a chart detects RTL:
// Measure axis positions are flipped. Primary measure axis is on the right
// and the secondary measure axis is on the left (when used).
// Domain axis' first domain starts on the right and grows left.
//
// Optionally, [RTLSpec] can be passed in when creating the chart to specify
// chart display settings in RTL mode.
return Directionality(
textDirection: TextDirection.rtl,
child: charts.BarChart(
seriesList,
animate: animate,
vertical: false,
));
}
/// Create one series with sample hard coded data.
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final data = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Sales',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,116 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// RTL Line chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class RTLLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const RTLLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory RTLLineChart.withSampleData() {
return RTLLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory RTLLineChart.withRandomData() {
return RTLLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// Charts will determine if RTL is enabled by checking the directionality by
// requesting Directionality.of(context). This returns the text direction
// from the closest instance of that encloses the context passed to build
// the chart. A [TextDirection.rtl] will be treated as a RTL chart. This
// means that the directionality widget does not have to directly wrap each
// chart. It is show here as an example only.
//
// By default, when a chart detects RTL:
// Measure axis positions are flipped. Primary measure axis is on the right
// and the secondary measure axis is on the left (when used).
// Domain axis' first domain starts on the right and grows left.
return Directionality(
textDirection: TextDirection.rtl,
child: charts.LineChart(
seriesList,
animate: animate,
));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,249 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a RTL stacked area chart with changing styles within each line.
///
/// Each series of data in this example contains different values for color,
/// dashPattern, or strokeWidthPx between each datum. The line and area skirt
/// will be rendered in segments, with the styling of the series changing when
/// these data attributes change.
///
/// Note that if a dashPattern or strokeWidth value is not found for a
/// particular datum, then the chart will fall back to use the value defined in
/// the [charts.LineRendererConfig]. This could be used, for example, to define
/// a default dash pattern for the series, with only a specific datum called out
/// with a different pattern.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class RTLLineSegments extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const RTLLineSegments(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory RTLLineSegments.withSampleData() {
return RTLLineSegments(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory RTLLineSegments.withRandomData() {
return RTLLineSegments(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
// Series of data with static dash pattern and stroke width. The colorFn
// accessor will colorize each datum (for all three series).
final colorChangeData = [
LinearSales(0, random.nextInt(100), null, 2.0),
LinearSales(1, random.nextInt(100), null, 2.0),
LinearSales(2, random.nextInt(100), null, 2.0),
LinearSales(3, random.nextInt(100), null, 2.0),
LinearSales(4, random.nextInt(100), null, 2.0),
LinearSales(5, random.nextInt(100), null, 2.0),
LinearSales(6, random.nextInt(100), null, 2.0),
];
// Series of data with changing color and dash pattern.
final dashPatternChangeData = [
LinearSales(0, random.nextInt(100), [2, 2], 2.0),
LinearSales(1, random.nextInt(100), [2, 2], 2.0),
LinearSales(2, random.nextInt(100), [4, 4], 2.0),
LinearSales(3, random.nextInt(100), [4, 4], 2.0),
LinearSales(4, random.nextInt(100), [4, 4], 2.0),
LinearSales(5, random.nextInt(100), [8, 3, 2, 3], 2.0),
LinearSales(6, random.nextInt(100), [8, 3, 2, 3], 2.0),
];
// Series of data with changing color and stroke width.
final strokeWidthChangeData = [
LinearSales(0, random.nextInt(100), null, 2.0),
LinearSales(1, random.nextInt(100), null, 2.0),
LinearSales(2, random.nextInt(100), null, 4.0),
LinearSales(3, random.nextInt(100), null, 4.0),
LinearSales(4, random.nextInt(100), null, 4.0),
LinearSales(5, random.nextInt(100), null, 6.0),
LinearSales(6, random.nextInt(100), null, 6.0),
];
// Generate 2 shades of each color so that we can style the line segments.
final blue = charts.MaterialPalette.blue.makeShades(2);
final red = charts.MaterialPalette.red.makeShades(2);
final green = charts.MaterialPalette.green.makeShades(2);
return [
charts.Series<LinearSales, int>(
id: 'Color Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? blue[1] : blue[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: colorChangeData,
),
charts.Series<LinearSales, int>(
id: 'Dash Pattern Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? red[1] : red[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: dashPatternChangeData,
),
charts.Series<LinearSales, int>(
id: 'Stroke Width Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? green[1] : green[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: strokeWidthChangeData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// Charts will determine if RTL is enabled by checking the directionality by
// requesting Directionality.of(context). This returns the text direction
// from the closest instance of that encloses the context passed to build
// the chart. A [TextDirection.rtl] will be treated as a RTL chart. This
// means that the directionality widget does not have to directly wrap each
// chart. It is show here as an example only.
//
// By default, when a chart detects RTL:
// Measure axis positions are flipped. Primary measure axis is on the right
// and the secondary measure axis is on the left (when used).
// Domain axis' first domain starts on the right and grows left.
return Directionality(
textDirection: TextDirection.rtl,
child: charts.LineChart(
seriesList,
defaultRenderer:
charts.LineRendererConfig(includeArea: true, stacked: true),
animate: animate,
));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
// Series of data with static dash pattern and stroke width. The colorFn
// accessor will colorize each datum (for all three series).
final colorChangeData = [
LinearSales(0, 5, null, 2.0),
LinearSales(1, 15, null, 2.0),
LinearSales(2, 25, null, 2.0),
LinearSales(3, 75, null, 2.0),
LinearSales(4, 100, null, 2.0),
LinearSales(5, 90, null, 2.0),
LinearSales(6, 75, null, 2.0),
];
// Series of data with changing color and dash pattern.
final dashPatternChangeData = [
LinearSales(0, 5, [2, 2], 2.0),
LinearSales(1, 15, [2, 2], 2.0),
LinearSales(2, 25, [4, 4], 2.0),
LinearSales(3, 75, [4, 4], 2.0),
LinearSales(4, 100, [4, 4], 2.0),
LinearSales(5, 90, [8, 3, 2, 3], 2.0),
LinearSales(6, 75, [8, 3, 2, 3], 2.0),
];
// Series of data with changing color and stroke width.
final strokeWidthChangeData = [
LinearSales(0, 5, null, 2.0),
LinearSales(1, 15, null, 2.0),
LinearSales(2, 25, null, 4.0),
LinearSales(3, 75, null, 4.0),
LinearSales(4, 100, null, 4.0),
LinearSales(5, 90, null, 6.0),
LinearSales(6, 75, null, 6.0),
];
// Generate 2 shades of each color so that we can style the line segments.
final blue = charts.MaterialPalette.blue.makeShades(2);
final red = charts.MaterialPalette.red.makeShades(2);
final green = charts.MaterialPalette.green.makeShades(2);
return [
charts.Series<LinearSales, int>(
id: 'Color Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? blue[1] : blue[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: colorChangeData,
),
charts.Series<LinearSales, int>(
id: 'Dash Pattern Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? red[1] : red[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: dashPatternChangeData,
),
charts.Series<LinearSales, int>(
id: 'Stroke Width Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? green[1] : green[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: strokeWidthChangeData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
final List<int>? dashPattern;
final double strokeWidthPx;
LinearSales(this.year, this.sales, this.dashPattern, this.strokeWidthPx);
}

@ -1,207 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// RTL Bar chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class RTLSeriesLegend extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const RTLSeriesLegend(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [BarChart] with sample data and no transition.
factory RTLSeriesLegend.withSampleData() {
return RTLSeriesLegend(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory RTLSeriesLegend.withRandomData() {
return RTLSeriesLegend(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tabletSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final otherSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
// Charts will determine if RTL is enabled by checking the directionality by
// requesting Directionality.of(context). This returns the text direction
// from the closest instance of that encloses the context passed to build
// the chart. A [TextDirection.rtl] will be treated as a RTL chart. This
// means that the directionality widget does not have to directly wrap each
// chart. It is show here as an example only.
//
// When the legend behavior detects RTL:
// [BehaviorPosition.start] is to the right of the chart.
// [BehaviorPosition.end] is to the left of the chart.
//
// If the [BehaviorPosition] is top or bottom, the start justification
// is to the right, and the end justification is to the left.
//
// The legend's tabular layout will also layout rows and columns from right
// to left.
//
// The below example changes the position to 'start' and max rows of 2 in
// order to show these effects, but are not required for SeriesLegend to
// work with the correct directionality.
return Directionality(
textDirection: TextDirection.rtl,
child: charts.BarChart(
seriesList,
animate: animate,
behaviors: [
charts.SeriesLegend(
position: charts.BehaviorPosition.end, desiredMaxRows: 2)
],
));
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final otherSalesData = [
OrdinalSales('2014', 20),
OrdinalSales('2015', 35),
OrdinalSales('2016', 15),
OrdinalSales('2017', 10),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,137 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Pie chart with example of a legend with customized position, justification,
/// desired max rows, padding, and entry text styles. These options are shown as
/// an example of how to use the customizations, they do not necessary have to
/// be used together in this way. Choosing [end] as the position does not
/// require the justification to also be [endDrawArea].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class DatumLegendOptions extends StatelessWidget {
final List<charts.Series<dynamic, int>> seriesList;
final bool? animate;
const DatumLegendOptions(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory DatumLegendOptions.withSampleData() {
return DatumLegendOptions(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DatumLegendOptions.withRandomData() {
return DatumLegendOptions(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, int>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart(
seriesList,
animate: animate,
// Add the legend behavior to the chart to turn on legends.
// This example shows how to change the position and justification of
// the legend, in addition to altering the max rows and padding.
behaviors: [
charts.DatumLegend(
// Positions for "start" and "end" will be left and right respectively
// for widgets with a build context that has directionality ltr.
// For rtl, "start" and "end" will be right and left respectively.
// Since this example has directionality of ltr, the legend is
// positioned on the right side of the chart.
position: charts.BehaviorPosition.end,
// For a legend that is positioned on the left or right of the chart,
// setting the justification for [endDrawArea] is aligned to the
// bottom of the chart draw area.
outsideJustification: charts.OutsideJustification.endDrawArea,
// By default, if the position of the chart is on the left or right of
// the chart, [horizontalFirst] is set to false. This means that the
// legend entries will grow as new rows first instead of a new column.
horizontalFirst: false,
// By setting this value to 2, the legend entries will grow up to two
// rows before adding a new column.
desiredMaxRows: 2,
// This defines the padding around each legend entry.
cellPadding: const EdgeInsets.only(right: 4.0, bottom: 4.0),
// Render the legend entry text with custom styles.
entryTextStyle: charts.TextStyleSpec(
color: charts.MaterialPalette.purple.shadeDefault,
fontFamily: 'Georgia',
fontSize: 11),
)
],
);
}
/// Create series list with one series
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 100),
LinearSales(1, 75),
LinearSales(2, 25),
LinearSales(3, 5),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,147 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with example of a legend with customized position, justification,
/// desired max rows, and padding. These options are shown as an example of how
/// to use the customizations, they do not necessary have to be used together in
/// this way. Choosing [end] as the position does not require the justification
/// to also be [endDrawArea].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example that shows how to build a datum legend that shows measure values.
///
/// Also shows the option to provide a custom measure formatter.
class DatumLegendWithMeasures extends StatelessWidget {
final List<charts.Series<LinearSales, int>> seriesList;
final bool? animate;
const DatumLegendWithMeasures(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory DatumLegendWithMeasures.withSampleData() {
return DatumLegendWithMeasures(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DatumLegendWithMeasures.withRandomData() {
return DatumLegendWithMeasures(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, int>> _createRandomData() {
final random = Random();
final data = [
LinearSales(2014, random.nextInt(100)),
LinearSales(2015, random.nextInt(100)),
LinearSales(2016, random.nextInt(100)),
LinearSales(2017, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart<int>(
seriesList,
animate: animate,
// Add the legend behavior to the chart to turn on legends.
// This example shows how to optionally show measure and provide a custom
// formatter.
behaviors: [
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// This is added in order to generate the image for the gallery to show
// an initial selection so that measure values are shown in the gallery.
charts.InitialSelection(
selectedDataConfig: [
charts.SeriesDatumConfig('Sales', 0),
],
),
// EXCLUDE_FROM_GALLERY_DOCS_END
charts.DatumLegend(
// Positions for "start" and "end" will be left and right respectively
// for widgets with a build context that has directionality ltr.
// For rtl, "start" and "end" will be right and left respectively.
// Since this example has directionality of ltr, the legend is
// positioned on the right side of the chart.
position: charts.BehaviorPosition.end,
// By default, if the position of the chart is on the left or right of
// the chart, [horizontalFirst] is set to false. This means that the
// legend entries will grow as new rows first instead of a new column.
horizontalFirst: false,
// This defines the padding around each legend entry.
cellPadding: const EdgeInsets.only(right: 4.0, bottom: 4.0),
// Set [showMeasures] to true to display measures in series legend.
showMeasures: true,
// Configure the measure value to be shown by default in the legend.
legendDefaultMeasure: charts.LegendDefaultMeasure.firstValue,
// Optionally provide a measure formatter to format the measure value.
// If none is specified the value is formatted as a decimal.
measureFormatter: (num? value) {
return value == null ? '-' : '${value}k';
},
),
],
);
}
/// Create series list with one series
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(2014, 100),
LinearSales(2015, 75),
LinearSales(2016, 25),
LinearSales(2017, 5),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,189 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with default hidden series legend example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class DefaultHiddenSeriesLegend extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const DefaultHiddenSeriesLegend(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory DefaultHiddenSeriesLegend.withSampleData() {
return DefaultHiddenSeriesLegend(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DefaultHiddenSeriesLegend.withRandomData() {
return DefaultHiddenSeriesLegend(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tabletSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final otherSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// Add the series legend behavior to the chart to turn on series legends.
// By default the legend will display above the chart.
behaviors: [
charts.SeriesLegend(
// Configures the "Other" series to be hidden on first chart draw.
defaultHiddenSeries: const ['Other'],
)
],
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final otherSalesData = [
OrdinalSales('2014', 20),
OrdinalSales('2015', 35),
OrdinalSales('2016', 15),
OrdinalSales('2017', 10),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,211 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with custom symbol in legend example.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example custom renderer that renders [IconData].
///
/// This is used to show that legend symbols can be assigned a custom symbol.
class IconRenderer extends charts.CustomSymbolRenderer {
final IconData iconData;
IconRenderer(this.iconData);
@override
Widget build(BuildContext context,
{Size? size, Color? color, bool enabled = true}) {
// Lighten the color if the symbol is not enabled
// Example: If user has tapped on a Series deselecting it.
if (!enabled) {
color = color!.withOpacity(0.26);
}
return SizedBox.fromSize(
size: size, child: Icon(iconData, color: color, size: 12.0));
}
}
class LegendWithCustomSymbol extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const LegendWithCustomSymbol(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory LegendWithCustomSymbol.withSampleData() {
return LegendWithCustomSymbol(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LegendWithCustomSymbol.withRandomData() {
return LegendWithCustomSymbol(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tabletSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final otherSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// Add the legend behavior to the chart to turn on legends.
// By default the legend will display above the chart.
//
// To change the symbol used in the legend, set the renderer attribute of
// symbolRendererKey to a SymbolRenderer.
behaviors: [charts.SeriesLegend()],
defaultRenderer:
charts.BarRendererConfig(symbolRenderer: IconRenderer(Icons.cloud)),
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final otherSalesData = [
OrdinalSales('2014', 20),
OrdinalSales('2015', 35),
OrdinalSales('2016', 15),
OrdinalSales('2017', 10),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
)
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,80 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'datum_legend_options.dart';
import 'datum_legend_with_measures.dart';
import 'default_hidden_series_legend.dart';
import 'legend_custom_symbol.dart';
import 'series_legend_options.dart';
import 'series_legend_with_measures.dart';
import 'simple_datum_legend.dart';
import 'simple_series_legend.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Series Legend',
subtitle: 'A series legend for a bar chart with default settings',
childBuilder: () => SimpleSeriesLegend.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Series Legend Options',
subtitle:
'A series legend with custom positioning and spacing for a bar chart',
childBuilder: () => LegendOptions.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Series Legend Custom Symbol',
subtitle: 'A series legend using a custom symbol renderer',
childBuilder: () => LegendWithCustomSymbol.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Default Hidden Series Legend',
subtitle: 'A series legend showing a series hidden by default',
childBuilder: () => DefaultHiddenSeriesLegend.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.insert_chart),
title: 'Series legend with measures',
subtitle: 'Series legend with measures and measure formatting',
childBuilder: () => LegendWithMeasures.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.pie_chart),
title: 'Datum Legend',
subtitle: 'A datum legend for a pie chart with default settings',
childBuilder: () => SimpleDatumLegend.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.pie_chart),
title: 'Datum Legend Options',
subtitle:
'A datum legend with custom positioning and spacing for a pie chart',
childBuilder: () => DatumLegendOptions.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.pie_chart),
title: 'Datum legend with measures',
subtitle: 'Datum legend with measures and measure formatting',
childBuilder: () => DatumLegendWithMeasures.withRandomData(),
),
];
}

@ -1,216 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with example of a legend with customized position, justification,
/// desired max rows, padding, and entry text styles. These options are shown as
/// an example of how to use the customizations, they do not necessary have to
/// be used together in this way. Choosing [end] as the position does not
/// require the justification to also be [endDrawArea].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class LegendOptions extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const LegendOptions(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory LegendOptions.withSampleData() {
return LegendOptions(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LegendOptions.withRandomData() {
return LegendOptions(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final otherSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// Add the legend behavior to the chart to turn on legends.
// This example shows how to change the position and justification of
// the legend, in addition to altering the max rows and padding.
behaviors: [
charts.SeriesLegend(
// Positions for "start" and "end" will be left and right respectively
// for widgets with a build context that has directionality ltr.
// For rtl, "start" and "end" will be right and left respectively.
// Since this example has directionality of ltr, the legend is
// positioned on the right side of the chart.
position: charts.BehaviorPosition.end,
// For a legend that is positioned on the left or right of the chart,
// setting the justification for [endDrawArea] is aligned to the
// bottom of the chart draw area.
outsideJustification: charts.OutsideJustification.endDrawArea,
// By default, if the position of the chart is on the left or right of
// the chart, [horizontalFirst] is set to false. This means that the
// legend entries will grow as new rows first instead of a new column.
horizontalFirst: false,
// By setting this value to 2, the legend entries will grow up to two
// rows before adding a new column.
desiredMaxRows: 2,
// This defines the padding around each legend entry.
cellPadding: const EdgeInsets.only(right: 4.0, bottom: 4.0),
// Render the legend entry text with custom styles.
entryTextStyle: charts.TextStyleSpec(
color: charts.MaterialPalette.purple.shadeDefault,
fontFamily: 'Georgia',
fontSize: 11),
)
],
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final otherSalesData = [
OrdinalSales('2014', 20),
OrdinalSales('2015', 35),
OrdinalSales('2016', 15),
OrdinalSales('2017', 10),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,229 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with example of a legend with customized position, justification,
/// desired max rows, and padding. These options are shown as an example of how
/// to use the customizations, they do not necessary have to be used together in
/// this way. Choosing [end] as the position does not require the justification
/// to also be [endDrawArea].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
/// Example that shows how to build a series legend that shows measure values
/// when a datum is selected.
///
/// Also shows the option to provide a custom measure formatter.
class LegendWithMeasures extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const LegendWithMeasures(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory LegendWithMeasures.withSampleData() {
return LegendWithMeasures(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LegendWithMeasures.withRandomData() {
return LegendWithMeasures(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final otherSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// Add the legend behavior to the chart to turn on legends.
// This example shows how to optionally show measure and provide a custom
// formatter.
behaviors: [
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// This is added in order to generate the image for the gallery to show
// an initial selection so that measure values are shown in the gallery.
charts.InitialSelection(
selectedDataConfig: [
charts.SeriesDatumConfig('Desktop', '2016'),
charts.SeriesDatumConfig('Tablet', '2016'),
charts.SeriesDatumConfig('Mobile', '2016'),
charts.SeriesDatumConfig('Other', '2016'),
],
),
// EXCLUDE_FROM_GALLERY_DOCS_END
charts.SeriesLegend(
// Positions for "start" and "end" will be left and right respectively
// for widgets with a build context that has directionality ltr.
// For rtl, "start" and "end" will be right and left respectively.
// Since this example has directionality of ltr, the legend is
// positioned on the right side of the chart.
position: charts.BehaviorPosition.end,
// By default, if the position of the chart is on the left or right of
// the chart, [horizontalFirst] is set to false. This means that the
// legend entries will grow as new rows first instead of a new column.
horizontalFirst: false,
// This defines the padding around each legend entry.
cellPadding: const EdgeInsets.only(right: 4.0, bottom: 4.0),
// Set show measures to true to display measures in series legend,
// when the datum is selected.
showMeasures: true,
// Optionally provide a measure formatter to format the measure value.
// If none is specified the value is formatted as a decimal.
measureFormatter: (num? value) {
return value == null ? '-' : '${value}k';
},
),
],
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
// Purposely have a missing datum for 2016 to show the null measure format
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final otherSalesData = [
OrdinalSales('2014', 20),
OrdinalSales('2015', 35),
OrdinalSales('2016', 15),
OrdinalSales('2017', 10),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,105 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with series legend example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class SimpleDatumLegend extends StatelessWidget {
final List<charts.Series<dynamic, int>> seriesList;
final bool? animate;
const SimpleDatumLegend(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory SimpleDatumLegend.withSampleData() {
return SimpleDatumLegend(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SimpleDatumLegend.withRandomData() {
return SimpleDatumLegend(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, int>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart(
seriesList,
animate: animate,
// Add the series legend behavior to the chart to turn on series legends.
// By default the legend will display above the chart.
behaviors: [charts.DatumLegend()],
);
}
/// Create series list with one series
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 100),
LinearSales(1, 75),
LinearSales(2, 25),
LinearSales(3, 5),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,184 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Bar chart with series legend example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class SimpleSeriesLegend extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const SimpleSeriesLegend(this.seriesList, {this.animate, Key? key})
: super(key: key);
factory SimpleSeriesLegend.withSampleData() {
return SimpleSeriesLegend(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SimpleSeriesLegend.withRandomData() {
return SimpleSeriesLegend(_createRandomData());
}
/// Create random data.
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
final random = Random();
final desktopSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final tabletSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final mobileSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
final otherSalesData = [
OrdinalSales('2014', random.nextInt(100)),
OrdinalSales('2015', random.nextInt(100)),
OrdinalSales('2016', random.nextInt(100)),
OrdinalSales('2017', random.nextInt(100)),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.BarChart(
seriesList,
animate: animate,
barGroupingType: charts.BarGroupingType.grouped,
// Add the series legend behavior to the chart to turn on series legends.
// By default the legend will display above the chart.
behaviors: [charts.SeriesLegend()],
);
}
/// Create series list with multiple series
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
final desktopSalesData = [
OrdinalSales('2014', 5),
OrdinalSales('2015', 25),
OrdinalSales('2016', 100),
OrdinalSales('2017', 75),
];
final tabletSalesData = [
OrdinalSales('2014', 25),
OrdinalSales('2015', 50),
OrdinalSales('2016', 10),
OrdinalSales('2017', 20),
];
final mobileSalesData = [
OrdinalSales('2014', 10),
OrdinalSales('2015', 15),
OrdinalSales('2016', 50),
OrdinalSales('2017', 45),
];
final otherSalesData = [
OrdinalSales('2014', 20),
OrdinalSales('2015', 35),
OrdinalSales('2016', 15),
OrdinalSales('2017', 10),
];
return [
charts.Series<OrdinalSales, String>(
id: 'Desktop',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: desktopSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Tablet',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: tabletSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Mobile',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: mobileSalesData,
),
charts.Series<OrdinalSales, String>(
id: 'Other',
domainFn: (OrdinalSales sales, _) => sales.year,
measureFn: (OrdinalSales sales, _) => sales.sales,
data: otherSalesData,
),
];
}
}
/// Sample ordinal data type.
class OrdinalSales {
final String year;
final int sales;
OrdinalSales(this.year, this.sales);
}

@ -1,102 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a line chart with pan and zoom enabled via
/// [Charts.PanAndZoomBehavior].
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class LineAnimationZoomChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const LineAnimationZoomChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory LineAnimationZoomChart.withSampleData() {
return LineAnimationZoomChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LineAnimationZoomChart.withRandomData() {
return LineAnimationZoomChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = <LinearSales>[];
for (var i = 0; i < 100; i++) {
data.add(LinearSales(i, random.nextInt(100)));
}
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList, animate: animate, behaviors: [
charts.PanAndZoomBehavior(),
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,142 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Line chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class AreaAndLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const AreaAndLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory AreaAndLineChart.withSampleData() {
return AreaAndLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory AreaAndLineChart.withRandomData() {
return AreaAndLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final myFakeDesktopData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeTabletData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customArea'),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
animate: animate,
customSeriesRenderers: [
charts.LineRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'customArea',
includeArea: true,
stacked: true),
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
var myFakeTabletData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
)
// Configure our custom bar target renderer for this series.
..setAttribute(charts.rendererIdKey, 'customArea'),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,163 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Dash pattern line chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
/// Example of a line chart rendered with dash patterns.
class DashPatternLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const DashPatternLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory DashPatternLineChart.withSampleData() {
return DashPatternLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DashPatternLineChart.withRandomData() {
return DashPatternLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final myFakeDesktopData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeTabletData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeMobileData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
dashPatternFn: (_, __) => [2, 2],
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
dashPatternFn: (_, __) => [8, 3, 2, 3],
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList, animate: animate);
}
/// Create three series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
var myFakeTabletData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
var myFakeMobileData = [
LinearSales(0, 15),
LinearSales(1, 75),
LinearSales(2, 300),
LinearSales(3, 225),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
dashPatternFn: (_, __) => [2, 2],
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
dashPatternFn: (_, __) => [8, 3, 2, 3],
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,121 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Line chart with line annotations example.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class LineLineAnnotationChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const LineLineAnnotationChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and line annotations.
///
/// The second annotation extends beyond the range of the series data,
/// demonstrating the effect of the [Charts.RangeAnnotation.extendAxis] flag.
/// This can be set to false to disable range extension.
factory LineLineAnnotationChart.withSampleData() {
return LineLineAnnotationChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LineLineAnnotationChart.withRandomData() {
return LineLineAnnotationChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
// Fix one of the points to 100 so that the annotations are consistently
// placed.
LinearSales(3, 100),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList, animate: animate, behaviors: [
charts.RangeAnnotation([
charts.LineAnnotationSegment(1.0, charts.RangeAnnotationAxisType.domain,
startLabel: 'Domain 1'),
charts.LineAnnotationSegment(4, charts.RangeAnnotationAxisType.domain,
endLabel: 'Domain 2', color: charts.MaterialPalette.gray.shade200),
charts.LineAnnotationSegment(20, charts.RangeAnnotationAxisType.measure,
startLabel: 'Measure 1 Start',
endLabel: 'Measure 1 End',
color: charts.MaterialPalette.gray.shade300),
charts.LineAnnotationSegment(65, charts.RangeAnnotationAxisType.measure,
startLabel: 'Measure 2 Start',
endLabel: 'Measure 2 End',
color: charts.MaterialPalette.gray.shade400),
]),
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,113 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import '../gallery_scaffold.dart';
import 'animation_zoom.dart';
import 'area_and_line.dart';
import 'dash_pattern.dart';
import 'line_annotation.dart';
import 'points.dart';
import 'range_annotation.dart';
import 'range_annotation_margin.dart';
import 'segments.dart';
import 'simple.dart';
import 'simple_nulls.dart';
import 'stacked_area.dart';
import 'stacked_area_custom_color.dart';
import 'stacked_area_nulls.dart';
List<GalleryScaffold> buildGallery() {
return [
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Simple Line Chart',
subtitle: 'With a single series and default line point highlighter',
childBuilder: () => SimpleLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Stacked Area Chart',
subtitle: 'Stacked area chart with three series',
childBuilder: () => StackedAreaLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Stacked Area Custom Color Chart',
subtitle: 'Stacked area chart with custom area skirt color',
childBuilder: () => StackedAreaCustomColorLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Area and Line Combo Chart',
subtitle: 'Combo chart with one line series and one area series',
childBuilder: () => AreaAndLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Points Line Chart',
subtitle: 'Line chart with points on a single series',
childBuilder: () => PointsLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Null Data Line Chart',
subtitle: 'With a single series and null measure values',
childBuilder: () => SimpleNullsLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Stacked Area with Nulls Chart',
subtitle: 'Stacked area chart with three series and null measure values',
childBuilder: () => StackedAreaNullsLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Dash Pattern Line Chart',
subtitle: 'Line chart with dash patterns',
childBuilder: () => DashPatternLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Segments Line Chart',
subtitle: 'Line chart with changes of style for each line',
childBuilder: () => SegmentsLineChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Line Annotation Line Chart',
subtitle: 'Line chart with line annotations',
childBuilder: () => LineLineAnnotationChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Range Annotation Line Chart',
subtitle: 'Line chart with range annotations',
childBuilder: () => LineRangeAnnotationChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Range Annotation Margin Labels Line Chart',
subtitle: 'Line chart with range annotations with labels in margins',
childBuilder: () => LineRangeAnnotationMarginChart.withRandomData(),
),
GalleryScaffold(
listTileIcon: const Icon(Icons.show_chart),
title: 'Pan and Zoom Line Chart',
subtitle: 'Simple line chart pan and zoom behaviors enabled',
childBuilder: () => LineAnimationZoomChart.withRandomData(),
),
];
}

@ -1,104 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Line chart example
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class PointsLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const PointsLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory PointsLineChart.withSampleData() {
return PointsLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory PointsLineChart.withRandomData() {
return PointsLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
animate: animate,
defaultRenderer: charts.LineRendererConfig(includePoints: true));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,125 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Line chart with range annotations example.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class LineRangeAnnotationChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const LineRangeAnnotationChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and range annotations.
///
/// The second annotation extends beyond the range of the series data,
/// demonstrating the effect of the [Charts.RangeAnnotation.extendAxis] flag.
/// This can be set to false to disable range extension.
factory LineRangeAnnotationChart.withSampleData() {
return LineRangeAnnotationChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LineRangeAnnotationChart.withRandomData() {
return LineRangeAnnotationChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
// Fix one of the points to 100 so that the annotations are consistently
// placed.
LinearSales(3, 100),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList, animate: animate, behaviors: [
charts.RangeAnnotation([
charts.RangeAnnotationSegment(
0.5, 1.0, charts.RangeAnnotationAxisType.domain,
startLabel: 'Domain 1'),
charts.RangeAnnotationSegment(
2, 4, charts.RangeAnnotationAxisType.domain,
endLabel: 'Domain 2', color: charts.MaterialPalette.gray.shade200),
charts.RangeAnnotationSegment(
15, 20, charts.RangeAnnotationAxisType.measure,
startLabel: 'Measure 1 Start',
endLabel: 'Measure 1 End',
color: charts.MaterialPalette.gray.shade300),
charts.RangeAnnotationSegment(
35, 65, charts.RangeAnnotationAxisType.measure,
startLabel: 'Measure 2 Start',
endLabel: 'Measure 2 End',
color: charts.MaterialPalette.gray.shade400),
]),
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,143 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a line chart with range annotations configured to render labels
/// in the chart margin area.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class LineRangeAnnotationMarginChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const LineRangeAnnotationMarginChart(this.seriesList,
{this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and range annotations.
///
/// The second annotation extends beyond the range of the series data,
/// demonstrating the effect of the [Charts.RangeAnnotation.extendAxis] flag.
/// This can be set to false to disable range extension.
factory LineRangeAnnotationMarginChart.withSampleData() {
return LineRangeAnnotationMarginChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory LineRangeAnnotationMarginChart.withRandomData() {
return LineRangeAnnotationMarginChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
// Fix one of the points to 100 so that the annotations are consistently
// placed.
LinearSales(3, 100),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
animate: animate,
// Allow enough space in the left and right chart margins for the
// annotations.
layoutConfig: charts.LayoutConfig(
leftMarginSpec: charts.MarginSpec.fixedPixel(60),
topMarginSpec: charts.MarginSpec.fixedPixel(20),
rightMarginSpec: charts.MarginSpec.fixedPixel(60),
bottomMarginSpec: charts.MarginSpec.fixedPixel(20)),
behaviors: [
// Define one domain and two measure annotations configured to render
// labels in the chart margins.
charts.RangeAnnotation([
charts.RangeAnnotationSegment(
0.5, 1.0, charts.RangeAnnotationAxisType.domain,
startLabel: 'D1 Start',
endLabel: 'D1 End',
labelAnchor: charts.AnnotationLabelAnchor.end,
color: charts.MaterialPalette.gray.shade200,
// Override the default vertical direction for domain labels.
labelDirection: charts.AnnotationLabelDirection.horizontal),
charts.RangeAnnotationSegment(
15, 20, charts.RangeAnnotationAxisType.measure,
startLabel: 'M1 Start',
endLabel: 'M1 End',
labelAnchor: charts.AnnotationLabelAnchor.end,
color: charts.MaterialPalette.gray.shade300),
charts.RangeAnnotationSegment(
35, 65, charts.RangeAnnotationAxisType.measure,
startLabel: 'M2 Start',
endLabel: 'M2 End',
labelAnchor: charts.AnnotationLabelAnchor.start,
color: charts.MaterialPalette.gray.shade400),
], defaultLabelPosition: charts.AnnotationLabelPosition.margin),
]);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,234 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a stacked area chart with changing styles within each line.
///
/// Each series of data in this example contains different values for color,
/// dashPattern, or strokeWidthPx between each datum. The line and area skirt
/// will be rendered in segments, with the styling of the series changing when
/// these data attributes change.
///
/// Note that if a dashPattern or strokeWidth value is not found for a
/// particular datum, then the chart will fall back to use the value defined in
/// the [charts.LineRendererConfig]. This could be used, for example, to define
/// a default dash pattern for the series, with only a specific datum called out
/// with a different pattern.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SegmentsLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SegmentsLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory SegmentsLineChart.withSampleData() {
return SegmentsLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SegmentsLineChart.withRandomData() {
return SegmentsLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
// Series of data with static dash pattern and stroke width. The colorFn
// accessor will colorize each datum (for all three series).
final colorChangeData = [
LinearSales(0, random.nextInt(100), null, 2.0),
LinearSales(1, random.nextInt(100), null, 2.0),
LinearSales(2, random.nextInt(100), null, 2.0),
LinearSales(3, random.nextInt(100), null, 2.0),
LinearSales(4, random.nextInt(100), null, 2.0),
LinearSales(5, random.nextInt(100), null, 2.0),
LinearSales(6, random.nextInt(100), null, 2.0),
];
// Series of data with changing color and dash pattern.
final dashPatternChangeData = [
LinearSales(0, random.nextInt(100), [2, 2], 2.0),
LinearSales(1, random.nextInt(100), [2, 2], 2.0),
LinearSales(2, random.nextInt(100), [4, 4], 2.0),
LinearSales(3, random.nextInt(100), [4, 4], 2.0),
LinearSales(4, random.nextInt(100), [4, 4], 2.0),
LinearSales(5, random.nextInt(100), [8, 3, 2, 3], 2.0),
LinearSales(6, random.nextInt(100), [8, 3, 2, 3], 2.0),
];
// Series of data with changing color and stroke width.
final strokeWidthChangeData = [
LinearSales(0, random.nextInt(100), null, 2.0),
LinearSales(1, random.nextInt(100), null, 2.0),
LinearSales(2, random.nextInt(100), null, 4.0),
LinearSales(3, random.nextInt(100), null, 4.0),
LinearSales(4, random.nextInt(100), null, 4.0),
LinearSales(5, random.nextInt(100), null, 6.0),
LinearSales(6, random.nextInt(100), null, 6.0),
];
// Generate 2 shades of each color so that we can style the line segments.
final blue = charts.MaterialPalette.blue.makeShades(2);
final red = charts.MaterialPalette.red.makeShades(2);
final green = charts.MaterialPalette.green.makeShades(2);
return [
charts.Series<LinearSales, int>(
id: 'Color Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? blue[1] : blue[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: colorChangeData,
),
charts.Series<LinearSales, int>(
id: 'Dash Pattern Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? red[1] : red[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: dashPatternChangeData,
),
charts.Series<LinearSales, int>(
id: 'Stroke Width Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? green[1] : green[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: strokeWidthChangeData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
defaultRenderer:
charts.LineRendererConfig(includeArea: true, stacked: true),
animate: animate);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
// Series of data with static dash pattern and stroke width. The colorFn
// accessor will colorize each datum (for all three series).
final colorChangeData = [
LinearSales(0, 5, null, 2.0),
LinearSales(1, 15, null, 2.0),
LinearSales(2, 25, null, 2.0),
LinearSales(3, 75, null, 2.0),
LinearSales(4, 100, null, 2.0),
LinearSales(5, 90, null, 2.0),
LinearSales(6, 75, null, 2.0),
];
// Series of data with changing color and dash pattern.
final dashPatternChangeData = [
LinearSales(0, 5, [2, 2], 2.0),
LinearSales(1, 15, [2, 2], 2.0),
LinearSales(2, 25, [4, 4], 2.0),
LinearSales(3, 75, [4, 4], 2.0),
LinearSales(4, 100, [4, 4], 2.0),
LinearSales(5, 90, [8, 3, 2, 3], 2.0),
LinearSales(6, 75, [8, 3, 2, 3], 2.0),
];
// Series of data with changing color and stroke width.
final strokeWidthChangeData = [
LinearSales(0, 5, null, 2.0),
LinearSales(1, 15, null, 2.0),
LinearSales(2, 25, null, 4.0),
LinearSales(3, 75, null, 4.0),
LinearSales(4, 100, null, 4.0),
LinearSales(5, 90, null, 6.0),
LinearSales(6, 75, null, 6.0),
];
// Generate 2 shades of each color so that we can style the line segments.
final blue = charts.MaterialPalette.blue.makeShades(2);
final red = charts.MaterialPalette.red.makeShades(2);
final green = charts.MaterialPalette.green.makeShades(2);
return [
charts.Series<LinearSales, int>(
id: 'Color Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? blue[1] : blue[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: colorChangeData,
),
charts.Series<LinearSales, int>(
id: 'Dash Pattern Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? red[1] : red[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: dashPatternChangeData,
),
charts.Series<LinearSales, int>(
id: 'Stroke Width Change',
// Light shade for even years, dark shade for odd.
colorFn: (LinearSales sales, _) =>
sales.year % 2 == 0 ? green[1] : green[0],
dashPatternFn: (LinearSales sales, _) => sales.dashPattern,
strokeWidthPxFn: (LinearSales sales, _) => sales.strokeWidthPx,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: strokeWidthChangeData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
final List<int>? dashPattern;
final double strokeWidthPx;
LinearSales(this.year, this.sales, this.dashPattern, this.strokeWidthPx);
}

@ -1,102 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a simple line chart.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SimpleLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SimpleLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory SimpleLineChart.withSampleData() {
return SimpleLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SimpleLineChart.withRandomData() {
return SimpleLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList, animate: animate);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,180 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a line chart with null measure values.
///
/// Null values will be visible as gaps in lines and area skirts. Any data
/// points that exist between two nulls in a line will be rendered as an
/// isolated point, as seen in the green series.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SimpleNullsLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const SimpleNullsLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory SimpleNullsLineChart.withSampleData() {
return SimpleNullsLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory SimpleNullsLineChart.withRandomData() {
return SimpleNullsLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final myFakeDesktopData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, null),
LinearSales(3, random.nextInt(100)),
LinearSales(4, random.nextInt(100)),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
];
var myFakeTabletData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
LinearSales(4, random.nextInt(100)),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
];
var myFakeMobileData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, null),
LinearSales(3, random.nextInt(100)),
LinearSales(4, null),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList, animate: animate);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
LinearSales(0, 5),
LinearSales(1, 15),
LinearSales(2, null),
LinearSales(3, 75),
LinearSales(4, 100),
LinearSales(5, 90),
LinearSales(6, 75),
];
final myFakeTabletData = [
LinearSales(0, 10),
LinearSales(1, 30),
LinearSales(2, 50),
LinearSales(3, 150),
LinearSales(4, 200),
LinearSales(5, 180),
LinearSales(6, 150),
];
final myFakeMobileData = [
LinearSales(0, 15),
LinearSales(1, 45),
LinearSales(2, null),
LinearSales(3, 225),
LinearSales(4, null),
LinearSales(5, 270),
LinearSales(6, 225),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int? sales;
LinearSales(this.year, this.sales);
}

@ -1,161 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a stacked area chart.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class StackedAreaLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const StackedAreaLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory StackedAreaLineChart.withSampleData() {
return StackedAreaLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedAreaLineChart.withRandomData() {
return StackedAreaLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final myFakeDesktopData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeTabletData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeMobileData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
defaultRenderer:
charts.LineRendererConfig(includeArea: true, stacked: true),
animate: animate);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
var myFakeTabletData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
var myFakeMobileData = [
LinearSales(0, 15),
LinearSales(1, 75),
LinearSales(2, 300),
LinearSales(3, 225),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,177 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a stacked area chart with custom area colors.
///
/// By default, the area skirt for a chart will be drawn with the same color as
/// the line, but with a 10% opacity assigned to it. An area color function can
/// be provided to override this with any custom color.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class StackedAreaCustomColorLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const StackedAreaCustomColorLineChart(this.seriesList,
{this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory StackedAreaCustomColorLineChart.withSampleData() {
return StackedAreaCustomColorLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedAreaCustomColorLineChart.withRandomData() {
return StackedAreaCustomColorLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final myFakeDesktopData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeTabletData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
var myFakeMobileData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
defaultRenderer:
charts.LineRendererConfig(includeArea: true, stacked: true),
animate: animate);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
LinearSales(0, 5),
LinearSales(1, 25),
LinearSales(2, 100),
LinearSales(3, 75),
];
var myFakeTabletData = [
LinearSales(0, 10),
LinearSales(1, 50),
LinearSales(2, 200),
LinearSales(3, 150),
];
var myFakeMobileData = [
LinearSales(0, 15),
LinearSales(1, 75),
LinearSales(2, 300),
LinearSales(3, 225),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
// colorFn specifies that the line will be blue.
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
// areaColorFn specifies that the area skirt will be light blue.
areaColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
// colorFn specifies that the line will be red.
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
// areaColorFn specifies that the area skirt will be light red.
areaColorFn: (_, __) => charts.MaterialPalette.red.shadeDefault.lighter,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
// colorFn specifies that the line will be green.
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
// areaColorFn specifies that the area skirt will be light green.
areaColorFn: (_, __) =>
charts.MaterialPalette.green.shadeDefault.lighter,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,192 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Example of a stacked area chart with null measure values.
///
/// Null values will be visible as gaps in lines and area skirts. Any data
/// points that exist between two nulls in a line will be rendered as an
/// isolated point, as seen in the green series.
///
/// In a stacked area chart, no data above a null value in the stack will be
/// rendered. In this example, the null measure value at domain 2 in the Desktop
/// series will prevent any data from being rendered at domain 2 for every
/// series because it is at the bottom of the stack.
///
/// This will also result in an isolated point being rendered for the domain
/// value 3 in the Mobile series, because that series also contains a null at
/// domain 4.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class StackedAreaNullsLineChart extends StatelessWidget {
final List<charts.Series<dynamic, num>> seriesList;
final bool? animate;
const StackedAreaNullsLineChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [LineChart] with sample data and no transition.
factory StackedAreaNullsLineChart.withSampleData() {
return StackedAreaNullsLineChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory StackedAreaNullsLineChart.withRandomData() {
return StackedAreaNullsLineChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, num>> _createRandomData() {
final random = Random();
final myFakeDesktopData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, null),
LinearSales(3, random.nextInt(100)),
LinearSales(4, random.nextInt(100)),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
];
var myFakeTabletData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
LinearSales(4, random.nextInt(100)),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
];
var myFakeMobileData = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
LinearSales(4, null),
LinearSales(5, random.nextInt(100)),
LinearSales(6, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.LineChart(seriesList,
defaultRenderer:
charts.LineRendererConfig(includeArea: true, stacked: true),
animate: animate);
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final myFakeDesktopData = [
LinearSales(0, 5),
LinearSales(1, 15),
LinearSales(2, null),
LinearSales(3, 75),
LinearSales(4, 100),
LinearSales(5, 90),
LinearSales(6, 75),
];
final myFakeTabletData = [
LinearSales(0, 5),
LinearSales(1, 15),
LinearSales(2, 25),
LinearSales(3, 75),
LinearSales(4, 100),
LinearSales(5, 90),
LinearSales(6, 75),
];
final myFakeMobileData = [
LinearSales(0, 5),
LinearSales(1, 15),
LinearSales(2, 25),
LinearSales(3, 75),
LinearSales(4, null),
LinearSales(5, 90),
LinearSales(6, 75),
];
return [
charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeDesktopData,
),
charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeTabletData,
),
charts.Series<LinearSales, int>(
id: 'Mobile',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: myFakeMobileData,
),
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int? sales;
LinearSales(this.year, this.sales);
}

@ -1,54 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter/material.dart';
import 'app_config.dart';
import 'home.dart';
/// The main gallery app widget.
class GalleryApp extends StatefulWidget {
const GalleryApp({Key? key}) : super(key: key);
@override
State<GalleryApp> createState() => _GalleryAppState();
}
/// The main gallery app state.
///
/// Controls performance overlay, and instantiates a [Home] widget.
class _GalleryAppState extends State<GalleryApp> {
// Initialize app settings from the default configuration.
bool _showPerformanceOverlay = defaultConfig.showPerformanceOverlay;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: defaultConfig.appName,
theme: defaultConfig.theme,
showPerformanceOverlay: _showPerformanceOverlay,
home: Home(
showPerformanceOverlay: _showPerformanceOverlay,
onShowPerformanceOverlayChanged: (bool value) {
setState(() {
_showPerformanceOverlay = value;
});
},
));
}
}
void main() {
runApp(const GalleryApp());
}

@ -1,123 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Donut chart with labels example. This is a simple pie chart with a hole in
/// the middle.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class DonutAutoLabelChart extends StatelessWidget {
final List<charts.Series<dynamic, int>> seriesList;
final bool? animate;
const DonutAutoLabelChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [PieChart] with sample data and no transition.
factory DonutAutoLabelChart.withSampleData() {
return DonutAutoLabelChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DonutAutoLabelChart.withRandomData() {
return DonutAutoLabelChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, int>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the arc label.
labelAccessorFn: (LinearSales row, _) => '${row.year}: ${row.sales}',
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart(seriesList,
animate: animate,
// Configure the width of the pie slices to 60px. The remaining space in
// the chart will be left as a hole in the center.
//
// [ArcLabelDecorator] will automatically position the label inside the
// arc if the label will fit. If the label will not fit, it will draw
// outside of the arc with a leader line. Labels can always display
// inside or outside using [LabelPosition].
//
// Text style for inside / outside can be controlled independently by
// setting [insideLabelStyleSpec] and [outsideLabelStyleSpec].
//
// Example configuring different styles for inside/outside:
// new charts.ArcLabelDecorator(
// insideLabelStyleSpec: new charts.TextStyleSpec(...),
// outsideLabelStyleSpec: new charts.TextStyleSpec(...)),
defaultRenderer: charts.ArcRendererConfig(
arcWidth: 60, arcRendererDecorators: [charts.ArcLabelDecorator()]));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 100),
LinearSales(1, 75),
LinearSales(2, 25),
LinearSales(3, 5),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the arc label.
labelAccessorFn: (LinearSales row, _) => '${row.year}: ${row.sales}',
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,104 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Donut chart example. This is a simple pie chart with a hole in the middle.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class DonutPieChart extends StatelessWidget {
final List<charts.Series<dynamic, int>> seriesList;
final bool? animate;
const DonutPieChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [PieChart] with sample data and no transition.
factory DonutPieChart.withSampleData() {
return DonutPieChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory DonutPieChart.withRandomData() {
return DonutPieChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, int>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart(seriesList,
animate: animate,
// Configure the width of the pie slices to 60px. The remaining space in
// the chart will be left as a hole in the center.
defaultRenderer: charts.ArcRendererConfig(arcWidth: 60));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 100),
LinearSales(1, 75),
LinearSales(2, 25),
LinearSales(3, 5),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

@ -1,106 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Gauge chart example, where the data does not cover a full revolution in the
/// chart.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class GaugeChart extends StatelessWidget {
final List<charts.Series<dynamic, String>> seriesList;
final bool? animate;
const GaugeChart(this.seriesList, {this.animate, Key? key}) : super(key: key);
/// Creates a [PieChart] with sample data and no transition.
factory GaugeChart.withSampleData() {
return GaugeChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory GaugeChart.withRandomData() {
return GaugeChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<GaugeSegment, String>> _createRandomData() {
final random = Random();
final data = [
GaugeSegment('Low', random.nextInt(100)),
GaugeSegment('Acceptable', random.nextInt(100)),
GaugeSegment('High', random.nextInt(100)),
GaugeSegment('Highly Unusual', random.nextInt(100)),
];
return [
charts.Series<GaugeSegment, String>(
id: 'Segments',
domainFn: (GaugeSegment segment, _) => segment.segment,
measureFn: (GaugeSegment segment, _) => segment.size,
data: data,
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart(seriesList,
animate: animate,
// Configure the width of the pie slices to 30px. The remaining space in
// the chart will be left as a hole in the center. Adjust the start
// angle and the arc length of the pie so it resembles a gauge.
defaultRenderer: charts.ArcRendererConfig(
arcWidth: 30, startAngle: 4 / 5 * pi, arcLength: 7 / 5 * pi));
}
/// Create one series with sample hard coded data.
static List<charts.Series<GaugeSegment, String>> _createSampleData() {
final data = [
GaugeSegment('Low', 75),
GaugeSegment('Acceptable', 100),
GaugeSegment('High', 50),
GaugeSegment('Highly Unusual', 5),
];
return [
charts.Series<GaugeSegment, String>(
id: 'Segments',
domainFn: (GaugeSegment segment, _) => segment.segment,
measureFn: (GaugeSegment segment, _) => segment.size,
data: data,
)
];
}
}
/// Sample data type.
class GaugeSegment {
final String segment;
final int size;
GaugeSegment(this.segment, this.size);
}

@ -1,119 +0,0 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Simple pie chart with outside labels example.
// EXCLUDE_FROM_GALLERY_DOCS_START
import 'dart:math';
// EXCLUDE_FROM_GALLERY_DOCS_END
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class PieOutsideLabelChart extends StatelessWidget {
final List<charts.Series<dynamic, int>> seriesList;
final bool? animate;
const PieOutsideLabelChart(this.seriesList, {this.animate, Key? key})
: super(key: key);
/// Creates a [PieChart] with sample data and no transition.
factory PieOutsideLabelChart.withSampleData() {
return PieOutsideLabelChart(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
// EXCLUDE_FROM_GALLERY_DOCS_START
// This section is excluded from being copied to the gallery.
// It is used for creating random series data to demonstrate animation in
// the example app only.
factory PieOutsideLabelChart.withRandomData() {
return PieOutsideLabelChart(_createRandomData());
}
/// Create random data.
static List<charts.Series<LinearSales, int>> _createRandomData() {
final random = Random();
final data = [
LinearSales(0, random.nextInt(100)),
LinearSales(1, random.nextInt(100)),
LinearSales(2, random.nextInt(100)),
LinearSales(3, random.nextInt(100)),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the arc label.
labelAccessorFn: (LinearSales row, _) => '${row.year}: ${row.sales}',
)
];
}
// EXCLUDE_FROM_GALLERY_DOCS_END
@override
Widget build(BuildContext context) {
return charts.PieChart(seriesList,
animate: animate,
// Add an [ArcLabelDecorator] configured to render labels outside of the
// arc with a leader line.
//
// Text style for inside / outside can be controlled independently by
// setting [insideLabelStyleSpec] and [outsideLabelStyleSpec].
//
// Example configuring different styles for inside/outside:
// new charts.ArcLabelDecorator(
// insideLabelStyleSpec: new charts.TextStyleSpec(...),
// outsideLabelStyleSpec: new charts.TextStyleSpec(...)),
defaultRenderer: charts.ArcRendererConfig(arcRendererDecorators: [
charts.ArcLabelDecorator(
labelPosition: charts.ArcLabelPosition.outside)
]));
}
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
LinearSales(0, 100),
LinearSales(1, 75),
LinearSales(2, 25),
LinearSales(3, 5),
];
return [
charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
// Set a label accessor to control the text of the arc label.
labelAccessorFn: (LinearSales row, _) => '${row.year}: ${row.sales}',
)
];
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save