mirror of
https://github.com/flutter/samples.git
synced 2026-04-03 02:02:27 +00:00
Add flutter_web samples (#75)
This commit is contained in:
committed by
Andrew Brogdon
parent
42f2dce01b
commit
3fe927cb29
126
web/charts/example/lib/behaviors/behaviors_gallery.dart
Normal file
126
web/charts/example/lib/behaviors/behaviors_gallery.dart
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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_web/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 [
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Selection Bar Highlight',
|
||||
subtitle: 'Simple bar chart with tap activation',
|
||||
childBuilder: () => new SelectionBarHighlight.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Selection Line Highlight',
|
||||
subtitle: 'Line chart with tap and drag activation',
|
||||
childBuilder: () => new SelectionLineHighlight.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Selection Line Highlight Custom Shape',
|
||||
subtitle: 'Line chart with tap and drag activation and a custom shape',
|
||||
childBuilder: () =>
|
||||
new SelectionLineHighlightCustomShape.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Selection Scatter Plot Highlight',
|
||||
subtitle: 'Scatter plot chart with tap and drag activation',
|
||||
childBuilder: () => new SelectionScatterPlotHighlight.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Selection Callback Example',
|
||||
subtitle: 'Timeseries that updates external components on selection',
|
||||
childBuilder: () => new SelectionCallbackExample.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'User managed selection',
|
||||
subtitle:
|
||||
'Example where selection can be set and cleared programmatically',
|
||||
childBuilder: () => new SelectionUserManaged.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Bar Chart with initial selection',
|
||||
subtitle: 'Single series with initial selection',
|
||||
childBuilder: () => new InitialSelection.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Line Chart with Chart Titles',
|
||||
subtitle: 'Line chart with four chart titles',
|
||||
childBuilder: () => new ChartTitleLine.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.flag),
|
||||
title: 'Line Chart with Slider',
|
||||
subtitle: 'Line chart with a slider behavior',
|
||||
childBuilder: () => new SliderLine.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Percent of Domain',
|
||||
subtitle: 'Stacked bar chart with measures calculated as percent of ' +
|
||||
'domain',
|
||||
childBuilder: () => new PercentOfDomainBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new 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: () =>
|
||||
new PercentOfDomainByCategoryBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Percent of Series',
|
||||
subtitle: 'Grouped bar chart with measures calculated as percent of ' +
|
||||
'series',
|
||||
childBuilder: () => new PercentOfSeriesBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Sliding viewport on domain selection',
|
||||
subtitle: 'Center viewport on selected domain',
|
||||
childBuilder: () => new SlidingViewportOnSelection.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Initial hint animation ',
|
||||
subtitle: 'Animate into final viewport',
|
||||
childBuilder: () => new InitialHintAnimation.withRandomData(),
|
||||
),
|
||||
];
|
||||
}
|
||||
131
web/charts/example/lib/behaviors/chart_title.dart
Normal file
131
web/charts/example/lib/behaviors/chart_title.dart
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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_web/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> seriesList;
|
||||
final bool animate;
|
||||
|
||||
ChartTitleLine(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [LineChart] with sample data and no transition.
|
||||
factory ChartTitleLine.withSampleData() {
|
||||
return new 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 new ChartTitleLine(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<LinearSales, num>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new LinearSales(0, random.nextInt(100)),
|
||||
new LinearSales(1, random.nextInt(100)),
|
||||
new LinearSales(2, random.nextInt(100)),
|
||||
new LinearSales(3, random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new 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: [
|
||||
new 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),
|
||||
new charts.ChartTitle('Bottom title text',
|
||||
behaviorPosition: charts.BehaviorPosition.bottom,
|
||||
titleOutsideJustification:
|
||||
charts.OutsideJustification.middleDrawArea),
|
||||
new charts.ChartTitle('Start title',
|
||||
behaviorPosition: charts.BehaviorPosition.start,
|
||||
titleOutsideJustification:
|
||||
charts.OutsideJustification.middleDrawArea),
|
||||
new 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 = [
|
||||
new LinearSales(0, 5),
|
||||
new LinearSales(1, 25),
|
||||
new LinearSales(2, 100),
|
||||
new LinearSales(3, 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
175
web/charts/example/lib/behaviors/initial_hint_animation.dart
Normal file
175
web/charts/example/lib/behaviors/initial_hint_animation.dart
Normal file
@@ -0,0 +1,175 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class InitialHintAnimation extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
InitialHintAnimation(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory InitialHintAnimation.withSampleData() {
|
||||
return new 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 new InitialHintAnimation(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
new OrdinalSales('2018', random.nextInt(100)),
|
||||
new OrdinalSales('2019', random.nextInt(100)),
|
||||
new OrdinalSales('2020', random.nextInt(100)),
|
||||
new OrdinalSales('2021', random.nextInt(100)),
|
||||
new OrdinalSales('2022', random.nextInt(100)),
|
||||
new OrdinalSales('2023', random.nextInt(100)),
|
||||
new OrdinalSales('2024', random.nextInt(100)),
|
||||
new OrdinalSales('2025', random.nextInt(100)),
|
||||
new OrdinalSales('2026', random.nextInt(100)),
|
||||
new OrdinalSales('2027', random.nextInt(100)),
|
||||
new OrdinalSales('2028', random.nextInt(100)),
|
||||
new OrdinalSales('2029', random.nextInt(100)),
|
||||
new OrdinalSales('2030', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new 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: new charts.OrdinalAxisSpec(
|
||||
viewport: new 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.
|
||||
new 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
|
||||
new charts.PanAndZoomBehavior(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final data = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
new OrdinalSales('2018', 33),
|
||||
new OrdinalSales('2019', 80),
|
||||
new OrdinalSales('2020', 21),
|
||||
new OrdinalSales('2021', 77),
|
||||
new OrdinalSales('2022', 8),
|
||||
new OrdinalSales('2023', 12),
|
||||
new OrdinalSales('2024', 42),
|
||||
new OrdinalSales('2025', 70),
|
||||
new OrdinalSales('2026', 77),
|
||||
new OrdinalSales('2027', 55),
|
||||
new OrdinalSales('2028', 19),
|
||||
new OrdinalSales('2029', 66),
|
||||
new OrdinalSales('2030', 27),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
129
web/charts/example/lib/behaviors/initial_selection.dart
Normal file
129
web/charts/example/lib/behaviors/initial_selection.dart
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class InitialSelection extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
InitialSelection(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [BarChart] with initial selection behavior.
|
||||
factory InitialSelection.withSampleData() {
|
||||
return new 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 new InitialSelection(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new 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.
|
||||
new charts.InitialSelection(selectedDataConfig: [
|
||||
new charts.SeriesDatumConfig<String>('Sales', '2016')
|
||||
])
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final data = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
167
web/charts/example/lib/behaviors/percent_of_domain.dart
Normal file
167
web/charts/example/lib/behaviors/percent_of_domain.dart
Normal file
@@ -0,0 +1,167 @@
|
||||
// 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_web/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PercentOfDomainBarChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PercentOfDomainBarChart(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a stacked [BarChart] with sample data and no transition.
|
||||
factory PercentOfDomainBarChart.withSampleData() {
|
||||
return new 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 new PercentOfDomainBarChart(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final desktopSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final tableSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final mobileSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
),
|
||||
new 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 new 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: [
|
||||
new charts.PercentInjector(
|
||||
totalType: charts.PercentInjectorTotalType.domain)
|
||||
],
|
||||
// Configure the axis spec to show percentage values.
|
||||
primaryMeasureAxis: new charts.PercentAxisSpec(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final desktopSalesData = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
final tableSalesData = [
|
||||
new OrdinalSales('2014', 25),
|
||||
new OrdinalSales('2015', 50),
|
||||
new OrdinalSales('2016', 10),
|
||||
new OrdinalSales('2017', 20),
|
||||
];
|
||||
|
||||
final mobileSalesData = [
|
||||
new OrdinalSales('2014', 10),
|
||||
new OrdinalSales('2015', 15),
|
||||
new OrdinalSales('2016', 50),
|
||||
new OrdinalSales('2017', 45),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
),
|
||||
new 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);
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
// 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_web/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PercentOfDomainByCategoryBarChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PercentOfDomainByCategoryBarChart(this.seriesList, {this.animate});
|
||||
|
||||
factory PercentOfDomainByCategoryBarChart.withSampleData() {
|
||||
return new 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 new PercentOfDomainByCategoryBarChart(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final desktopSalesDataA = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final tableSalesDataA = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final mobileSalesDataA = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final desktopSalesDataB = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final tableSalesDataB = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
final mobileSalesDataB = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop A',
|
||||
seriesCategory: 'A',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesDataA,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet A',
|
||||
seriesCategory: 'A',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesDataA,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile A',
|
||||
seriesCategory: 'A',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileSalesDataA,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop B',
|
||||
seriesCategory: 'B',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesDataB,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet B',
|
||||
seriesCategory: 'B',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesDataB,
|
||||
),
|
||||
new 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 new 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: [
|
||||
new charts.PercentInjector(
|
||||
totalType: charts.PercentInjectorTotalType.domainBySeriesCategory)
|
||||
],
|
||||
// Configure the axis spec to show percentage values.
|
||||
primaryMeasureAxis: new charts.PercentAxisSpec(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> createSampleData() {
|
||||
final desktopSalesDataA = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
final tableSalesDataA = [
|
||||
new OrdinalSales('2014', 25),
|
||||
new OrdinalSales('2015', 50),
|
||||
new OrdinalSales('2016', 10),
|
||||
new OrdinalSales('2017', 20),
|
||||
];
|
||||
|
||||
final mobileSalesDataA = [
|
||||
new OrdinalSales('2014', 10),
|
||||
new OrdinalSales('2015', 15),
|
||||
new OrdinalSales('2016', 50),
|
||||
new OrdinalSales('2017', 45),
|
||||
];
|
||||
|
||||
final desktopSalesDataB = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
final tableSalesDataB = [
|
||||
new OrdinalSales('2014', 25),
|
||||
new OrdinalSales('2015', 50),
|
||||
new OrdinalSales('2016', 10),
|
||||
new OrdinalSales('2017', 20),
|
||||
];
|
||||
|
||||
final mobileSalesDataB = [
|
||||
new OrdinalSales('2014', 10),
|
||||
new OrdinalSales('2015', 15),
|
||||
new OrdinalSales('2016', 50),
|
||||
new OrdinalSales('2017', 45),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop A',
|
||||
seriesCategory: 'A',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesDataA,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet A',
|
||||
seriesCategory: 'A',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesDataA,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile A',
|
||||
seriesCategory: 'A',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileSalesDataA,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop B',
|
||||
seriesCategory: 'B',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesDataB,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet B',
|
||||
seriesCategory: 'B',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesDataB,
|
||||
),
|
||||
new 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);
|
||||
}
|
||||
120
web/charts/example/lib/behaviors/percent_of_series.dart
Normal file
120
web/charts/example/lib/behaviors/percent_of_series.dart
Normal file
@@ -0,0 +1,120 @@
|
||||
// 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_web/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PercentOfSeriesBarChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PercentOfSeriesBarChart(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a stacked [BarChart] with sample data and no transition.
|
||||
factory PercentOfSeriesBarChart.withSampleData() {
|
||||
return new 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 new PercentOfSeriesBarChart(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final desktopSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new 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: [
|
||||
new charts.PercentInjector(
|
||||
totalType: charts.PercentInjectorTotalType.series)
|
||||
],
|
||||
// Configure the axis spec to show percentage values.
|
||||
primaryMeasureAxis: new charts.PercentAxisSpec(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final desktopSalesData = [
|
||||
new OrdinalSales('2011', 5),
|
||||
new OrdinalSales('2012', 25),
|
||||
new OrdinalSales('2013', 50),
|
||||
new OrdinalSales('2014', 75),
|
||||
new OrdinalSales('2015', 100),
|
||||
new OrdinalSales('2016', 125),
|
||||
new OrdinalSales('2017', 200),
|
||||
new OrdinalSales('2018', 150),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
110
web/charts/example/lib/behaviors/selection_bar_highlight.dart
Normal file
110
web/charts/example/lib/behaviors/selection_bar_highlight.dart
Normal file
@@ -0,0 +1,110 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SelectionBarHighlight extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionBarHighlight(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory SelectionBarHighlight.withSampleData() {
|
||||
return new 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 new SelectionBarHighlight(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
defaultInteractions: true,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final data = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
201
web/charts/example/lib/behaviors/selection_callback_example.dart
Normal file
201
web/charts/example/lib/behaviors/selection_callback_example.dart
Normal file
@@ -0,0 +1,201 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SelectionCallbackExample extends StatefulWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionCallbackExample(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [charts.TimeSeriesChart] with sample data and no transition.
|
||||
factory SelectionCallbackExample.withSampleData() {
|
||||
return new 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 new SelectionCallbackExample(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<TimeSeriesSales, DateTime>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final us_data = [
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 19), random.nextInt(100)),
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 26), random.nextInt(100)),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 3), random.nextInt(100)),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 10), random.nextInt(100)),
|
||||
];
|
||||
|
||||
final uk_data = [
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 19), random.nextInt(100)),
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 26), random.nextInt(100)),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 3), random.nextInt(100)),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 10), random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<TimeSeriesSales, DateTime>(
|
||||
id: 'US Sales',
|
||||
domainFn: (TimeSeriesSales sales, _) => sales.time,
|
||||
measureFn: (TimeSeriesSales sales, _) => sales.sales,
|
||||
data: us_data,
|
||||
),
|
||||
new charts.Series<TimeSeriesSales, DateTime>(
|
||||
id: 'UK Sales',
|
||||
domainFn: (TimeSeriesSales sales, _) => sales.time,
|
||||
measureFn: (TimeSeriesSales sales, _) => sales.sales,
|
||||
data: uk_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() => new _SelectionCallbackState();
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
|
||||
final us_data = [
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 19), 5),
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 26), 25),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 3), 78),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 10), 54),
|
||||
];
|
||||
|
||||
final uk_data = [
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 19), 15),
|
||||
new TimeSeriesSales(new DateTime(2017, 9, 26), 33),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 3), 68),
|
||||
new TimeSeriesSales(new DateTime(2017, 10, 10), 48),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<TimeSeriesSales, DateTime>(
|
||||
id: 'US Sales',
|
||||
domainFn: (TimeSeriesSales sales, _) => sales.time,
|
||||
measureFn: (TimeSeriesSales sales, _) => sales.sales,
|
||||
data: us_data,
|
||||
),
|
||||
new charts.Series<TimeSeriesSales, DateTime>(
|
||||
id: 'UK Sales',
|
||||
domainFn: (TimeSeriesSales sales, _) => sales.time,
|
||||
measureFn: (TimeSeriesSales sales, _) => sales.sales,
|
||||
data: uk_data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
selectedDatum.forEach((charts.SeriesDatum datumPair) {
|
||||
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>[
|
||||
new SizedBox(
|
||||
height: 150.0,
|
||||
child: new charts.TimeSeriesChart(
|
||||
widget.seriesList,
|
||||
animate: widget.animate,
|
||||
selectionModels: [
|
||||
new charts.SelectionModelConfig(
|
||||
type: charts.SelectionModelType.info,
|
||||
changedListener: _onSelectionChanged,
|
||||
)
|
||||
],
|
||||
)),
|
||||
];
|
||||
|
||||
// If there is a selection, then include the details.
|
||||
if (_time != null) {
|
||||
children.add(new Padding(
|
||||
padding: new EdgeInsets.only(top: 5.0),
|
||||
child: new Text(_time.toString())));
|
||||
}
|
||||
_measures?.forEach((String series, num value) {
|
||||
children.add(new Text('${series}: ${value}'));
|
||||
});
|
||||
|
||||
return new Column(children: children);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample time series data type.
|
||||
class TimeSeriesSales {
|
||||
final DateTime time;
|
||||
final int sales;
|
||||
|
||||
TimeSeriesSales(this.time, this.sales);
|
||||
}
|
||||
127
web/charts/example/lib/behaviors/selection_line_highlight.dart
Normal file
127
web/charts/example/lib/behaviors/selection_line_highlight.dart
Normal file
@@ -0,0 +1,127 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SelectionLineHighlight extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionLineHighlight(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [LineChart] with sample data and no transition.
|
||||
factory SelectionLineHighlight.withSampleData() {
|
||||
return new 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 new SelectionLineHighlight(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<LinearSales, num>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new LinearSales(0, random.nextInt(100)),
|
||||
new LinearSales(1, random.nextInt(100)),
|
||||
new LinearSales(2, random.nextInt(100)),
|
||||
new LinearSales(3, random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new 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.
|
||||
new 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.
|
||||
new charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag)
|
||||
]);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<LinearSales, int>> _createSampleData() {
|
||||
final data = [
|
||||
new LinearSales(0, 5),
|
||||
new LinearSales(1, 25),
|
||||
new LinearSales(2, 100),
|
||||
new LinearSales(3, 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SelectionLineHighlightCustomShape extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionLineHighlightCustomShape(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [LineChart] with sample data and no transition.
|
||||
factory SelectionLineHighlightCustomShape.withSampleData() {
|
||||
return new 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 new SelectionLineHighlightCustomShape(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<LinearSales, num>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new LinearSales(0, random.nextInt(100)),
|
||||
new LinearSales(1, random.nextInt(100)),
|
||||
new LinearSales(2, random.nextInt(100)),
|
||||
new LinearSales(3, random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new 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.
|
||||
new charts.LinePointHighlighter(
|
||||
showHorizontalFollowLine:
|
||||
charts.LinePointHighlighterFollowLineType.none,
|
||||
showVerticalFollowLine:
|
||||
charts.LinePointHighlighterFollowLineType.nearest,
|
||||
symbolRenderer: new 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.
|
||||
new charts.SelectNearest(eventTrigger: charts.SelectionTrigger.tapAndDrag)
|
||||
]);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<LinearSales, int>> _createSampleData() {
|
||||
final data = [
|
||||
new LinearSales(0, 5),
|
||||
new LinearSales(1, 25),
|
||||
new LinearSales(2, 100),
|
||||
new LinearSales(3, 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SelectionScatterPlotHighlight extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionScatterPlotHighlight(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [ScatterPlotChart] with sample data and no transition.
|
||||
factory SelectionScatterPlotHighlight.withSampleData() {
|
||||
return new 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 new SelectionScatterPlotHighlight(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<LinearSales, num>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final makeRadius = (int value) => (random.nextInt(value) + 2).toDouble();
|
||||
|
||||
final data = [
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
'circle', null, null),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
// Render a hollow circle, filled in with white.
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100),
|
||||
makeRadius(4) + 4, 'circle', charts.MaterialPalette.white, 2.0),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
'circle', null, null),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
// Render a hollow circle, filled in with white.
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100),
|
||||
makeRadius(4) + 4, 'circle', charts.MaterialPalette.white, 2.0),
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100), makeRadius(6),
|
||||
null, null, null),
|
||||
// Render a hollow square, filled in with white.
|
||||
new LinearSales(random.nextInt(100), random.nextInt(100),
|
||||
makeRadius(4) + 4, null, charts.MaterialPalette.white, 2.0),
|
||||
];
|
||||
|
||||
final maxMeasure = 100;
|
||||
|
||||
return [
|
||||
new 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 new 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.
|
||||
new 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.
|
||||
new charts.SelectNearest(
|
||||
eventTrigger: charts.SelectionTrigger.tapAndDrag),
|
||||
],
|
||||
// Configure the point renderer to have a map of custom symbol
|
||||
// renderers.
|
||||
defaultRenderer:
|
||||
new charts.PointRendererConfig<num>(customSymbolRenderers: {
|
||||
'circle': new charts.CircleSymbolRenderer(),
|
||||
'rect': new charts.RectSymbolRenderer(),
|
||||
}));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<LinearSales, int>> _createSampleData() {
|
||||
final data = [
|
||||
new LinearSales(0, 5, 3.0, 'circle', null, null),
|
||||
new LinearSales(10, 25, 5.0, null, null, null),
|
||||
new LinearSales(12, 75, 4.0, null, null, null),
|
||||
// Render a hollow circle, filled in with white.
|
||||
new LinearSales(
|
||||
13, 225, 5.0, 'circle', charts.MaterialPalette.white, 2.0),
|
||||
new LinearSales(16, 50, 4.0, null, null, null),
|
||||
new LinearSales(24, 75, 3.0, null, null, null),
|
||||
new LinearSales(25, 100, 3.0, 'circle', null, null),
|
||||
new LinearSales(34, 150, 5.0, null, null, null),
|
||||
new LinearSales(37, 10, 4.5, null, null, null),
|
||||
// Render a hollow circle, filled in with white.
|
||||
new LinearSales(
|
||||
45, 300, 8.0, 'circle', charts.MaterialPalette.white, 2.0),
|
||||
new LinearSales(52, 15, 4.0, null, null, null),
|
||||
// Render a hollow square, filled in with white.
|
||||
new LinearSales(56, 200, 7.0, null, charts.MaterialPalette.white, 2.0),
|
||||
];
|
||||
|
||||
final maxMeasure = 300;
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
164
web/charts/example/lib/behaviors/selection_user_managed.dart
Normal file
164
web/charts/example/lib/behaviors/selection_user_managed.dart
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SelectionUserManaged extends StatefulWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionUserManaged(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory SelectionUserManaged.withSampleData() {
|
||||
return new 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 new SelectionUserManaged(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new SelectionUserManagedState();
|
||||
}
|
||||
}
|
||||
|
||||
class SelectionUserManagedState extends State<SelectionUserManaged> {
|
||||
final _myState = new charts.UserManagedState<String>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final chart = new charts.BarChart(
|
||||
widget.seriesList,
|
||||
animate: false, //widget.animate,
|
||||
selectionModels: [
|
||||
new 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: [
|
||||
new charts.InitialSelection(selectedDataConfig: [
|
||||
new charts.SeriesDatumConfig<String>('Sales', '2016')
|
||||
])
|
||||
],
|
||||
);
|
||||
|
||||
final clearSelection = new MaterialButton(
|
||||
onPressed: _handleClearSelection, child: new Text('Clear Selection'));
|
||||
|
||||
return new Column(
|
||||
children: [new SizedBox(child: chart, height: 150.0), 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] =
|
||||
new 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] =
|
||||
new charts.UserManagedSelectionModel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
196
web/charts/example/lib/behaviors/slider.dart
Normal file
196
web/charts/example/lib/behaviors/slider.dart
Normal file
@@ -0,0 +1,196 @@
|
||||
// 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_web/material.dart';
|
||||
import 'package:flutter_web/rendering.dart';
|
||||
import 'package:flutter_web/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> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SliderLine(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [LineChart] with sample data and no transition.
|
||||
factory SliderLine.withSampleData() {
|
||||
return new 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 new SliderLine(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<LinearSales, num>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new LinearSales(0, random.nextInt(100)),
|
||||
new LinearSales(1, random.nextInt(100)),
|
||||
new LinearSales(2, random.nextInt(100)),
|
||||
new LinearSales(3, random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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() => new _SliderCallbackState();
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<LinearSales, int>> _createSampleData() {
|
||||
final data = [
|
||||
new LinearSales(0, 5),
|
||||
new LinearSales(1, 25),
|
||||
new LinearSales(2, 100),
|
||||
new LinearSales(3, 75),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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>[
|
||||
new SizedBox(
|
||||
height: 150.0,
|
||||
child: new 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: [
|
||||
new charts.Slider(
|
||||
initialDomainValue: 1.0, onChangeCallback: _onSliderChange),
|
||||
],
|
||||
)),
|
||||
];
|
||||
|
||||
// If there is a slider change event, then include the details.
|
||||
if (_sliderDomainValue != null) {
|
||||
children.add(new Padding(
|
||||
padding: new EdgeInsets.only(top: 5.0),
|
||||
child: new Text('Slider domain value: ${_sliderDomainValue}')));
|
||||
}
|
||||
if (_sliderPosition != null) {
|
||||
children.add(new Padding(
|
||||
padding: new EdgeInsets.only(top: 5.0),
|
||||
child: new Text(
|
||||
'Slider position: ${_sliderPosition.x}, ${_sliderPosition.y}')));
|
||||
}
|
||||
if (_sliderDragState != null) {
|
||||
children.add(new Padding(
|
||||
padding: new EdgeInsets.only(top: 5.0),
|
||||
child: new Text('Slider drag state: ${_sliderDragState}')));
|
||||
}
|
||||
|
||||
return new Column(children: children);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
final int year;
|
||||
final int sales;
|
||||
|
||||
LinearSales(this.year, this.sales);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// 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_web/material.dart';
|
||||
|
||||
class SlidingViewportOnSelection extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SlidingViewportOnSelection(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory SlidingViewportOnSelection.withSampleData() {
|
||||
return new 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 new SlidingViewportOnSelection(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new OrdinalSales('2014', random.nextInt(100)),
|
||||
new OrdinalSales('2015', random.nextInt(100)),
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
new OrdinalSales('2018', random.nextInt(100)),
|
||||
new OrdinalSales('2019', random.nextInt(100)),
|
||||
new OrdinalSales('2020', random.nextInt(100)),
|
||||
new OrdinalSales('2021', random.nextInt(100)),
|
||||
new OrdinalSales('2022', random.nextInt(100)),
|
||||
new OrdinalSales('2023', random.nextInt(100)),
|
||||
new OrdinalSales('2024', random.nextInt(100)),
|
||||
new OrdinalSales('2025', random.nextInt(100)),
|
||||
new OrdinalSales('2026', random.nextInt(100)),
|
||||
new OrdinalSales('2027', random.nextInt(100)),
|
||||
new OrdinalSales('2028', random.nextInt(100)),
|
||||
new OrdinalSales('2029', random.nextInt(100)),
|
||||
new OrdinalSales('2030', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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 new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
behaviors: [
|
||||
// Add the sliding viewport behavior to have the viewport center on the
|
||||
// domain that is currently selected.
|
||||
new 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.
|
||||
new charts.PanAndZoomBehavior(),
|
||||
],
|
||||
// Set an initial viewport to demonstrate the sliding viewport behavior on
|
||||
// initial chart load.
|
||||
domainAxis: new charts.OrdinalAxisSpec(
|
||||
viewport: new charts.OrdinalViewport('2018', 4)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final data = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
new OrdinalSales('2018', 33),
|
||||
new OrdinalSales('2019', 80),
|
||||
new OrdinalSales('2020', 21),
|
||||
new OrdinalSales('2021', 77),
|
||||
new OrdinalSales('2022', 8),
|
||||
new OrdinalSales('2023', 12),
|
||||
new OrdinalSales('2024', 42),
|
||||
new OrdinalSales('2025', 70),
|
||||
new OrdinalSales('2026', 77),
|
||||
new OrdinalSales('2027', 55),
|
||||
new OrdinalSales('2028', 19),
|
||||
new OrdinalSales('2029', 66),
|
||||
new OrdinalSales('2030', 27),
|
||||
];
|
||||
|
||||
return [
|
||||
new 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);
|
||||
}
|
||||
Reference in New Issue
Block a user