first commit
79
CHANGELOG.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# 0.12.0
|
||||
* Add functions to draw horizontal or vertical links onto the dart charts web canvas.
|
||||
* Add "preserveSelection" functionality to InitialSelection chart Behavior.
|
||||
* Bug fixes.
|
||||
|
||||
# 0.11.0
|
||||
* Null support
|
||||
* Update to latest from internal repo
|
||||
|
||||
# 0.10.0
|
||||
* Internal bug fixes
|
||||
* Bump versions of intl due to pull request
|
||||
|
||||
# 0.9.0
|
||||
* Internal bug fixes
|
||||
* Bump versions in Gemlock file due to security alerts
|
||||
|
||||
# 0.8.1
|
||||
* Update intl version.
|
||||
|
||||
# 0.8.0
|
||||
* Bug fixes from open source.
|
||||
|
||||
# 0.7.0
|
||||
* Added vertical bar label
|
||||
|
||||
# 0.6.0
|
||||
* Bars can now be rendered on line charts.
|
||||
* Negative measure values will now be rendered on bar charts as a separate stack from the positive
|
||||
values.
|
||||
* Added a Datum Legend, which displays one entry per value in the first series on the chart. This is
|
||||
useful for pie and scatter plot charts.
|
||||
* The AxisPosition enum in RTLSpec was refactored to AxisDirection to better reflect its effect on
|
||||
swapping the positions of all start and end components, and not just positioning the measure axes.
|
||||
* Added custom colors for line renderer area skirts and confidence intervals. A new "areaColorFn"
|
||||
has been added to Series, and corresponding data to the datum. We could not use the fillColorFn for
|
||||
these elements, because that color is already applied to the internal section of points on line
|
||||
charts (including highlighter behaviors).
|
||||
|
||||
# 0.5.0
|
||||
* SelectionModelConfig's listener parameter has been renamed to "changeListener". This is a breaking
|
||||
change. Please rename any existing uses of the "listener" parameter to "changeListener". This was
|
||||
named in order to add an additional listener "updateListener" that listens to any update requests,
|
||||
regardless if the selection model has changed.
|
||||
* CartesianChart's method getMeasureAxis(String axisId) has been changed to
|
||||
getMeasureAxis({String axisId) so that getting the primary measure axis will not need passing any id
|
||||
that does not match the secondary measure axis id. This affects users implementing custom behaviors
|
||||
using the existing method.
|
||||
|
||||
# 0.4.0
|
||||
* Fixed export file to export ChartsBehavior in the Flutter library instead of the one that resides
|
||||
in charts_common. The charts_common behavior should not be used except internally in the
|
||||
charts_flutter library. This is a breaking change if you are using charts_common behavior.
|
||||
* Declare compatibility with Dart 2.
|
||||
* BasicNumericTickFormatterSpec now takes in a callback instead of NumberFormat as the default
|
||||
constructor. Use named constructor withNumberFormat instead. This is a breaking change.
|
||||
* BarRendererConfig is no longer default of type String, please change current usage to
|
||||
BarRendererConfig<String>. This is a breaking change.
|
||||
* BarTargetLineRendererConfig is no longer default of type String, please change current usage to
|
||||
BarTargetLineRendererConfig<String>. This is a breaking change.
|
||||
|
||||
# 0.3.0
|
||||
* Simplified API by removing the requirement for specifying the datum type when creating a chart.
|
||||
For example, previously to construct a bar chart the syntax was 'new BarChart<MyDatumType>()'.
|
||||
The syntax is now cleaned up to be 'new BarChart()'. Please refer to the
|
||||
[online gallery](https://google.github.io/charts/flutter/gallery.html) for the correct syntax.
|
||||
* Added scatter plot charts
|
||||
* Added tap to hide for legends
|
||||
* Added support for rendering area skirts to line charts
|
||||
* Added support for configurable fill colors to bar charts
|
||||
|
||||
# 0.2.0
|
||||
|
||||
* Update color palette. Please use MaterialPalette instead of QuantumPalette.
|
||||
* Dart2 fixes
|
||||
|
||||
# 0.1.0
|
||||
|
||||
Initial release.
|
||||
202
LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
6
charts_flutter.gwsq
Normal file
@@ -0,0 +1,6 @@
|
||||
send_cls_to('dart-charts-team+reviews');
|
||||
send_cls_to('dart-charts-team');
|
||||
|
||||
define Main {
|
||||
reassign_to_list(from_owners_file('third_party/dart/charts_common/OWNERS'));
|
||||
}
|
||||
12
example/android.iml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/android">
|
||||
<sourceFolder url="file://$MODULE_DIR$/android/app/src/main/java" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
7
example/android/Android_Charts.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<configuration
|
||||
name="Android Charts"
|
||||
type="FlutterBazelRunConfigurationType"
|
||||
factoryName="Flutter (Bazel)">
|
||||
<option name="bazelTarget" value="//third_party/dart/charts_flutter/example/android:Charts" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
51
example/android/app/build.gradle
Normal file
@@ -0,0 +1,51 @@
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.example.examples"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
|
||||
}
|
||||
39
example/android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.examples">
|
||||
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
<application
|
||||
android:name="io.flutter.app.FlutterApplication"
|
||||
android:label="Charts Flutter Gallery"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- This keeps the window background of the activity showing
|
||||
until Flutter renders its first frame. It can be removed if
|
||||
there is no splash screen (such as the default splash screen
|
||||
defined in @style/LaunchTheme). -->
|
||||
<meta-data
|
||||
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
|
||||
android:value="true" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.example.examples;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
/**
|
||||
* FlutterActivity
|
||||
*/
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
BIN
example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 544 B |
BIN
example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
8
example/android/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
</resources>
|
||||
29
example/android/build.gradle
Normal file
@@ -0,0 +1,29 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.buildDir = '../build'
|
||||
subprojects {
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
4
example/android/gradle.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
BIN
example/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
example/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Wed Feb 19 15:38:12 AWST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
160
example/android/gradlew
vendored
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
example/android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
15
example/android/settings.gradle
Normal file
@@ -0,0 +1,15 @@
|
||||
include ':app'
|
||||
|
||||
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||
|
||||
def plugins = new Properties()
|
||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||
if (pluginsFile.exists()) {
|
||||
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
|
||||
}
|
||||
|
||||
plugins.each { name, path ->
|
||||
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||
include ":$name"
|
||||
project(":$name").projectDir = pluginDirectory
|
||||
}
|
||||
17
example/examples.iml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Flutter Plugins" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
26
example/examples_android.iml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/android/gen" />
|
||||
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/android/gen" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/android/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/android/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/android/assets" />
|
||||
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/android/libs" />
|
||||
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/android/proguard_logs" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/android">
|
||||
<sourceFolder url="file://$MODULE_DIR$/android/app/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/android/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
30
example/ios/Flutter/AppFrameworkInfo.plist
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
1
example/ios/Flutter/Debug.xcconfig
Normal file
@@ -0,0 +1 @@
|
||||
#include "Generated.xcconfig"
|
||||
1
example/ios/Flutter/Release.xcconfig
Normal file
@@ -0,0 +1 @@
|
||||
#include "Generated.xcconfig"
|
||||
7
example/ios/Ios_Charts.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<configuration
|
||||
name="Ios Charts"
|
||||
type="FlutterBazelRunConfigurationType"
|
||||
factoryName="Flutter (Bazel)">
|
||||
<option name="bazelTarget" value="//third_party/dart/charts_flutter/example/ios:Charts" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
436
example/ios/Runner.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,436 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
|
||||
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
|
||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
|
||||
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
|
||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
|
||||
3B80C3931E831B6300D905FE /* App.framework */,
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
97C146F11CF9000F007C117D /* Supporting Files */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F11CF9000F007C117D /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146F21CF9000F007C117D /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0910;
|
||||
ORGANIZATIONNAME = "The Chromium Authors";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ARCHS = arm64;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.examples;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ARCHS = arm64;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.examples;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
10
example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0730"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
22
example/ios/Runner/AppDelegate.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder<UIApplicationDelegate>
|
||||
|
||||
@property(strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
58
example/ios/Runner/AppDelegate.m
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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.
|
||||
|
||||
#include "AppDelegate.h"
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for
|
||||
// certain types of temporary interruptions (such as an incoming phone call or SMS message) or
|
||||
// when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame
|
||||
// rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store
|
||||
// enough application state information to restore your application to its current state in case
|
||||
// it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of
|
||||
// applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo
|
||||
// many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive.
|
||||
// If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also
|
||||
// applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small-40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small-40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small-40.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small-40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
27
example/ios/Runner/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
26
example/ios/Runner/Base.lproj/Main.storyboard
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Flutter View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
47
example/ios/Runner/Info.plist
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Charts Flutter Gallery</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
24
example/ios/Runner/main.m
Normal file
@@ -0,0 +1,24 @@
|
||||
// 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 <Flutter/Flutter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
29
example/lib/a11y/a11y_gallery.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import 'package:flutter/material.dart';
|
||||
import '../gallery_scaffold.dart';
|
||||
import 'domain_a11y_explore_bar_chart.dart';
|
||||
|
||||
List<GalleryScaffold> buildGallery() {
|
||||
return [
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.accessibility),
|
||||
title: 'Screen reader enabled bar chart',
|
||||
subtitle: 'Requires TalkBack or Voiceover turned on to work. '
|
||||
'Bar chart with domain selection explore mode behavior.',
|
||||
childBuilder: () => new DomainA11yExploreBarChart.withRandomData(),
|
||||
),
|
||||
];
|
||||
}
|
||||
215
example/lib/a11y/domain_a11y_explore_bar_chart.dart
Normal file
@@ -0,0 +1,215 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of a bar chart with domain selection A11y behavior.
|
||||
///
|
||||
/// The OS screen reader (TalkBack / VoiceOver) setting must be turned on, or
|
||||
/// the behavior does not do anything.
|
||||
///
|
||||
/// Note that the screenshot does not show any visual differences but when the
|
||||
/// OS screen reader is enabled, the node that is being read out loud will be
|
||||
/// surrounded by a rectangle.
|
||||
///
|
||||
/// When [DomainA11yExploreBehavior] is added to the chart, the chart will
|
||||
/// listen for the gesture that triggers "explore mode".
|
||||
/// "Explore mode" creates semantic nodes for each domain value in the chart
|
||||
/// with a description (customizable, defaults to domain value) and a bounding
|
||||
/// box that surrounds the domain.
|
||||
///
|
||||
/// These semantic node descriptions are read out loud by the OS screen reader
|
||||
/// when the user taps within the bounding box, or when the user cycles through
|
||||
/// the screen's elements (such as swiping left and right).
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DomainA11yExploreBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
DomainA11yExploreBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory DomainA11yExploreBarChart.withSampleData() {
|
||||
return new DomainA11yExploreBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory DomainA11yExploreBarChart.withRandomData() {
|
||||
return new DomainA11yExploreBarChart(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final mobileData = [
|
||||
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 tabletData = [
|
||||
// Purposely missing data to show that only measures that are available
|
||||
// are vocalized.
|
||||
new OrdinalSales('2016', random.nextInt(100)),
|
||||
new OrdinalSales('2017', random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile Sales',
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet Sales',
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tabletData,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
/// An example of how to generate a customized vocalization for
|
||||
/// [DomainA11yExploreBehavior] from a list of [SeriesDatum]s.
|
||||
///
|
||||
/// The list of series datums is for one domain.
|
||||
///
|
||||
/// This example vocalizes the domain, then for each series that has that
|
||||
/// domain, it vocalizes the series display name and the measure and a
|
||||
/// description of that measure.
|
||||
String vocalizeDomainAndMeasures(List<charts.SeriesDatum> seriesDatums) {
|
||||
final buffer = new StringBuffer();
|
||||
|
||||
// The datum's type in this case is [OrdinalSales].
|
||||
// So we can access year and sales information here.
|
||||
buffer.write(seriesDatums.first.datum.year);
|
||||
|
||||
for (charts.SeriesDatum seriesDatum in seriesDatums) {
|
||||
final series = seriesDatum.series;
|
||||
final datum = seriesDatum.datum;
|
||||
|
||||
buffer.write(' ${series.displayName} '
|
||||
'${datum.sales / 1000} thousand dollars');
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Semantics(
|
||||
// Describe your chart
|
||||
label: 'Yearly sales bar chart',
|
||||
// Optionally provide a hint for the user to know how to trigger
|
||||
// explore mode.
|
||||
hint: 'Press and hold to enable explore',
|
||||
child: new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
// To prevent conflict with the select nearest behavior that uses the
|
||||
// tap gesture, turn off default interactions when the user is using
|
||||
// an accessibility service like TalkBack or VoiceOver to interact
|
||||
// with the application.
|
||||
defaultInteractions: !MediaQuery.of(context).accessibleNavigation,
|
||||
behaviors: [
|
||||
new charts.DomainA11yExploreBehavior(
|
||||
// Callback for generating the message that is vocalized.
|
||||
// An example of how to use is in [vocalizeDomainAndMeasures].
|
||||
// If none is set, the default only vocalizes the domain value.
|
||||
vocalizationCallback: vocalizeDomainAndMeasures,
|
||||
// The following settings are optional, but shown here for
|
||||
// demonstration purchases.
|
||||
// [exploreModeTrigger] Default is press and hold, can be
|
||||
// changed to tap.
|
||||
exploreModeTrigger: charts.ExploreModeTrigger.pressHold,
|
||||
// [exploreModeEnabledAnnouncement] Optionally notify the OS
|
||||
// when explore mode is enabled.
|
||||
exploreModeEnabledAnnouncement: 'Explore mode enabled',
|
||||
// [exploreModeDisabledAnnouncement] Optionally notify the OS
|
||||
// when explore mode is disabled.
|
||||
exploreModeDisabledAnnouncement: 'Explore mode disabled',
|
||||
// [minimumWidth] Default and minimum is 1.0. This is the
|
||||
// minimum width of the screen reader bounding box. The bounding
|
||||
// box width is calculated based on the domain axis step size.
|
||||
// Minimum width will be used if the step size is smaller.
|
||||
minimumWidth: 1.0,
|
||||
),
|
||||
// Optionally include domain highlighter as a behavior.
|
||||
// This behavior is included in this example to show that when an
|
||||
// a11y node has focus, the chart's internal selection model is
|
||||
// also updated.
|
||||
new charts.DomainHighlighter(charts.SelectionModelType.info),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final mobileData = [
|
||||
new OrdinalSales('2014', 5),
|
||||
new OrdinalSales('2015', 25),
|
||||
new OrdinalSales('2016', 100),
|
||||
new OrdinalSales('2017', 75),
|
||||
];
|
||||
|
||||
final tabletData = [
|
||||
// Purposely missing data to show that only measures that are available
|
||||
// are vocalized.
|
||||
new OrdinalSales('2016', 25),
|
||||
new OrdinalSales('2017', 50),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile Sales',
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet Sales',
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tabletData,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
44
example/lib/app_config.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A particular configuration of the app.
|
||||
class AppConfig {
|
||||
final String appName;
|
||||
final String appLink;
|
||||
final ThemeData theme;
|
||||
final bool showPerformanceOverlay;
|
||||
|
||||
AppConfig({
|
||||
required this.appName,
|
||||
required this.appLink,
|
||||
required this.theme,
|
||||
required this.showPerformanceOverlay,
|
||||
});
|
||||
}
|
||||
|
||||
/// The default configuration of the app.
|
||||
AppConfig get defaultConfig {
|
||||
return new AppConfig(
|
||||
appName: 'Charts Gallery',
|
||||
appLink: '',
|
||||
theme: new ThemeData(
|
||||
brightness: Brightness.light,
|
||||
primarySwatch: Colors.lightBlue,
|
||||
),
|
||||
showPerformanceOverlay: false,
|
||||
);
|
||||
}
|
||||
137
example/lib/axes/axes_gallery.dart
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../gallery_scaffold.dart';
|
||||
import 'bar_secondary_axis.dart';
|
||||
import 'bar_secondary_axis_only.dart';
|
||||
import 'custom_axis_tick_formatters.dart';
|
||||
import 'custom_font_size_and_color.dart';
|
||||
import 'custom_measure_tick_count.dart';
|
||||
import 'gridline_dash_pattern.dart';
|
||||
import 'hidden_ticks_and_labels_axis.dart';
|
||||
import 'horizontal_bar_secondary_axis.dart';
|
||||
import 'integer_only_measure_axis.dart';
|
||||
import 'line_disjoint_axis.dart';
|
||||
import 'measure_axis_label_alignment.dart';
|
||||
import 'numeric_initial_viewport.dart';
|
||||
import 'nonzero_bound_measure_axis.dart';
|
||||
import 'ordinal_initial_viewport.dart';
|
||||
import 'short_tick_length_axis.dart';
|
||||
import 'statically_provided_ticks.dart';
|
||||
|
||||
List<GalleryScaffold> buildGallery() {
|
||||
return [
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Bar chart with Secondary Measure Axis',
|
||||
subtitle: 'Bar chart with a series using a secondary measure axis',
|
||||
childBuilder: () => new BarChartWithSecondaryAxis.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Bar chart with Secondary Measure Axis only',
|
||||
subtitle: 'Bar chart with both series using secondary measure axis',
|
||||
childBuilder: () => new BarChartWithSecondaryAxisOnly.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Horizontal bar chart with Secondary Measure Axis',
|
||||
subtitle:
|
||||
'Horizontal Bar chart with a series using secondary measure axis',
|
||||
childBuilder: () =>
|
||||
new HorizontalBarChartWithSecondaryAxis.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Short Ticks Axis',
|
||||
subtitle: 'Bar chart with the primary measure axis having short ticks',
|
||||
childBuilder: () => new ShortTickLengthAxis.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Custom Axis Fonts',
|
||||
subtitle: 'Bar chart with custom axis font size and color',
|
||||
childBuilder: () => new CustomFontSizeAndColor.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Label Alignment Axis',
|
||||
subtitle: 'Bar chart with custom measure axis label alignments',
|
||||
childBuilder: () => new MeasureAxisLabelAlignment.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'No Axis',
|
||||
subtitle: 'Bar chart with only the axis line drawn',
|
||||
childBuilder: () => new HiddenTicksAndLabelsAxis.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Statically Provided Ticks',
|
||||
subtitle: 'Bar chart with statically provided ticks',
|
||||
childBuilder: () => new StaticallyProvidedTicks.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Custom Formatter',
|
||||
subtitle: 'Timeseries with custom domain and measure tick formatters',
|
||||
childBuilder: () => new CustomAxisTickFormatters.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Custom Tick Count',
|
||||
subtitle: 'Timeseries with custom measure axis tick count',
|
||||
childBuilder: () => new CustomMeasureTickCount.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Integer Measure Ticks',
|
||||
subtitle: 'Timeseries with only whole number measure axis ticks',
|
||||
childBuilder: () => new IntegerOnlyMeasureAxis.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Non-zero bound Axis',
|
||||
subtitle: 'Timeseries with measure axis that does not include zero',
|
||||
childBuilder: () => new NonzeroBoundMeasureAxis.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Ordinal axis with initial viewport',
|
||||
subtitle: 'Single series with initial viewport',
|
||||
childBuilder: () => new OrdinalInitialViewport.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Numeric axis with initial viewport',
|
||||
subtitle: 'Initial viewport is set to a subset of the data',
|
||||
childBuilder: () => new NumericInitialViewport.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Gridline dash pattern',
|
||||
subtitle: 'Timeseries with measure gridlines that have a dash pattern',
|
||||
childBuilder: () => new GridlineDashPattern.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.show_chart),
|
||||
title: 'Disjoint Measure Axes',
|
||||
subtitle: 'Line chart with disjoint measure axes',
|
||||
childBuilder: () => new DisjointMeasureAxisLineChart.withRandomData(),
|
||||
),
|
||||
];
|
||||
}
|
||||
158
example/lib/axes/bar_secondary_axis.dart
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of using a primary and secondary axis (left & right respectively)
|
||||
/// for a set of grouped bars. This is useful for comparing Series that have
|
||||
/// different units (revenue vs clicks by region), or different magnitudes (2017
|
||||
/// revenue vs 1/1/2017 revenue by region).
|
||||
///
|
||||
/// The first series plots using the primary axis to position its measure
|
||||
/// values (bar height). This is the default axis used if the measureAxisId is
|
||||
/// not set.
|
||||
///
|
||||
/// The second series plots using the secondary axis due to the measureAxisId of
|
||||
/// secondaryMeasureAxisId.
|
||||
///
|
||||
/// Note: primary and secondary may flip left and right positioning when
|
||||
/// RTL.flipAxisLocations is set.
|
||||
class BarChartWithSecondaryAxis extends StatelessWidget {
|
||||
static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
BarChartWithSecondaryAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
factory BarChartWithSecondaryAxis.withSampleData() {
|
||||
return new BarChartWithSecondaryAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory BarChartWithSecondaryAxis.withRandomData() {
|
||||
return new BarChartWithSecondaryAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
final losAngelesSalesData = [
|
||||
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: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Los Angeles Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: losAngelesSalesData,
|
||||
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
|
||||
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
|
||||
// All series that have this set will use the secondary measure axis.
|
||||
// All other series will use the primary measure axis.
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
barGroupingType: charts.BarGroupingType.grouped,
|
||||
// It is important when using both primary and secondary axes to choose
|
||||
// the same number of ticks for both sides to get the gridlines to line
|
||||
// up.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
|
||||
secondaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
final losAngelesSalesData = [
|
||||
new OrdinalSales('2014', 25),
|
||||
new OrdinalSales('2015', 50),
|
||||
new OrdinalSales('2016', 10),
|
||||
new OrdinalSales('2017', 20),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Los Angeles Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: losAngelesSalesData,
|
||||
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
|
||||
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
|
||||
// All series that have this set will use the secondary measure axis.
|
||||
// All other series will use the primary measure axis.
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
114
example/lib/axes/bar_secondary_axis_only.dart
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of using only a secondary axis (on the right) for a set of grouped
|
||||
/// bars.
|
||||
///
|
||||
/// Both series plots using the secondary axis due to the measureAxisId of
|
||||
/// secondaryMeasureAxisId.
|
||||
///
|
||||
/// Note: secondary may flip left and right positioning when
|
||||
/// RTL.flipAxisLocations is set.
|
||||
class BarChartWithSecondaryAxisOnly extends StatelessWidget {
|
||||
static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
BarChartWithSecondaryAxisOnly(this.seriesList, {this.animate = false});
|
||||
|
||||
factory BarChartWithSecondaryAxisOnly.withSampleData() {
|
||||
return new BarChartWithSecondaryAxisOnly(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory BarChartWithSecondaryAxisOnly.withRandomData() {
|
||||
return new BarChartWithSecondaryAxisOnly(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
)
|
||||
// Set series to use the secondary measure axis.
|
||||
..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 500),
|
||||
new OrdinalSales('2015', 2500),
|
||||
new OrdinalSales('2016', 1000),
|
||||
new OrdinalSales('2017', 7500),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
)
|
||||
// Set series to use the secondary measure axis.
|
||||
..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
144
example/lib/axes/custom_axis_tick_formatters.dart
Normal file
@@ -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 timeseries chart with custom measure and domain formatters.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class CustomAxisTickFormatters extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, DateTime>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
CustomAxisTickFormatters(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [TimeSeriesChart] with sample data and no transition.
|
||||
factory CustomAxisTickFormatters.withSampleData() {
|
||||
return new CustomAxisTickFormatters(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory CustomAxisTickFormatters.withRandomData() {
|
||||
return new CustomAxisTickFormatters(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 26), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 27), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 28), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 29), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 30), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 01), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 02), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 03), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 04), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 05), random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Cost',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.cost,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/// Formatter for numeric ticks using [NumberFormat] to format into currency
|
||||
///
|
||||
/// This is what is used in the [NumericAxisSpec] below.
|
||||
final simpleCurrencyFormatter =
|
||||
new charts.BasicNumericTickFormatterSpec.fromNumberFormat(
|
||||
new NumberFormat.compactSimpleCurrency());
|
||||
|
||||
/// Formatter for numeric ticks that uses the callback provided.
|
||||
///
|
||||
/// Use this formatter if you need to format values that [NumberFormat]
|
||||
/// cannot provide.
|
||||
///
|
||||
/// To see this formatter, change [NumericAxisSpec] to use this formatter.
|
||||
// final customTickFormatter =
|
||||
// charts.BasicNumericTickFormatterSpec((num value) => 'MyValue: $value');
|
||||
|
||||
return new charts.TimeSeriesChart(seriesList,
|
||||
animate: animate,
|
||||
// Sets up a currency formatter for the measure axis.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickFormatterSpec: simpleCurrencyFormatter),
|
||||
|
||||
/// Customizes the date tick formatter. It will print the day of month
|
||||
/// as the default format, but include the month and year if it
|
||||
/// transitions to a new month.
|
||||
///
|
||||
/// minute, hour, day, month, and year are all provided by default and
|
||||
/// you can override them following this pattern.
|
||||
domainAxis: new charts.DateTimeAxisSpec(
|
||||
tickFormatterSpec: new charts.AutoDateTimeTickFormatterSpec(
|
||||
day: new charts.TimeFormatterSpec(
|
||||
format: 'd', transitionFormat: 'MM/dd/yyyy'))));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), 6),
|
||||
new MyRow(new DateTime(2017, 9, 26), 8),
|
||||
new MyRow(new DateTime(2017, 9, 27), 6),
|
||||
new MyRow(new DateTime(2017, 9, 28), 9),
|
||||
new MyRow(new DateTime(2017, 9, 29), 11),
|
||||
new MyRow(new DateTime(2017, 9, 30), 15),
|
||||
new MyRow(new DateTime(2017, 10, 01), 25),
|
||||
new MyRow(new DateTime(2017, 10, 02), 33),
|
||||
new MyRow(new DateTime(2017, 10, 03), 27),
|
||||
new MyRow(new DateTime(2017, 10, 04), 31),
|
||||
new MyRow(new DateTime(2017, 10, 05), 23),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Cost',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.cost,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample time series data type.
|
||||
class MyRow {
|
||||
final DateTime timeStamp;
|
||||
final int cost;
|
||||
MyRow(this.timeStamp, this.cost);
|
||||
}
|
||||
136
example/lib/axes/custom_font_size_and_color.dart
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Custom Font Style Example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of using a custom primary measure and domain axis replacing the
|
||||
/// renderSpec with one with a custom font size and a custom color.
|
||||
///
|
||||
/// There are many axis styling options in the SmallTickRenderer allowing you
|
||||
/// to customize the font, tick lengths, and offsets.
|
||||
class CustomFontSizeAndColor extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
CustomFontSizeAndColor(this.seriesList, {this.animate = false});
|
||||
|
||||
factory CustomFontSizeAndColor.withSampleData() {
|
||||
return new CustomFontSizeAndColor(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory CustomFontSizeAndColor.withRandomData() {
|
||||
return new CustomFontSizeAndColor(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Assign a custom style for the domain axis.
|
||||
///
|
||||
/// This is an OrdinalAxisSpec to match up with BarChart's default
|
||||
/// ordinal domain axis (use NumericAxisSpec or DateTimeAxisSpec for
|
||||
/// other charts).
|
||||
domainAxis: new charts.OrdinalAxisSpec(
|
||||
renderSpec: new charts.SmallTickRendererSpec(
|
||||
|
||||
// Tick and Label styling here.
|
||||
labelStyle: new charts.TextStyleSpec(
|
||||
fontSize: 18, // size in Pts.
|
||||
color: charts.MaterialPalette.black),
|
||||
|
||||
// Change the line colors to match text color.
|
||||
lineStyle: new charts.LineStyleSpec(
|
||||
color: charts.MaterialPalette.black))),
|
||||
|
||||
/// Assign a custom style for the measure axis.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
renderSpec: new charts.GridlineRendererSpec(
|
||||
|
||||
// Tick and Label styling here.
|
||||
labelStyle: new charts.TextStyleSpec(
|
||||
fontSize: 18, // size in Pts.
|
||||
color: charts.MaterialPalette.black),
|
||||
|
||||
// Change the line colors to match text color.
|
||||
lineStyle: new charts.LineStyleSpec(
|
||||
color: charts.MaterialPalette.black))),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with single series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
122
example/lib/axes/custom_measure_tick_count.dart
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of timeseries chart with a custom number of ticks
|
||||
///
|
||||
/// The tick count can be set by setting the [desiredMinTickCount] and
|
||||
/// [desiredMaxTickCount] for automatically adjusted tick counts (based on
|
||||
/// how 'nice' the ticks are) or [desiredTickCount] for a fixed tick count.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomMeasureTickCount extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, DateTime>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
CustomMeasureTickCount(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [TimeSeriesChart] with sample data and no transition.
|
||||
factory CustomMeasureTickCount.withSampleData() {
|
||||
return new CustomMeasureTickCount(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory CustomMeasureTickCount.withRandomData() {
|
||||
return new CustomMeasureTickCount(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 26), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 27), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 28), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 29), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 30), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 01), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 02), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 03), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 04), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 05), random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Cost',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.cost,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.TimeSeriesChart(seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Customize the measure axis to have 2 ticks,
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.BasicNumericTickProviderSpec(desiredTickCount: 2)));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), 6),
|
||||
new MyRow(new DateTime(2017, 9, 26), 8),
|
||||
new MyRow(new DateTime(2017, 9, 27), 6),
|
||||
new MyRow(new DateTime(2017, 9, 28), 9),
|
||||
new MyRow(new DateTime(2017, 9, 29), 11),
|
||||
new MyRow(new DateTime(2017, 9, 30), 15),
|
||||
new MyRow(new DateTime(2017, 10, 01), 25),
|
||||
new MyRow(new DateTime(2017, 10, 02), 33),
|
||||
new MyRow(new DateTime(2017, 10, 03), 27),
|
||||
new MyRow(new DateTime(2017, 10, 04), 31),
|
||||
new MyRow(new DateTime(2017, 10, 05), 23),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Cost',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.cost,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample time series data type.
|
||||
class MyRow {
|
||||
final DateTime timeStamp;
|
||||
final int cost;
|
||||
MyRow(this.timeStamp, this.cost);
|
||||
}
|
||||
114
example/lib/axes/flipped_vertical_axis.dart
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of flipping the vertical measure axis direction so that larger
|
||||
/// values render downward instead of the usual rendering up.
|
||||
///
|
||||
/// flipVerticalAxis, when set, flips the vertical axis from its default
|
||||
/// direction.
|
||||
///
|
||||
/// Note: primary and secondary may flip left and right positioning when
|
||||
/// RTL.flipAxisLocations is set.
|
||||
class FlippedVerticalAxis extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
FlippedVerticalAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
factory FlippedVerticalAxis.withSampleData() {
|
||||
return new FlippedVerticalAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory FlippedVerticalAxis.withRandomData() {
|
||||
return new FlippedVerticalAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<RunnerRank, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
const runners = ['Smith', 'Jones', 'Brown', 'Doe'];
|
||||
|
||||
// Randomly assign runners, but leave the order of the places.
|
||||
final raceData = [
|
||||
new RunnerRank(runners.removeAt(random.nextInt(runners.length)), 1),
|
||||
new RunnerRank(runners.removeAt(random.nextInt(runners.length)), 2),
|
||||
new RunnerRank(runners.removeAt(random.nextInt(runners.length)), 3),
|
||||
new RunnerRank(runners.removeAt(random.nextInt(runners.length)), 4),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<RunnerRank, String>(
|
||||
id: 'Race Results',
|
||||
domainFn: (RunnerRank row, _) => row.name,
|
||||
measureFn: (RunnerRank row, _) => row.place,
|
||||
data: raceData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
// Known Issue, the bar chart cannot render negative direction bars at this
|
||||
// time so the result is an empty chart.
|
||||
// TODO: Remove this comment
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
flipVerticalAxis: true,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<RunnerRank, String>> _createSampleData() {
|
||||
final raceData = [
|
||||
new RunnerRank('Smith', 1),
|
||||
new RunnerRank('Jones', 2),
|
||||
new RunnerRank('Brown', 3),
|
||||
new RunnerRank('Doe', 4),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<RunnerRank, String>(
|
||||
id: 'Race Results',
|
||||
domainFn: (RunnerRank row, _) => row.name,
|
||||
measureFn: (RunnerRank row, _) => row.place,
|
||||
data: raceData),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Datum/Row for the chart.
|
||||
class RunnerRank {
|
||||
final String name;
|
||||
final int place;
|
||||
RunnerRank(this.name, this.place);
|
||||
}
|
||||
120
example/lib/axes/gridline_dash_pattern.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 timeseries chart with gridlines that have a dash pattern.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GridlineDashPattern extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, DateTime>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GridlineDashPattern(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [TimeSeriesChart] with sample data and no transition.
|
||||
factory GridlineDashPattern.withSampleData() {
|
||||
return new GridlineDashPattern(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GridlineDashPattern.withRandomData() {
|
||||
return new GridlineDashPattern(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 26), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 27), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 28), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 29), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 9, 30), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 01), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 02), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 03), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 04), random.nextInt(100)),
|
||||
new MyRow(new DateTime(2017, 10, 05), random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Cost',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.cost,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.TimeSeriesChart(seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Customize the gridlines to use a dash pattern.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
renderSpec: charts.GridlineRendererSpec(
|
||||
lineStyle: charts.LineStyleSpec(
|
||||
dashPattern: [4, 4],
|
||||
))));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), 6),
|
||||
new MyRow(new DateTime(2017, 9, 26), 8),
|
||||
new MyRow(new DateTime(2017, 9, 27), 6),
|
||||
new MyRow(new DateTime(2017, 9, 28), 9),
|
||||
new MyRow(new DateTime(2017, 9, 29), 11),
|
||||
new MyRow(new DateTime(2017, 9, 30), 15),
|
||||
new MyRow(new DateTime(2017, 10, 01), 25),
|
||||
new MyRow(new DateTime(2017, 10, 02), 33),
|
||||
new MyRow(new DateTime(2017, 10, 03), 27),
|
||||
new MyRow(new DateTime(2017, 10, 04), 31),
|
||||
new MyRow(new DateTime(2017, 10, 05), 23),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Cost',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.cost,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample time series data type.
|
||||
class MyRow {
|
||||
final DateTime timeStamp;
|
||||
final int cost;
|
||||
MyRow(this.timeStamp, this.cost);
|
||||
}
|
||||
118
example/lib/axes/hidden_ticks_and_labels_axis.dart
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// No Axis Example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of hiding both axis.
|
||||
class HiddenTicksAndLabelsAxis extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
HiddenTicksAndLabelsAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
factory HiddenTicksAndLabelsAxis.withSampleData() {
|
||||
return new HiddenTicksAndLabelsAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory HiddenTicksAndLabelsAxis.withRandomData() {
|
||||
return new HiddenTicksAndLabelsAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Assign a custom style for the measure axis.
|
||||
///
|
||||
/// The NoneRenderSpec can still draw an axis line with
|
||||
/// showAxisLine=true.
|
||||
primaryMeasureAxis:
|
||||
new charts.NumericAxisSpec(renderSpec: new charts.NoneRenderSpec()),
|
||||
|
||||
/// This is an OrdinalAxisSpec to match up with BarChart's default
|
||||
/// ordinal domain axis (use NumericAxisSpec or DateTimeAxisSpec for
|
||||
/// other charts).
|
||||
domainAxis: new charts.OrdinalAxisSpec(
|
||||
// Make sure that we draw the domain axis line.
|
||||
showAxisLine: true,
|
||||
// But don't draw anything else.
|
||||
renderSpec: new charts.NoneRenderSpec()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with single series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
160
example/lib/axes/horizontal_bar_secondary_axis.dart
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of using a primary and secondary axis (left & right respectively)
|
||||
/// for a set of grouped bars. This is useful for comparing Series that have
|
||||
/// different units (revenue vs clicks by region), or different magnitudes (2017
|
||||
/// revenue vs 1/1/2017 revenue by region).
|
||||
///
|
||||
/// The first series plots using the primary axis to position its measure
|
||||
/// values (bar height). This is the default axis used if the measureAxisId is
|
||||
/// not set.
|
||||
///
|
||||
/// The second series plots using the secondary axis due to the measureAxisId of
|
||||
/// secondaryMeasureAxisId.
|
||||
///
|
||||
/// Note: primary and secondary may flip left and right positioning when
|
||||
/// RTL.flipAxisLocations is set.
|
||||
class HorizontalBarChartWithSecondaryAxis extends StatelessWidget {
|
||||
static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
HorizontalBarChartWithSecondaryAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
factory HorizontalBarChartWithSecondaryAxis.withSampleData() {
|
||||
return new HorizontalBarChartWithSecondaryAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory HorizontalBarChartWithSecondaryAxis.withRandomData() {
|
||||
return new HorizontalBarChartWithSecondaryAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
final losAngelesSalesData = [
|
||||
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: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Los Angeles Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: losAngelesSalesData,
|
||||
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
|
||||
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
|
||||
// All series that have this set will use the secondary measure axis.
|
||||
// All other series will use the primary measure axis.
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// For horizontal bar charts, set the [vertical] flag to false.
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
barGroupingType: charts.BarGroupingType.grouped,
|
||||
vertical: false,
|
||||
// It is important when using both primary and secondary axes to choose
|
||||
// the same number of ticks for both sides to get the gridlines to line
|
||||
// up.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
|
||||
secondaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.BasicNumericTickProviderSpec(desiredTickCount: 3)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
final losAngelesSalesData = [
|
||||
new OrdinalSales('2014', 25),
|
||||
new OrdinalSales('2015', 50),
|
||||
new OrdinalSales('2016', 10),
|
||||
new OrdinalSales('2017', 20),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Los Angeles Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: losAngelesSalesData,
|
||||
)..setAttribute(charts.measureAxisIdKey, secondaryMeasureAxisId)
|
||||
// Set the 'Los Angeles Revenue' series to use the secondary measure axis.
|
||||
// All series that have this set will use the secondary measure axis.
|
||||
// All other series will use the primary measure axis.
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
129
example/lib/axes/integer_only_measure_axis.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 timeseries chart forcing the measure axis to have whole number
|
||||
/// ticks. This is useful if the measure units don't make sense to present as
|
||||
/// fractional.
|
||||
///
|
||||
/// This is done by customizing the measure axis and setting
|
||||
/// [dataIsInWholeNumbers] on the tick provider.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class IntegerOnlyMeasureAxis extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, DateTime>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
IntegerOnlyMeasureAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [TimeSeriesChart] with sample data and no transition.
|
||||
factory IntegerOnlyMeasureAxis.withSampleData() {
|
||||
return new IntegerOnlyMeasureAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory IntegerOnlyMeasureAxis.withRandomData() {
|
||||
return new IntegerOnlyMeasureAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 9, 26), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 9, 27), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 9, 28), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 9, 29), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 9, 30), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 10, 01), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 10, 02), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 10, 03), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 10, 04), random.nextDouble().round()),
|
||||
new MyRow(new DateTime(2017, 10, 05), random.nextDouble().round()),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Headcount',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.headcount,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.TimeSeriesChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
// Provides a custom axis ensuring that the ticks are in whole numbers.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec: new charts.BasicNumericTickProviderSpec(
|
||||
// Make sure we don't have values less than 1 as ticks
|
||||
// (ie: counts).
|
||||
dataIsInWholeNumbers: true,
|
||||
// Fixed tick count to highlight the integer only behavior
|
||||
// generating ticks [0, 1, 2, 3, 4].
|
||||
desiredTickCount: 5)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), 0),
|
||||
new MyRow(new DateTime(2017, 9, 26), 0),
|
||||
new MyRow(new DateTime(2017, 9, 27), 0),
|
||||
new MyRow(new DateTime(2017, 9, 28), 0),
|
||||
new MyRow(new DateTime(2017, 9, 29), 0),
|
||||
new MyRow(new DateTime(2017, 9, 30), 0),
|
||||
new MyRow(new DateTime(2017, 10, 01), 1),
|
||||
new MyRow(new DateTime(2017, 10, 02), 1),
|
||||
new MyRow(new DateTime(2017, 10, 03), 1),
|
||||
new MyRow(new DateTime(2017, 10, 04), 1),
|
||||
new MyRow(new DateTime(2017, 10, 05), 1),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Headcount',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.headcount,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample time series data type.
|
||||
class MyRow {
|
||||
final DateTime timeStamp;
|
||||
final int headcount;
|
||||
MyRow(this.timeStamp, this.headcount);
|
||||
}
|
||||
268
example/lib/axes/line_disjoint_axis.dart
Normal file
@@ -0,0 +1,268 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of using disjoint measure axes to render 4 series of lines with
|
||||
/// separate scales. The general use case for this type of chart is to show
|
||||
/// differences in the trends of the data, without comparing their absolute
|
||||
/// values.
|
||||
///
|
||||
/// Disjoint measure axes will be used to scale the series associated with them,
|
||||
/// but they will not render any tick elements on either side of the chart.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:collection' show LinkedHashMap;
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DisjointMeasureAxisLineChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, num>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
DisjointMeasureAxisLineChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [LineChart] with sample data and no transition.
|
||||
factory DisjointMeasureAxisLineChart.withSampleData() {
|
||||
return new DisjointMeasureAxisLineChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory DisjointMeasureAxisLineChart.withRandomData() {
|
||||
return new DisjointMeasureAxisLineChart(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<LinearClicks, num>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
// The first three series contain similar data with different magnitudes.
|
||||
// This demonstrates the ability to graph the trends in each series relative
|
||||
// to each other, without the largest magnitude series compressing the
|
||||
// smallest.
|
||||
final myFakeDesktopData = [
|
||||
new LinearClicks(0, clickCount: random.nextInt(100)),
|
||||
new LinearClicks(1, clickCount: random.nextInt(100)),
|
||||
new LinearClicks(2, clickCount: random.nextInt(100)),
|
||||
new LinearClicks(3, clickCount: random.nextInt(100)),
|
||||
];
|
||||
|
||||
final myFakeTabletData = [
|
||||
new LinearClicks(0, clickCount: random.nextInt(100) * 100),
|
||||
new LinearClicks(1, clickCount: random.nextInt(100) * 100),
|
||||
new LinearClicks(2, clickCount: random.nextInt(100) * 100),
|
||||
new LinearClicks(3, clickCount: random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
final myFakeMobileData = [
|
||||
new LinearClicks(0, clickCount: random.nextInt(100) * 1000),
|
||||
new LinearClicks(1, clickCount: random.nextInt(100) * 1000),
|
||||
new LinearClicks(2, clickCount: random.nextInt(100) * 1000),
|
||||
new LinearClicks(3, clickCount: random.nextInt(100) * 1000),
|
||||
];
|
||||
|
||||
// The fourth series renders with decimal values, representing a very
|
||||
// different sort ratio-based data. If this was on the same axis as any of
|
||||
// the other series, it would be squashed near zero.
|
||||
final myFakeClickRateData = [
|
||||
new LinearClicks(0, clickRate: .25),
|
||||
new LinearClicks(1, clickRate: .65),
|
||||
new LinearClicks(2, clickRate: .50),
|
||||
new LinearClicks(3, clickRate: .30),
|
||||
];
|
||||
|
||||
return [
|
||||
// We render an empty series on the primary measure axis to ensure that
|
||||
// the axis itself gets rendered. This helps us draw the gridlines on the
|
||||
// chart.
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Fake Series',
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: []),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Desktop',
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeDesktopData,
|
||||
)
|
||||
// Set the 'Desktop' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 1'),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Tablet',
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeTabletData,
|
||||
)
|
||||
// Set the 'Tablet' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 2'),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Mobile',
|
||||
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeMobileData,
|
||||
)
|
||||
// Set the 'Mobile' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 3'),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Click Rate',
|
||||
colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeClickRateData,
|
||||
)
|
||||
// Set the 'Click Rate' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 4'),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.LineChart(seriesList,
|
||||
animate: animate,
|
||||
// Configure a primary measure axis that will render gridlines across
|
||||
// the chart. This axis uses fake ticks with no labels to ensure that we
|
||||
// get 5 grid lines.
|
||||
//
|
||||
// We do this because disjoint measure axes do not draw any tick
|
||||
// elements on the chart.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec: new charts.StaticNumericTickProviderSpec(
|
||||
// Create the ticks to be used the domain axis.
|
||||
<charts.TickSpec<num>>[
|
||||
new charts.TickSpec(0, label: ''),
|
||||
new charts.TickSpec(1, label: ''),
|
||||
new charts.TickSpec(2, label: ''),
|
||||
new charts.TickSpec(3, label: ''),
|
||||
new charts.TickSpec(4, label: ''),
|
||||
],
|
||||
)),
|
||||
// Create one disjoint measure axis per series on the chart.
|
||||
//
|
||||
// Disjoint measure axes will be used to scale the rendered data,
|
||||
// without drawing any tick elements on either side of the chart.
|
||||
disjointMeasureAxes:
|
||||
new LinkedHashMap<String, charts.NumericAxisSpec>.from({
|
||||
'axis 1': new charts.NumericAxisSpec(),
|
||||
'axis 2': new charts.NumericAxisSpec(),
|
||||
'axis 3': new charts.NumericAxisSpec(),
|
||||
'axis 4': new charts.NumericAxisSpec(),
|
||||
}));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<LinearClicks, int>> _createSampleData() {
|
||||
// The first three series contain similar data with different magnitudes.
|
||||
// This demonstrates the ability to graph the trends in each series relative
|
||||
// to each other, without the largest magnitude series compressing the
|
||||
// smallest.
|
||||
final myFakeDesktopData = [
|
||||
new LinearClicks(0, clickCount: 25),
|
||||
new LinearClicks(1, clickCount: 125),
|
||||
new LinearClicks(2, clickCount: 920),
|
||||
new LinearClicks(3, clickCount: 375),
|
||||
];
|
||||
|
||||
final myFakeTabletData = [
|
||||
new LinearClicks(0, clickCount: 375),
|
||||
new LinearClicks(1, clickCount: 1850),
|
||||
new LinearClicks(2, clickCount: 9700),
|
||||
new LinearClicks(3, clickCount: 5000),
|
||||
];
|
||||
|
||||
final myFakeMobileData = [
|
||||
new LinearClicks(0, clickCount: 5000),
|
||||
new LinearClicks(1, clickCount: 25000),
|
||||
new LinearClicks(2, clickCount: 100000),
|
||||
new LinearClicks(3, clickCount: 75000),
|
||||
];
|
||||
|
||||
// The fourth series renders with decimal values, representing a very
|
||||
// different sort ratio-based data. If this was on the same axis as any of
|
||||
// the other series, it would be squashed near zero.
|
||||
final myFakeClickRateData = [
|
||||
new LinearClicks(0, clickRate: .25),
|
||||
new LinearClicks(1, clickRate: .65),
|
||||
new LinearClicks(2, clickRate: .50),
|
||||
new LinearClicks(3, clickRate: .30),
|
||||
];
|
||||
|
||||
return [
|
||||
// We render an empty series on the primary measure axis to ensure that
|
||||
// the axis itself gets rendered. This helps us draw the gridlines on the
|
||||
// chart.
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Fake Series',
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: []),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Desktop',
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeDesktopData,
|
||||
)
|
||||
// Set the 'Desktop' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 1'),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Tablet',
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeTabletData,
|
||||
)
|
||||
// Set the 'Tablet' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 2'),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Mobile',
|
||||
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickCount,
|
||||
data: myFakeMobileData,
|
||||
)
|
||||
// Set the 'Mobile' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 3'),
|
||||
new charts.Series<LinearClicks, int>(
|
||||
id: 'Click Rate',
|
||||
colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault,
|
||||
domainFn: (LinearClicks clickCount, _) => clickCount.year,
|
||||
measureFn: (LinearClicks clickCount, _) => clickCount.clickRate,
|
||||
data: myFakeClickRateData,
|
||||
)
|
||||
// Set the 'Click Rate' series to use a disjoint axis.
|
||||
..setAttribute(charts.measureAxisIdKey, 'axis 4'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample linear data type.
|
||||
class LinearClicks {
|
||||
final int year;
|
||||
final int? clickCount;
|
||||
final double? clickRate;
|
||||
|
||||
LinearClicks(this.year, {this.clickCount, this.clickRate});
|
||||
}
|
||||
122
example/lib/axes/measure_axis_label_alignment.dart
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Custom Tick Label Alignment Example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of using a custom primary measure replacing the renderSpec with one
|
||||
/// that aligns the text under the tick and left justifies.
|
||||
class MeasureAxisLabelAlignment extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
MeasureAxisLabelAlignment(this.seriesList, {this.animate = false});
|
||||
|
||||
factory MeasureAxisLabelAlignment.withSampleData() {
|
||||
return new MeasureAxisLabelAlignment(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory MeasureAxisLabelAlignment.withRandomData() {
|
||||
return new MeasureAxisLabelAlignment(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Customize the primary measure axis using a small tick renderer.
|
||||
/// Use String instead of num for ordinal domain axis
|
||||
/// (typically bar charts).
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
renderSpec: new charts.GridlineRendererSpec(
|
||||
// Display the measure axis labels below the gridline.
|
||||
//
|
||||
// 'Before' & 'after' follow the axis value direction.
|
||||
// Vertical axes draw 'before' below & 'after' above the tick.
|
||||
// Horizontal axes draw 'before' left & 'after' right the tick.
|
||||
labelAnchor: charts.TickLabelAnchor.before,
|
||||
|
||||
// Left justify the text in the axis.
|
||||
//
|
||||
// Note: outside means that the secondary measure axis would right
|
||||
// justify.
|
||||
labelJustification: charts.TickLabelJustification.outside,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with single series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
119
example/lib/axes/nonzero_bound_measure_axis.dart
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of timeseries chart that has a measure axis that does NOT include
|
||||
/// zero. It starts at 100 and goes to 140.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NonzeroBoundMeasureAxis extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, DateTime>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
NonzeroBoundMeasureAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [TimeSeriesChart] with sample data and no transition.
|
||||
factory NonzeroBoundMeasureAxis.withSampleData() {
|
||||
return new NonzeroBoundMeasureAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory NonzeroBoundMeasureAxis.withRandomData() {
|
||||
return new NonzeroBoundMeasureAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 9, 26), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 9, 27), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 9, 28), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 9, 29), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 9, 30), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 10, 01), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 10, 02), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 10, 03), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 10, 04), random.nextInt(100) + 100),
|
||||
new MyRow(new DateTime(2017, 10, 05), random.nextInt(100) + 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Headcount',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.headcount,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.TimeSeriesChart(seriesList,
|
||||
animate: animate,
|
||||
// Provide a tickProviderSpec which does NOT require that zero is
|
||||
// included.
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.BasicNumericTickProviderSpec(zeroBound: false)));
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
|
||||
final data = [
|
||||
new MyRow(new DateTime(2017, 9, 25), 106),
|
||||
new MyRow(new DateTime(2017, 9, 26), 108),
|
||||
new MyRow(new DateTime(2017, 9, 27), 106),
|
||||
new MyRow(new DateTime(2017, 9, 28), 109),
|
||||
new MyRow(new DateTime(2017, 9, 29), 111),
|
||||
new MyRow(new DateTime(2017, 9, 30), 115),
|
||||
new MyRow(new DateTime(2017, 10, 01), 125),
|
||||
new MyRow(new DateTime(2017, 10, 02), 133),
|
||||
new MyRow(new DateTime(2017, 10, 03), 127),
|
||||
new MyRow(new DateTime(2017, 10, 04), 131),
|
||||
new MyRow(new DateTime(2017, 10, 05), 123),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<MyRow, DateTime>(
|
||||
id: 'Headcount',
|
||||
domainFn: (MyRow row, _) => row.timeStamp,
|
||||
measureFn: (MyRow row, _) => row.headcount,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample time series data type.
|
||||
class MyRow {
|
||||
final DateTime timeStamp;
|
||||
final int headcount;
|
||||
MyRow(this.timeStamp, this.headcount);
|
||||
}
|
||||
133
example/lib/axes/numeric_initial_viewport.dart
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of setting an initial viewport for ordinal axis.
|
||||
///
|
||||
/// This allows for specifying the specific range of data to show that differs
|
||||
/// from what was provided in the series list.
|
||||
///
|
||||
/// In this example, the series list has numeric data from 0 to 10, but we
|
||||
/// want to show from 3 to 7.
|
||||
/// We can do this by specifying an [NumericExtents] in [NumericAxisSpec].
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NumericInitialViewport extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, num>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
NumericInitialViewport(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [LineChart] with sample data and no transition.
|
||||
factory NumericInitialViewport.withSampleData() {
|
||||
return new NumericInitialViewport(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory NumericInitialViewport.withRandomData() {
|
||||
return new NumericInitialViewport(_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)),
|
||||
new LinearSales(4, random.nextInt(100)),
|
||||
new LinearSales(5, random.nextInt(100)),
|
||||
new LinearSales(6, random.nextInt(100)),
|
||||
new LinearSales(7, random.nextInt(100)),
|
||||
new LinearSales(8, random.nextInt(100)),
|
||||
new LinearSales(9, random.nextInt(100)),
|
||||
new LinearSales(10, random.nextInt(100)),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<LinearSales, int>(
|
||||
id: 'Sales',
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.sales,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.LineChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
domainAxis: new charts.NumericAxisSpec(
|
||||
// Set the initial viewport by providing a new AxisSpec with the
|
||||
// desired viewport, in NumericExtents.
|
||||
viewport: new charts.NumericExtents(3.0, 7.0)),
|
||||
// Optionally add a pan or pan and zoom behavior.
|
||||
// If pan/zoom is not added, the viewport specified remains the viewport.
|
||||
behaviors: [new charts.PanAndZoomBehavior()],
|
||||
);
|
||||
}
|
||||
|
||||
/// 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),
|
||||
new LinearSales(4, 55),
|
||||
new LinearSales(5, 66),
|
||||
new LinearSales(6, 110),
|
||||
new LinearSales(7, 70),
|
||||
new LinearSales(8, 20),
|
||||
new LinearSales(9, 25),
|
||||
new LinearSales(10, 45),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<LinearSales, int>(
|
||||
id: 'Sales',
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.sales,
|
||||
data: data,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
final int year;
|
||||
final int sales;
|
||||
|
||||
LinearSales(this.year, this.sales);
|
||||
}
|
||||
145
example/lib/axes/ordinal_initial_viewport.dart
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of setting an initial viewport for ordinal axis.
|
||||
///
|
||||
/// This allows for specifying the specific range of data to show that differs
|
||||
/// from what was provided in the series list.
|
||||
///
|
||||
/// In this example, the series list has ordinal data from year 2014 to 2030,
|
||||
/// but we want to show starting at 2018 and we only want to show 4 values.
|
||||
/// We can do this by specifying an [OrdinalViewport] in [OrdinalAxisSpec].
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class OrdinalInitialViewport extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
OrdinalInitialViewport(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory OrdinalInitialViewport.withSampleData() {
|
||||
return new OrdinalInitialViewport(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory OrdinalInitialViewport.withRandomData() {
|
||||
return new OrdinalInitialViewport(_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,
|
||||
// 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)),
|
||||
// Optionally add a pan or pan and zoom behavior.
|
||||
// If pan/zoom is not added, the viewport specified remains the viewport.
|
||||
behaviors: [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);
|
||||
}
|
||||
115
example/lib/axes/short_tick_length_axis.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Custom Tick Style Example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of using a custom primary measure axis replacing the default
|
||||
/// gridline rendering with a short tick rendering. It also turns on the axis
|
||||
/// line so that the ticks have something to line up against.
|
||||
///
|
||||
/// There are many axis styling options in the SmallTickRenderer allowing you
|
||||
/// to customize the font, tick lengths, and offsets.
|
||||
class ShortTickLengthAxis extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
ShortTickLengthAxis(this.seriesList, {this.animate = false});
|
||||
|
||||
factory ShortTickLengthAxis.withSampleData() {
|
||||
return new ShortTickLengthAxis(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory ShortTickLengthAxis.withRandomData() {
|
||||
return new ShortTickLengthAxis(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Customize the primary measure axis using a small tick renderer.
|
||||
/// Note: use String instead of num for ordinal domain axis
|
||||
/// (typically bar charts).
|
||||
primaryMeasureAxis: new charts.NumericAxisSpec(
|
||||
renderSpec: new charts.SmallTickRendererSpec(
|
||||
// Tick and Label styling here.
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with single series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
134
example/lib/axes/statically_provided_ticks.dart
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of axis using statically provided ticks.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of specifying a custom set of ticks to be used on the domain axis.
|
||||
///
|
||||
/// Specifying custom set of ticks allows specifying exactly what ticks are
|
||||
/// used in the axis. Each tick is also allowed to have a different style set.
|
||||
///
|
||||
/// For an ordinal axis, the [StaticOrdinalTickProviderSpec] is shown in this
|
||||
/// example defining ticks to be used with [TickSpec] of String.
|
||||
///
|
||||
/// For numeric axis, the [StaticNumericTickProviderSpec] can be used by passing
|
||||
/// in a list of ticks defined with [TickSpec] of num.
|
||||
///
|
||||
/// For datetime axis, the [StaticDateTimeTickProviderSpec] can be used by
|
||||
/// passing in a list of ticks defined with [TickSpec] of datetime.
|
||||
class StaticallyProvidedTicks extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
StaticallyProvidedTicks(this.seriesList, {this.animate = false});
|
||||
|
||||
factory StaticallyProvidedTicks.withSampleData() {
|
||||
return new StaticallyProvidedTicks(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory StaticallyProvidedTicks.withRandomData() {
|
||||
return new StaticallyProvidedTicks(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2015', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2016', random.nextInt(100) * 100),
|
||||
new OrdinalSales('2017', random.nextInt(100) * 100),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Create the ticks to be used the domain axis.
|
||||
final staticTicks = <charts.TickSpec<String>>[
|
||||
new charts.TickSpec(
|
||||
// Value must match the domain value.
|
||||
'2014',
|
||||
// Optional label for this tick, defaults to domain value if not set.
|
||||
label: 'Year 2014',
|
||||
// The styling for this tick.
|
||||
style: new charts.TextStyleSpec(
|
||||
color: new charts.Color(r: 0x4C, g: 0xAF, b: 0x50))),
|
||||
// If no text style is specified - the style from renderSpec will be used
|
||||
// if one is specified.
|
||||
new charts.TickSpec('2015'),
|
||||
new charts.TickSpec('2016'),
|
||||
new charts.TickSpec('2017'),
|
||||
];
|
||||
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
domainAxis: new charts.OrdinalAxisSpec(
|
||||
tickProviderSpec:
|
||||
new charts.StaticOrdinalTickProviderSpec(staticTicks)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with single series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 25000),
|
||||
new OrdinalSales('2016', 100000),
|
||||
new OrdinalSales('2017', 750000),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
164
example/lib/bar_chart/bar_gallery.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.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../gallery_scaffold.dart';
|
||||
import 'custom_rounded_bars.dart';
|
||||
import 'grouped.dart';
|
||||
import 'grouped_fill_color.dart';
|
||||
import 'grouped_single_target_line.dart';
|
||||
import 'grouped_stacked.dart';
|
||||
import 'grouped_stacked_weight_pattern.dart';
|
||||
import 'grouped_target_line.dart';
|
||||
import 'horizontal.dart';
|
||||
import 'horizontal_bar_label.dart';
|
||||
import 'horizontal_bar_label_custom.dart';
|
||||
import 'horizontal_pattern_forward_hatch.dart';
|
||||
import 'pattern_forward_hatch.dart';
|
||||
import 'simple.dart';
|
||||
import 'stacked.dart';
|
||||
import 'stacked_fill_color.dart';
|
||||
import 'stacked_horizontal.dart';
|
||||
import 'stacked_target_line.dart';
|
||||
import 'spark_bar.dart';
|
||||
import 'vertical_bar_label.dart';
|
||||
|
||||
List<GalleryScaffold> buildGallery() {
|
||||
return [
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Simple Bar Chart',
|
||||
subtitle: 'Simple bar chart with a single series',
|
||||
childBuilder: () => new SimpleBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Stacked Bar Chart',
|
||||
subtitle: 'Stacked bar chart with multiple series',
|
||||
childBuilder: () => new StackedBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Grouped Bar Chart',
|
||||
subtitle: 'Grouped bar chart with multiple series',
|
||||
childBuilder: () => new GroupedBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Grouped Stacked Bar Chart',
|
||||
subtitle: 'Grouped and stacked bar chart with multiple series',
|
||||
childBuilder: () => new GroupedStackedBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Grouped Bar Target Line Chart',
|
||||
subtitle: 'Grouped bar target line chart with multiple series',
|
||||
childBuilder: () => new GroupedBarTargetLineChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Grouped Bar Single Target Line Chart',
|
||||
subtitle:
|
||||
'Grouped bar target line chart with multiple series and a single target',
|
||||
childBuilder: () => new GroupedBarSingleTargetLineChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Stacked Bar Target Line Chart',
|
||||
subtitle: 'Stacked bar target line chart with multiple series',
|
||||
childBuilder: () => new StackedBarTargetLineChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Horizontal Bar Chart',
|
||||
subtitle: 'Horizontal bar chart with a single series',
|
||||
childBuilder: () => new HorizontalBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Stacked Horizontal Bar Chart',
|
||||
subtitle: 'Stacked horizontal bar chart with multiple series',
|
||||
childBuilder: () => new StackedHorizontalBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Horizontal Bar Chart with Bar Labels',
|
||||
subtitle: 'Horizontal bar chart with a single series and bar labels',
|
||||
childBuilder: () => new HorizontalBarLabelChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Horizontal Bar Chart with Custom Bar Labels',
|
||||
subtitle: 'Bar labels with customized styling',
|
||||
childBuilder: () => new HorizontalBarLabelCustomChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Vertical Bar Chart with Bar Labels',
|
||||
subtitle: 'Vertical bar chart with a single series and bar labels',
|
||||
childBuilder: () => new VerticalBarLabelChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Spark Bar Chart',
|
||||
subtitle: 'Spark Bar Chart',
|
||||
childBuilder: () => new SparkBar.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Grouped Fill Color Bar Chart',
|
||||
subtitle: 'Grouped bar chart with fill colors',
|
||||
childBuilder: () => new GroupedFillColorBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Stacked Fill Color Bar Chart',
|
||||
subtitle: 'Stacked bar chart with fill colors',
|
||||
childBuilder: () => new StackedFillColorBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Pattern Forward Hatch Bar Chart',
|
||||
subtitle: 'Pattern Forward Hatch Bar Chart',
|
||||
childBuilder: () => new PatternForwardHatchBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Transform.rotate(
|
||||
angle: 1.5708, child: new Icon(Icons.insert_chart)),
|
||||
title: 'Horizontal Pattern Forward Hatch Bar Chart',
|
||||
subtitle: 'Horizontal Pattern Forward Hatch Bar Chart',
|
||||
childBuilder: () =>
|
||||
new HorizontalPatternForwardHatchBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Weight Pattern Bar Chart',
|
||||
subtitle: 'Grouped and stacked bar chart with a weight pattern',
|
||||
childBuilder: () =>
|
||||
new GroupedStackedWeightPatternBarChart.withRandomData(),
|
||||
),
|
||||
new GalleryScaffold(
|
||||
listTileIcon: new Icon(Icons.insert_chart),
|
||||
title: 'Bar Chart with custom bar radius',
|
||||
subtitle: 'Custom rounded bar corners',
|
||||
childBuilder: () => new CustomRoundedBars.withRandomData(),
|
||||
),
|
||||
];
|
||||
}
|
||||
110
example/lib/bar_chart/custom_rounded_bars.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.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomRoundedBars extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
CustomRoundedBars(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with custom rounded bars.
|
||||
factory CustomRoundedBars.withSampleData() {
|
||||
return new CustomRoundedBars(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory CustomRoundedBars.withRandomData() {
|
||||
return new CustomRoundedBars(_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,
|
||||
defaultRenderer: new charts.BarRendererConfig(
|
||||
// By default, bar renderer will draw rounded bars with a constant
|
||||
// radius of 30.
|
||||
// To not have any rounded corners, use [NoCornerStrategy]
|
||||
// To change the radius of the bars, use [ConstCornerStrategy]
|
||||
cornerStrategy: const charts.ConstCornerStrategy(30)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create one series with sample hard coded data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final data = [
|
||||
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);
|
||||
}
|
||||
154
example/lib/bar_chart/grouped.dart
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GroupedBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory GroupedBarChart.withSampleData() {
|
||||
return new GroupedBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GroupedBarChart.withRandomData() {
|
||||
return new GroupedBarChart(_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.grouped,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
178
example/lib/bar_chart/grouped_fill_color.dart
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of a grouped bar chart with three series, each rendered with
|
||||
/// different fill colors.
|
||||
class GroupedFillColorBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedFillColorBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory GroupedFillColorBarChart.withSampleData() {
|
||||
return new GroupedFillColorBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GroupedFillColorBarChart.withRandomData() {
|
||||
return new GroupedFillColorBarChart(_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 [
|
||||
// Blue bars with a lighter center color.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
fillColorFn: (_, __) =>
|
||||
charts.MaterialPalette.blue.shadeDefault.lighter,
|
||||
),
|
||||
// Solid red bars. Fill color will default to the series color if no
|
||||
// fillColorFn is configured.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
),
|
||||
// Hollow green bars.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
|
||||
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
// Configure a stroke width to enable borders on the bars.
|
||||
defaultRenderer: new charts.BarRendererConfig(
|
||||
groupingType: charts.BarGroupingType.grouped, strokeWidthPx: 2.0),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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', 50),
|
||||
new OrdinalSales('2016', 50),
|
||||
new OrdinalSales('2017', 45),
|
||||
];
|
||||
|
||||
return [
|
||||
// Blue bars with a lighter center color.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
fillColorFn: (_, __) =>
|
||||
charts.MaterialPalette.blue.shadeDefault.lighter,
|
||||
),
|
||||
// Solid red bars. Fill color will default to the series color if no
|
||||
// fillColorFn is configured.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet',
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
),
|
||||
// Hollow green bars.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
|
||||
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
180
example/lib/bar_chart/grouped_single_target_line.dart
Normal file
@@ -0,0 +1,180 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GroupedBarSingleTargetLineChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedBarSingleTargetLineChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory GroupedBarSingleTargetLineChart.withSampleData() {
|
||||
return new GroupedBarSingleTargetLineChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GroupedBarSingleTargetLineChart.withRandomData() {
|
||||
return new GroupedBarSingleTargetLineChart(_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)),
|
||||
];
|
||||
|
||||
final targetLineData = [
|
||||
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),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: targetLineData)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(seriesList,
|
||||
animate: animate,
|
||||
barGroupingType: charts.BarGroupingType.grouped,
|
||||
customSeriesRenderers: [
|
||||
new charts.BarTargetLineRendererConfig(
|
||||
// ID used to link series to this renderer.
|
||||
customRendererId: 'customTargetLine',
|
||||
groupingType: charts.BarGroupingType.grouped)
|
||||
]);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final desktopSalesData = [
|
||||
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),
|
||||
];
|
||||
|
||||
final targetLineData = [
|
||||
new OrdinalSales('2014', 30),
|
||||
new OrdinalSales('2015', 55),
|
||||
new OrdinalSales('2016', 15),
|
||||
new OrdinalSales('2017', 25),
|
||||
];
|
||||
|
||||
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),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: targetLineData)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
244
example/lib/bar_chart/grouped_stacked.dart
Normal file
@@ -0,0 +1,244 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of a bar chart with grouped, stacked series oriented vertically.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GroupedStackedBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedStackedBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory GroupedStackedBarChart.withSampleData() {
|
||||
return new GroupedStackedBarChart(
|
||||
createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GroupedStackedBarChart.withRandomData() {
|
||||
return new GroupedStackedBarChart(_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,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
256
example/lib/bar_chart/grouped_stacked_weight_pattern.dart
Normal file
@@ -0,0 +1,256 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Example of a bar chart with grouped, stacked series oriented vertically with
|
||||
/// a custom weight pattern.
|
||||
///
|
||||
/// This is a pattern of weights used to calculate the width of bars within a
|
||||
/// bar group. If not specified, each bar in the group will have an equal width.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GroupedStackedWeightPatternBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedStackedWeightPatternBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory GroupedStackedWeightPatternBarChart.withSampleData() {
|
||||
return new GroupedStackedWeightPatternBarChart(
|
||||
createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GroupedStackedWeightPatternBarChart.withRandomData() {
|
||||
return new GroupedStackedWeightPatternBarChart(_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,
|
||||
// Configure the bar renderer in grouped stacked rendering mode with a
|
||||
// custom weight pattern.
|
||||
//
|
||||
// The first stack of bars in each group is configured to be twice as wide
|
||||
// as the second stack of bars in each group.
|
||||
defaultRenderer: new charts.BarRendererConfig(
|
||||
groupingType: charts.BarGroupingType.groupedStacked,
|
||||
weightPattern: [2, 1],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
248
example/lib/bar_chart/grouped_target_line.dart
Normal file
@@ -0,0 +1,248 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GroupedBarTargetLineChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedBarTargetLineChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory GroupedBarTargetLineChart.withSampleData() {
|
||||
return new GroupedBarTargetLineChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory GroupedBarTargetLineChart.withRandomData() {
|
||||
return new GroupedBarTargetLineChart(_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)),
|
||||
];
|
||||
|
||||
final desktopTargetLineData = [
|
||||
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 tableTargetLineData = [
|
||||
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 mobileTargetLineData = [
|
||||
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,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(seriesList,
|
||||
animate: animate,
|
||||
barGroupingType: charts.BarGroupingType.grouped,
|
||||
customSeriesRenderers: [
|
||||
new charts.BarTargetLineRendererConfig<String>(
|
||||
// ID used to link series to this renderer.
|
||||
customRendererId: 'customTargetLine',
|
||||
groupingType: charts.BarGroupingType.grouped)
|
||||
]);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final desktopSalesData = [
|
||||
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),
|
||||
];
|
||||
|
||||
final desktopTargetLineData = [
|
||||
new OrdinalSales('2014', 4),
|
||||
new OrdinalSales('2015', 20),
|
||||
new OrdinalSales('2016', 80),
|
||||
new OrdinalSales('2017', 65),
|
||||
];
|
||||
|
||||
final tableTargetLineData = [
|
||||
new OrdinalSales('2014', 30),
|
||||
new OrdinalSales('2015', 55),
|
||||
new OrdinalSales('2016', 15),
|
||||
new OrdinalSales('2017', 25),
|
||||
];
|
||||
|
||||
final mobileTargetLineData = [
|
||||
new OrdinalSales('2014', 10),
|
||||
new OrdinalSales('2015', 5),
|
||||
new OrdinalSales('2016', 45),
|
||||
new OrdinalSales('2017', 35),
|
||||
];
|
||||
|
||||
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,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
104
example/lib/bar_chart/horizontal.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Horizontal bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HorizontalBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
HorizontalBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory HorizontalBarChart.withSampleData() {
|
||||
return new HorizontalBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory HorizontalBarChart.withRandomData() {
|
||||
return new HorizontalBarChart(_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) {
|
||||
// For horizontal bar charts, set the [vertical] flag to false.
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
vertical: false,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
123
example/lib/bar_chart/horizontal_bar_label.dart
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Horizontal bar chart with bar label renderer example and hidden domain axis.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HorizontalBarLabelChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
HorizontalBarLabelChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory HorizontalBarLabelChart.withSampleData() {
|
||||
return new HorizontalBarLabelChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory HorizontalBarLabelChart.withRandomData() {
|
||||
return new HorizontalBarLabelChart(_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,
|
||||
// Set a label accessor to control the text of the bar label.
|
||||
labelAccessorFn: (OrdinalSales sales, _) =>
|
||||
'${sales.year}: \$${sales.sales.toString()}')
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
// [BarLabelDecorator] will automatically position the label
|
||||
// inside the bar if the label will fit. If the label will not fit and the
|
||||
// area outside of the bar is larger than the bar, it will draw outside of the
|
||||
// bar. Labels can always display inside or outside using [LabelPosition].
|
||||
//
|
||||
// Text style for inside / outside can be controlled independently by setting
|
||||
// [insideLabelStyleSpec] and [outsideLabelStyleSpec].
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
vertical: false,
|
||||
// Set a bar label decorator.
|
||||
// Example configuring different styles for inside/outside:
|
||||
// barRendererDecorator: new charts.BarLabelDecorator(
|
||||
// insideLabelStyleSpec: new charts.TextStyleSpec(...),
|
||||
// outsideLabelStyleSpec: new charts.TextStyleSpec(...)),
|
||||
barRendererDecorator: new charts.BarLabelDecorator<String>(),
|
||||
// Hide domain axis.
|
||||
domainAxis:
|
||||
new charts.OrdinalAxisSpec(renderSpec: new charts.NoneRenderSpec()),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
// Set a label accessor to control the text of the bar label.
|
||||
labelAccessorFn: (OrdinalSales sales, _) =>
|
||||
'${sales.year}: \$${sales.sales.toString()}')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
140
example/lib/bar_chart/horizontal_bar_label_custom.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Horizontal bar chart with custom style for each datum in the bar label.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HorizontalBarLabelCustomChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
HorizontalBarLabelCustomChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
static HorizontalBarLabelCustomChart createWithSampleData() {
|
||||
return new HorizontalBarLabelCustomChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory HorizontalBarLabelCustomChart.withRandomData() {
|
||||
return new HorizontalBarLabelCustomChart(_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,
|
||||
// Set a label accessor to control the text of the bar label.
|
||||
labelAccessorFn: (OrdinalSales sales, _) =>
|
||||
'${sales.year}: \$${sales.sales.toString()}',
|
||||
insideLabelStyleAccessorFn: (OrdinalSales sales, _) {
|
||||
final color = (sales.year == '2014')
|
||||
? charts.MaterialPalette.red.shadeDefault
|
||||
: charts.MaterialPalette.yellow.shadeDefault.darker;
|
||||
return new charts.TextStyleSpec(color: color);
|
||||
},
|
||||
outsideLabelStyleAccessorFn: (OrdinalSales sales, _) {
|
||||
final color = (sales.year == '2014')
|
||||
? charts.MaterialPalette.red.shadeDefault
|
||||
: charts.MaterialPalette.yellow.shadeDefault.darker;
|
||||
return new charts.TextStyleSpec(color: color);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
// The [BarLabelDecorator] has settings to set the text style for all labels
|
||||
// for inside the bar and outside the bar. To be able to control each datum's
|
||||
// style, set the style accessor functions on the series.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
vertical: false,
|
||||
barRendererDecorator: new charts.BarLabelDecorator<String>(),
|
||||
// Hide domain axis.
|
||||
domainAxis:
|
||||
new charts.OrdinalAxisSpec(renderSpec: new charts.NoneRenderSpec()),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
// Set a label accessor to control the text of the bar label.
|
||||
labelAccessorFn: (OrdinalSales sales, _) =>
|
||||
'${sales.year}: \$${sales.sales.toString()}',
|
||||
insideLabelStyleAccessorFn: (OrdinalSales sales, _) {
|
||||
final color = (sales.year == '2014')
|
||||
? charts.MaterialPalette.red.shadeDefault
|
||||
: charts.MaterialPalette.yellow.shadeDefault.darker;
|
||||
return new charts.TextStyleSpec(color: color);
|
||||
},
|
||||
outsideLabelStyleAccessorFn: (OrdinalSales sales, _) {
|
||||
final color = (sales.year == '2014')
|
||||
? charts.MaterialPalette.red.shadeDefault
|
||||
: charts.MaterialPalette.yellow.shadeDefault.darker;
|
||||
return new charts.TextStyleSpec(color: color);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
164
example/lib/bar_chart/horizontal_pattern_forward_hatch.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.
|
||||
|
||||
/// Forward pattern hatch bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Forward hatch pattern horizontal bar chart example.
|
||||
///
|
||||
/// The second series of bars is rendered with a pattern by defining a
|
||||
/// fillPatternFn mapping function.
|
||||
class HorizontalPatternForwardHatchBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
HorizontalPatternForwardHatchBarChart(this.seriesList,
|
||||
{this.animate = false});
|
||||
|
||||
factory HorizontalPatternForwardHatchBarChart.withSampleData() {
|
||||
return new HorizontalPatternForwardHatchBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory HorizontalPatternForwardHatchBarChart.withRandomData() {
|
||||
return new HorizontalPatternForwardHatchBarChart(_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,
|
||||
fillPatternFn: (OrdinalSales sales, _) =>
|
||||
charts.FillPatternType.forwardHatch,
|
||||
),
|
||||
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.grouped,
|
||||
vertical: false,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
fillPatternFn: (OrdinalSales sales, _) =>
|
||||
charts.FillPatternType.forwardHatch,
|
||||
),
|
||||
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);
|
||||
}
|
||||
161
example/lib/bar_chart/pattern_forward_hatch.dart
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Forward hatch pattern bar chart example.
|
||||
///
|
||||
/// The second series of bars is rendered with a pattern by defining a
|
||||
/// fillPatternFn mapping function.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PatternForwardHatchBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PatternForwardHatchBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory PatternForwardHatchBarChart.withSampleData() {
|
||||
return new PatternForwardHatchBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory PatternForwardHatchBarChart.withRandomData() {
|
||||
return new PatternForwardHatchBarChart(_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,
|
||||
fillPatternFn: (OrdinalSales sales, _) =>
|
||||
charts.FillPatternType.forwardHatch,
|
||||
),
|
||||
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.grouped,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
fillPatternFn: (OrdinalSales sales, _) =>
|
||||
charts.FillPatternType.forwardHatch,
|
||||
),
|
||||
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);
|
||||
}
|
||||
104
example/lib/bar_chart/simple.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SimpleBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SimpleBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory SimpleBarChart.withSampleData() {
|
||||
return new SimpleBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory SimpleBarChart.withRandomData() {
|
||||
return new SimpleBarChart(_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,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
140
example/lib/bar_chart/spark_bar.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Spark Bar Example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of a Spark Bar by hiding both axis, reducing the chart margins.
|
||||
class SparkBar extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SparkBar(this.seriesList, {this.animate = false});
|
||||
|
||||
factory SparkBar.withSampleData() {
|
||||
return new SparkBar(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory SparkBar.withRandomData() {
|
||||
return new SparkBar(_createRandomData());
|
||||
}
|
||||
|
||||
/// Create random data.
|
||||
static List<charts.Series<OrdinalSales, String>> _createRandomData() {
|
||||
final random = new Random();
|
||||
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2007', random.nextInt(100)),
|
||||
new OrdinalSales('2008', random.nextInt(100)),
|
||||
new OrdinalSales('2009', random.nextInt(100)),
|
||||
new OrdinalSales('2010', random.nextInt(100)),
|
||||
new OrdinalSales('2011', random.nextInt(100)),
|
||||
new OrdinalSales('2012', random.nextInt(100)),
|
||||
new OrdinalSales('2013', 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: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
|
||||
/// Assign a custom style for the measure axis.
|
||||
///
|
||||
/// The NoneRenderSpec only draws an axis line (and even that can be hidden
|
||||
/// with showAxisLine=false).
|
||||
primaryMeasureAxis:
|
||||
new charts.NumericAxisSpec(renderSpec: new charts.NoneRenderSpec()),
|
||||
|
||||
/// This is an OrdinalAxisSpec to match up with BarChart's default
|
||||
/// ordinal domain axis (use NumericAxisSpec or DateTimeAxisSpec for
|
||||
/// other charts).
|
||||
domainAxis: new charts.OrdinalAxisSpec(
|
||||
// Make sure that we draw the domain axis line.
|
||||
showAxisLine: true,
|
||||
// But don't draw anything else.
|
||||
renderSpec: new charts.NoneRenderSpec()),
|
||||
|
||||
// With a spark chart we likely don't want large chart margins.
|
||||
// 1px is the smallest we can make each margin.
|
||||
layoutConfig: new charts.LayoutConfig(
|
||||
leftMarginSpec: new charts.MarginSpec.fixedPixel(0),
|
||||
topMarginSpec: new charts.MarginSpec.fixedPixel(0),
|
||||
rightMarginSpec: new charts.MarginSpec.fixedPixel(0),
|
||||
bottomMarginSpec: new charts.MarginSpec.fixedPixel(0)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with single series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final globalSalesData = [
|
||||
new OrdinalSales('2007', 3100),
|
||||
new OrdinalSales('2008', 3500),
|
||||
new OrdinalSales('2009', 5000),
|
||||
new OrdinalSales('2010', 2500),
|
||||
new OrdinalSales('2011', 3200),
|
||||
new OrdinalSales('2012', 4500),
|
||||
new OrdinalSales('2013', 4400),
|
||||
new OrdinalSales('2014', 5000),
|
||||
new OrdinalSales('2015', 5000),
|
||||
new OrdinalSales('2016', 4500),
|
||||
new OrdinalSales('2017', 4300),
|
||||
];
|
||||
|
||||
return [
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Global Revenue',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: globalSalesData,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
155
example/lib/bar_chart/stacked.dart
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class StackedBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
StackedBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a stacked [BarChart] with sample data and no transition.
|
||||
factory StackedBarChart.withSampleData() {
|
||||
return new StackedBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory StackedBarChart.withRandomData() {
|
||||
return new StackedBarChart(_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,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
178
example/lib/bar_chart/stacked_fill_color.dart
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
/// Example of a stacked bar chart with three series, each rendered with
|
||||
/// different fill colors.
|
||||
class StackedFillColorBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
StackedFillColorBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
factory StackedFillColorBarChart.withSampleData() {
|
||||
return new StackedFillColorBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory StackedFillColorBarChart.withRandomData() {
|
||||
return new StackedFillColorBarChart(_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 [
|
||||
// Blue bars with a lighter center color.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
fillColorFn: (_, __) =>
|
||||
charts.MaterialPalette.blue.shadeDefault.lighter,
|
||||
),
|
||||
// Solid red bars. Fill color will default to the series color if no
|
||||
// fillColorFn is configured.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
),
|
||||
// Hollow green bars.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
|
||||
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
|
||||
),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
// Configure a stroke width to enable borders on the bars.
|
||||
defaultRenderer: new charts.BarRendererConfig(
|
||||
groupingType: charts.BarGroupingType.stacked, strokeWidthPx: 2.0),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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', 50),
|
||||
new OrdinalSales('2016', 50),
|
||||
new OrdinalSales('2017', 45),
|
||||
];
|
||||
|
||||
return [
|
||||
// Blue bars with a lighter center color.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
fillColorFn: (_, __) =>
|
||||
charts.MaterialPalette.blue.shadeDefault.lighter,
|
||||
),
|
||||
// Solid red bars. Fill color will default to the series color if no
|
||||
// fillColorFn is configured.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet',
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
),
|
||||
// Hollow green bars.
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileSalesData,
|
||||
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
|
||||
fillColorFn: (_, __) => charts.MaterialPalette.transparent,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
157
example/lib/bar_chart/stacked_horizontal.dart
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class StackedHorizontalBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
StackedHorizontalBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a stacked [BarChart] with sample data and no transition.
|
||||
factory StackedHorizontalBarChart.withSampleData() {
|
||||
return new StackedHorizontalBarChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory StackedHorizontalBarChart.withRandomData() {
|
||||
return new StackedHorizontalBarChart(_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) {
|
||||
// For horizontal bar charts, set the [vertical] flag to false.
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
barGroupingType: charts.BarGroupingType.stacked,
|
||||
vertical: false,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final desktopSalesData = [
|
||||
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);
|
||||
}
|
||||
249
example/lib/bar_chart/stacked_target_line.dart
Normal file
@@ -0,0 +1,249 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bar chart example
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class StackedBarTargetLineChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
StackedBarTargetLineChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a stacked [BarChart] with sample data and no transition.
|
||||
factory StackedBarTargetLineChart.withSampleData() {
|
||||
return new StackedBarTargetLineChart(
|
||||
_createSampleData(),
|
||||
// Disable animations for image tests.
|
||||
animate: false,
|
||||
);
|
||||
}
|
||||
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
// This section is excluded from being copied to the gallery.
|
||||
// It is used for creating random series data to demonstrate animation in
|
||||
// the example app only.
|
||||
factory StackedBarTargetLineChart.withRandomData() {
|
||||
return new StackedBarTargetLineChart(_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)),
|
||||
];
|
||||
|
||||
final desktopTargetLineData = [
|
||||
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 tableTargetLineData = [
|
||||
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 mobileTargetLineData = [
|
||||
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,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(seriesList,
|
||||
animate: animate,
|
||||
barGroupingType: charts.BarGroupingType.stacked,
|
||||
customSeriesRenderers: [
|
||||
new charts.BarTargetLineRendererConfig<String>(
|
||||
// ID used to link series to this renderer.
|
||||
customRendererId: 'customTargetLine',
|
||||
groupingType: charts.BarGroupingType.stacked)
|
||||
]);
|
||||
}
|
||||
|
||||
/// Create series list with multiple series
|
||||
static List<charts.Series<OrdinalSales, String>> _createSampleData() {
|
||||
final desktopSalesData = [
|
||||
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),
|
||||
];
|
||||
|
||||
final desktopTargetLineData = [
|
||||
new OrdinalSales('2014', 4),
|
||||
new OrdinalSales('2015', 20),
|
||||
new OrdinalSales('2016', 80),
|
||||
new OrdinalSales('2017', 65),
|
||||
];
|
||||
|
||||
final tableTargetLineData = [
|
||||
new OrdinalSales('2014', 30),
|
||||
new OrdinalSales('2015', 55),
|
||||
new OrdinalSales('2016', 15),
|
||||
new OrdinalSales('2017', 25),
|
||||
];
|
||||
|
||||
final mobileTargetLineData = [
|
||||
new OrdinalSales('2014', 10),
|
||||
new OrdinalSales('2015', 5),
|
||||
new OrdinalSales('2016', 45),
|
||||
new OrdinalSales('2017', 35),
|
||||
];
|
||||
|
||||
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,
|
||||
),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Desktop Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: desktopTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Tablet Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: tableTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
new charts.Series<OrdinalSales, String>(
|
||||
id: 'Mobile Target Line',
|
||||
domainFn: (OrdinalSales sales, _) => sales.year,
|
||||
measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
data: mobileTargetLineData,
|
||||
)
|
||||
// Configure our custom bar target renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customTargetLine'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
120
example/lib/bar_chart/vertical_bar_label.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.
|
||||
|
||||
/// Vertical bar chart with bar label renderer example.
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_START
|
||||
import 'dart:math';
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class VerticalBarLabelChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
VerticalBarLabelChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// Creates a [BarChart] with sample data and no transition.
|
||||
factory VerticalBarLabelChart.withSampleData() {
|
||||
return new VerticalBarLabelChart(
|
||||
_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 VerticalBarLabelChart.withRandomData() {
|
||||
return new VerticalBarLabelChart(_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,
|
||||
// Set a label accessor to control the text of the bar label.
|
||||
labelAccessorFn: (OrdinalSales sales, _) =>
|
||||
'${sales.sales.toString()}')
|
||||
];
|
||||
}
|
||||
// EXCLUDE_FROM_GALLERY_DOCS_END
|
||||
|
||||
// [BarLabelDecorator] will automatically position the label
|
||||
// inside the bar if the label will fit. If the label will not fit,
|
||||
// it will draw outside of the bar.
|
||||
// Labels can always display inside or outside using [LabelPosition].
|
||||
//
|
||||
// Text style for inside / outside can be controlled independently by setting
|
||||
// [insideLabelStyleSpec] and [outsideLabelStyleSpec].
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new charts.BarChart(
|
||||
seriesList,
|
||||
animate: animate,
|
||||
// Set a bar label decorator.
|
||||
// Example configuring different styles for inside/outside:
|
||||
// barRendererDecorator: new charts.BarLabelDecorator(
|
||||
// insideLabelStyleSpec: new charts.TextStyleSpec(...),
|
||||
// outsideLabelStyleSpec: new charts.TextStyleSpec(...)),
|
||||
barRendererDecorator: new charts.BarLabelDecorator<String>(),
|
||||
domainAxis: new charts.OrdinalAxisSpec(),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
// Set a label accessor to control the text of the bar label.
|
||||
labelAccessorFn: (OrdinalSales sales, _) =>
|
||||
'\$${sales.sales.toString()}')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
126
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/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
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/material.dart';
|
||||
|
||||
/// This is a line chart with a title text in every margin.
|
||||
///
|
||||
/// A series of [ChartTitle] behaviors are used to render titles, one per
|
||||
/// margin.
|
||||
class ChartTitleLine extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, num>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
ChartTitleLine(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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
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/material.dart';
|
||||
|
||||
class InitialHintAnimation extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
InitialHintAnimation(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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
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/material.dart';
|
||||
|
||||
class InitialSelection extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
InitialSelection(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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
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/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PercentOfDomainBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PercentOfDomainBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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);
|
||||
}
|
||||
261
example/lib/behaviors/percent_of_domain_by_category.dart
Normal file
@@ -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/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PercentOfDomainByCategoryBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PercentOfDomainByCategoryBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
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
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/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class PercentOfSeriesBarChart extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PercentOfSeriesBarChart(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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
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/material.dart';
|
||||
|
||||
class SelectionBarHighlight extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, String>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionBarHighlight(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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
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/material.dart';
|
||||
|
||||
class SelectionCallbackExample extends StatefulWidget {
|
||||
final List<charts.Series<dynamic, DateTime>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionCallbackExample(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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
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/material.dart';
|
||||
|
||||
class SelectionLineHighlight extends StatelessWidget {
|
||||
final List<charts.Series<dynamic, num>> seriesList;
|
||||
final bool animate;
|
||||
|
||||
SelectionLineHighlight(this.seriesList, {this.animate = false});
|
||||
|
||||
/// 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);
|
||||
}
|
||||