mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Drop web/charts sample (#1452)
This commit is contained in:
@@ -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
Reference in New Issue
Block a user