├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── main.dart │ └── pages │ │ ├── bar_page.dart │ │ ├── candle_page.dart │ │ ├── group_bar_page.dart │ │ ├── line_page.dart │ │ └── pie_page.dart ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements ├── pubspec.lock ├── pubspec.yaml ├── test │ └── widget_test.dart └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json ├── lib ├── mrx_charts.dart └── src │ ├── chart.dart │ ├── models │ ├── animation │ │ ├── chart_animation.dart │ │ ├── chart_color_animation.dart │ │ ├── chart_double_animation.dart │ │ ├── chart_position_animation.dart │ │ ├── chart_size_animation.dart │ │ └── chart_text_style_animation.dart │ ├── axis │ │ ├── chart_axis_layer.dart │ │ ├── data │ │ │ ├── chart_axis_data.dart │ │ │ └── chart_axis_data_item.dart │ │ └── settings │ │ │ ├── chart_axis_settings.dart │ │ │ └── chart_axis_settings_axis.dart │ ├── bar │ │ ├── chart_bar_data_item.dart │ │ ├── chart_bar_layer.dart │ │ └── chart_bar_settings.dart │ ├── candle │ │ ├── chart_candle_data_item.dart │ │ ├── chart_candle_data_item_value.dart │ │ ├── chart_candle_layer.dart │ │ └── chart_candle_settings.dart │ ├── chart_axis_value.dart │ ├── chart_data_item.dart │ ├── chart_layer.dart │ ├── chart_painter_data.dart │ ├── grid │ │ ├── chart_grid_layer.dart │ │ ├── data │ │ │ ├── chart_grid_data.dart │ │ │ └── chart_grid_data_item.dart │ │ └── settings │ │ │ ├── chart_grid_settings.dart │ │ │ └── chart_grid_settings_axis.dart │ ├── group │ │ ├── bar │ │ │ ├── chart_group_bar_data_item.dart │ │ │ ├── chart_group_bar_layer.dart │ │ │ └── chart_group_bar_settings.dart │ │ └── pie │ │ │ ├── chart_group_pie_data_item.dart │ │ │ ├── chart_group_pie_layer.dart │ │ │ └── chart_group_pie_settings.dart │ ├── highlight │ │ ├── chart_highlight_layer.dart │ │ └── shape │ │ │ ├── chart_highlight_line_shape.dart │ │ │ └── chart_highlight_shape.dart │ ├── line │ │ ├── chart_line_data_item.dart │ │ ├── chart_line_layer.dart │ │ └── chart_line_settings.dart │ ├── tooltip │ │ ├── chart_tooltip_layer.dart │ │ └── shape │ │ │ ├── chart_tooltip_bar_shape.dart │ │ │ ├── chart_tooltip_line_shape.dart │ │ │ ├── chart_tooltip_pie_shape.dart │ │ │ └── chart_tooltip_shape.dart │ └── touchable │ │ ├── arc_shape.dart │ │ ├── rectangle_shape.dart │ │ └── touchable_shape.dart │ ├── painter │ ├── chart_axis_painter.dart │ ├── chart_bar_painter.dart │ ├── chart_candle_painter.dart │ ├── chart_grid_painter.dart │ ├── chart_group_bar_painter.dart │ ├── chart_group_pie_painter.dart │ ├── chart_highlight_painter.dart │ ├── chart_line_painter.dart │ ├── chart_painter.dart │ └── chart_tooltip_painter.dart │ └── touch │ ├── chart_touch_callback_data.dart │ └── chart_touch_detector.dart ├── pubspec.yaml └── screenshots ├── chart_bar.gif ├── chart_candle.gif ├── chart_group_bar.gif ├── chart_line.gif └── chart_pie.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 25 | /pubspec.lock 26 | **/doc/api/ 27 | .dart_tool/ 28 | .packages 29 | build/ 30 | 31 | #FVM 32 | .fvm/flutter_sdk/ 33 | .fvm/flutter_sdk 34 | .fvm/ 35 | 36 | # Android Studio will place build artifacts here 37 | /android/app/debug 38 | /android/app/profile 39 | /android/app/release -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 097d3313d8e2c7f901932d63e537c1acefb87800 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.3 2 | - Support Flutter 3.0 3 | 4 | ## 0.1.2 5 | - Add doc 6 | 7 | ## 0.1.1 8 | - Refactor path 9 | 10 | ## 0.1.0 11 | - Released project -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Merixstudio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Charts Flutter 2 | Simple and beautiful smooth animated charts. 3 | ## Supported charts 4 | ### Bar 5 | ![Screenshot1](https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/master/screenshots/chart_bar.gif) 6 | ### Group bar 7 | ![Screenshot2](https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/master/screenshots/chart_group_bar.gif) 8 | ### Candle 9 | ![Screenshot3](https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/master/screenshots/chart_candle.gif) 10 | ### Line 11 | ![Screenshot4](https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/master/screenshots/chart_line.gif) 12 | ### Pie 13 | ![Screenshot5](https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/master/screenshots/chart_pie.gif) 14 | ## Example 15 | Check `/example` folder for more detailed usage 16 | ```dart 17 | Chart( 18 | layers: [ 19 | ChartAxisLayer( 20 | settings: ChartAxisSettings( 21 | x: ChartAxisSettingsAxis( 22 | frequency: 1.0, 23 | max: 13.0, 24 | min: 7.0, 25 | textStyle: TextStyle( 26 | color: Colors.white.withOpacity(0.6), 27 | fontSize: 10.0, 28 | ), 29 | ), 30 | y: ChartAxisSettingsAxis( 31 | frequency: 100.0, 32 | max: 300.0, 33 | min: 0.0, 34 | textStyle: TextStyle( 35 | color: Colors.white.withOpacity(0.6), 36 | fontSize: 10.0, 37 | ), 38 | ), 39 | ), 40 | labelX: (value) => value.toInt().toString(), 41 | labelY: (value) => value.toInt().toString(), 42 | ), 43 | ChartBarLayer( 44 | items: List.generate( 45 | 13 - 7 + 1, 46 | (index) => ChartBarDataItem( 47 | color: const Color(0xFF8043F9), 48 | value: Random().nextInt(280) + 20, 49 | x: index.toDouble() + 7, 50 | ), 51 | ), 52 | settings: const ChartBarSettings( 53 | thickness: 8.0, 54 | radius: BorderRadius.all(Radius.circular(4.0)), 55 | ), 56 | ), 57 | ] 58 | ], 59 | ) 60 | ``` 61 | ## About 62 | Developed with passion, by [Merixstudio](https://www.merixstudio.com/development/flutter/) developers. 63 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 097d3313d8e2c7f901932d63e537c1acefb87800 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.example.example" 47 | minSdkVersion flutter.minSdkVersion 48 | targetSdkVersion flutter.targetSdkVersion 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/pages/bar_page.dart'; 2 | import 'package:example/pages/candle_page.dart'; 3 | import 'package:example/pages/group_bar_page.dart'; 4 | import 'package:example/pages/line_page.dart'; 5 | import 'package:example/pages/pie_page.dart'; 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Chart', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: const HomePage(), 24 | ); 25 | } 26 | } 27 | 28 | class HomePage extends StatelessWidget { 29 | const HomePage({ 30 | Key? key, 31 | }) : super(key: key); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Scaffold( 36 | body: Padding( 37 | padding: const EdgeInsets.all(24.0), 38 | child: Column( 39 | crossAxisAlignment: CrossAxisAlignment.stretch, 40 | mainAxisAlignment: MainAxisAlignment.center, 41 | children: [ 42 | ElevatedButton( 43 | onPressed: () => Navigator.of(context).push( 44 | MaterialPageRoute( 45 | builder: (_) => const BarPage(), 46 | ), 47 | ), 48 | style: ElevatedButton.styleFrom( 49 | primary: const Color(0xFF1B0E41), 50 | ), 51 | child: const Padding( 52 | padding: EdgeInsets.all(12.0), 53 | child: Text('Bar'), 54 | ), 55 | ), 56 | const SizedBox( 57 | height: 6.0, 58 | ), 59 | ElevatedButton( 60 | onPressed: () => Navigator.of(context).push( 61 | MaterialPageRoute( 62 | builder: (_) => const GroupBarPage(), 63 | ), 64 | ), 65 | style: ElevatedButton.styleFrom( 66 | primary: const Color(0xFF1B0E41), 67 | ), 68 | child: const Padding( 69 | padding: EdgeInsets.all(12.0), 70 | child: Text('Group bar'), 71 | ), 72 | ), 73 | const SizedBox( 74 | height: 6.0, 75 | ), 76 | ElevatedButton( 77 | onPressed: () => Navigator.of(context).push( 78 | MaterialPageRoute( 79 | builder: (_) => const CandlePage(), 80 | ), 81 | ), 82 | style: ElevatedButton.styleFrom( 83 | primary: const Color(0xFF1B0E41), 84 | ), 85 | child: const Padding( 86 | padding: EdgeInsets.all(12.0), 87 | child: Text('Candle'), 88 | ), 89 | ), 90 | const SizedBox( 91 | height: 6.0, 92 | ), 93 | ElevatedButton( 94 | onPressed: () => Navigator.of(context).push( 95 | MaterialPageRoute( 96 | builder: (_) => const LinePage(), 97 | ), 98 | ), 99 | style: ElevatedButton.styleFrom( 100 | primary: const Color(0xFF1B0E41), 101 | ), 102 | child: const Padding( 103 | padding: EdgeInsets.all(12.0), 104 | child: Text('Line'), 105 | ), 106 | ), 107 | const SizedBox( 108 | height: 6.0, 109 | ), 110 | ElevatedButton( 111 | onPressed: () => Navigator.of(context).push( 112 | MaterialPageRoute( 113 | builder: (_) => const PiePage(), 114 | ), 115 | ), 116 | style: ElevatedButton.styleFrom( 117 | primary: const Color(0xFF1B0E41), 118 | ), 119 | child: const Padding( 120 | padding: EdgeInsets.all(12.0), 121 | child: Text('Pie'), 122 | ), 123 | ), 124 | ], 125 | ), 126 | ), 127 | ); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /example/lib/pages/bar_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:mrx_charts/mrx_charts.dart'; 5 | 6 | class BarPage extends StatefulWidget { 7 | const BarPage({Key? key}) : super(key: key); 8 | 9 | @override 10 | State createState() => _BarPageState(); 11 | } 12 | 13 | class _BarPageState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | appBar: AppBar( 18 | actions: [ 19 | Padding( 20 | padding: const EdgeInsets.only( 21 | right: 20.0, 22 | ), 23 | child: GestureDetector( 24 | onTap: () => setState(() {}), 25 | child: const Icon( 26 | Icons.refresh, 27 | size: 26.0, 28 | ), 29 | ), 30 | ), 31 | ], 32 | backgroundColor: Colors.transparent, 33 | elevation: 0.0, 34 | title: const Text('Bar'), 35 | ), 36 | backgroundColor: const Color(0xFF1B0E41), 37 | body: Center( 38 | child: Container( 39 | constraints: const BoxConstraints( 40 | maxHeight: 400.0, 41 | maxWidth: 600.0, 42 | ), 43 | padding: const EdgeInsets.all(24.0), 44 | child: Chart( 45 | layers: layers(), 46 | padding: const EdgeInsets.symmetric(horizontal: 12.0).copyWith( 47 | bottom: 12.0, 48 | ), 49 | ), 50 | ), 51 | ), 52 | ); 53 | } 54 | 55 | List layers() { 56 | return [ 57 | ChartAxisLayer( 58 | settings: ChartAxisSettings( 59 | x: ChartAxisSettingsAxis( 60 | frequency: 1.0, 61 | max: 13.0, 62 | min: 7.0, 63 | textStyle: TextStyle( 64 | color: Colors.white.withOpacity(0.6), 65 | fontSize: 10.0, 66 | ), 67 | ), 68 | y: ChartAxisSettingsAxis( 69 | frequency: 100.0, 70 | max: 300.0, 71 | min: 0.0, 72 | textStyle: TextStyle( 73 | color: Colors.white.withOpacity(0.6), 74 | fontSize: 10.0, 75 | ), 76 | ), 77 | ), 78 | labelX: (value) => value.toInt().toString(), 79 | labelY: (value) => value.toInt().toString(), 80 | ), 81 | ChartBarLayer( 82 | items: List.generate( 83 | 13 - 7 + 1, 84 | (index) => ChartBarDataItem( 85 | color: const Color(0xFF8043F9), 86 | value: Random().nextInt(280) + 20, 87 | x: index.toDouble() + 7, 88 | ), 89 | ), 90 | settings: const ChartBarSettings( 91 | thickness: 8.0, 92 | radius: BorderRadius.all(Radius.circular(4.0)), 93 | ), 94 | ), 95 | ]; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /example/lib/pages/candle_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:intl/intl.dart'; 3 | import 'package:mrx_charts/mrx_charts.dart'; 4 | 5 | class CandlePage extends StatefulWidget { 6 | const CandlePage({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _CandlePageState(); 10 | } 11 | 12 | class _CandlePageState extends State { 13 | bool _whichCandleMock = true; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | appBar: AppBar( 19 | actions: [ 20 | Padding( 21 | padding: const EdgeInsets.only( 22 | right: 20.0, 23 | ), 24 | child: GestureDetector( 25 | onTap: () => setState(() {}), 26 | child: const Icon( 27 | Icons.refresh, 28 | size: 26.0, 29 | ), 30 | ), 31 | ), 32 | ], 33 | backgroundColor: Colors.transparent, 34 | elevation: 0.0, 35 | title: const Text('Candle'), 36 | ), 37 | backgroundColor: const Color(0xFF1B0E41), 38 | body: Center( 39 | child: Container( 40 | constraints: const BoxConstraints( 41 | maxHeight: 400.0, 42 | maxWidth: 600.0, 43 | ), 44 | padding: const EdgeInsets.all(24.0), 45 | child: Chart( 46 | layers: layers(), 47 | padding: const EdgeInsets.symmetric(horizontal: 12.0).copyWith( 48 | bottom: 12.0, 49 | ), 50 | ), 51 | ), 52 | ), 53 | ); 54 | } 55 | 56 | List layers() { 57 | _whichCandleMock = !_whichCandleMock; 58 | final double frequency = 59 | (DateTime(2017, 11).millisecondsSinceEpoch.toDouble() - 60 | DateTime(2017, 4).millisecondsSinceEpoch.toDouble()) / 61 | 4; 62 | final double frequencyData = frequency / 3; 63 | final double from = DateTime(2017, 4).millisecondsSinceEpoch.toDouble(); 64 | return [ 65 | ChartGridLayer( 66 | settings: ChartGridSettings( 67 | x: ChartGridSettingsAxis( 68 | color: Colors.white.withOpacity(0.2), 69 | frequency: frequency, 70 | max: DateTime(2017, 11).millisecondsSinceEpoch.toDouble(), 71 | min: DateTime(2017, 4).millisecondsSinceEpoch.toDouble(), 72 | ), 73 | y: ChartGridSettingsAxis( 74 | color: Colors.white.withOpacity(0.2), 75 | frequency: 3.0, 76 | max: 66.0, 77 | min: 48.0, 78 | ), 79 | ), 80 | ), 81 | ChartAxisLayer( 82 | settings: ChartAxisSettings( 83 | x: ChartAxisSettingsAxis( 84 | frequency: frequency, 85 | max: DateTime(2017, 11).millisecondsSinceEpoch.toDouble(), 86 | min: DateTime(2017, 4).millisecondsSinceEpoch.toDouble(), 87 | textStyle: TextStyle( 88 | color: Colors.white.withOpacity(0.6), 89 | fontSize: 10.0, 90 | ), 91 | ), 92 | y: ChartAxisSettingsAxis( 93 | frequency: 3.0, 94 | max: 66.0, 95 | min: 48.0, 96 | textStyle: TextStyle( 97 | color: Colors.white.withOpacity(0.6), 98 | fontSize: 10.0, 99 | ), 100 | ), 101 | ), 102 | labelX: (value) => DateFormat('MMM yyyy') 103 | .format(DateTime.fromMillisecondsSinceEpoch(value.toInt())), 104 | labelY: (value) => value.toInt().toString(), 105 | ), 106 | ChartCandleLayer( 107 | items: _whichCandleMock 108 | ? [ 109 | _candleItem(Colors.green, 50.0, 52.0, 48.0, 53.0, from), 110 | _candleItem( 111 | Colors.red, 52.0, 54.0, 51.0, 57.0, from + frequencyData), 112 | _candleItem(Colors.red, 53.0, 56.0, 53.0, 56.0, 113 | from + 2 * frequencyData), 114 | _candleItem(Colors.green, 54.0, 56.0, 53.0, 58.0, 115 | from + 3 * frequencyData), 116 | _candleItem(Colors.green, 55.0, 57.0, 53.0, 58.0, 117 | from + 4 * frequencyData), 118 | _candleItem(Colors.green, 56.0, 58.0, 56.0, 58.0, 119 | from + 5 * frequencyData), 120 | _candleItem(Colors.red, 58.0, 60.0, 57.0, 61.0, 121 | from + 6 * frequencyData), 122 | _candleItem(Colors.green, 57.5, 59.0, 56.5, 60.3, 123 | from + 7 * frequencyData), 124 | _candleItem(Colors.green, 57.0, 59.0, 57.0, 60.0, 125 | from + 8 * frequencyData), 126 | _candleItem(Colors.red, 60.0, 62.0, 57.0, 61.0, 127 | from + 9 * frequencyData), 128 | _candleItem(Colors.green, 63.0, 65.0, 62.0, 66.0, 129 | from + 10 * frequencyData), 130 | _candleItem(Colors.green, 64.0, 66.0, 63.0, 66.0, 131 | from + 11 * frequencyData), 132 | _candleItem(Colors.red, 62.0, 64.0, 61.0, 64.0, 133 | from + 12 * frequencyData), 134 | ] 135 | : [ 136 | _candleItem(Colors.red, 62.0, 64.0, 61.0, 64.0, from), 137 | _candleItem( 138 | Colors.green, 64.0, 66.0, 63.0, 66.0, from + frequencyData), 139 | _candleItem(Colors.green, 63.0, 65.0, 62.0, 66.0, 140 | from + 2 * frequencyData), 141 | _candleItem(Colors.red, 60.0, 62.0, 57.0, 61.0, 142 | from + 3 * frequencyData), 143 | _candleItem(Colors.green, 57.0, 59.0, 57.0, 60.0, 144 | from + 4 * frequencyData), 145 | _candleItem(Colors.green, 57.5, 59.0, 56.5, 60.3, 146 | from + 5 * frequencyData), 147 | _candleItem(Colors.red, 58.0, 60.0, 57.0, 61.0, 148 | from + 6 * frequencyData), 149 | _candleItem(Colors.green, 56.0, 58.0, 56.0, 58.0, 150 | from + 7 * frequencyData), 151 | _candleItem(Colors.green, 55.0, 57.0, 53.0, 58.0, 152 | from + 8 * frequencyData), 153 | _candleItem(Colors.green, 54.0, 56.0, 53.0, 58.0, 154 | from + 9 * frequencyData), 155 | _candleItem(Colors.red, 53.0, 56.0, 53.0, 56.0, 156 | from + 10 * frequencyData), 157 | _candleItem(Colors.red, 52.0, 54.0, 51.0, 57.0, 158 | from + 11 * frequencyData), 159 | _candleItem(Colors.green, 50.0, 52.0, 48.0, 53.0, 160 | from + 12 * frequencyData), 161 | ], 162 | settings: const ChartCandleSettings(), 163 | ), 164 | ]; 165 | } 166 | 167 | static _candleItem(Color color, double min1, double max1, double min2, 168 | double max2, double x) { 169 | return ChartCandleDataItem( 170 | color: color, 171 | value1: ChartCandleDataItemValue( 172 | max: max1, 173 | min: min1, 174 | ), 175 | value2: ChartCandleDataItemValue( 176 | max: max2, 177 | min: min2, 178 | ), 179 | x: x, 180 | ); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /example/lib/pages/group_bar_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:mrx_charts/mrx_charts.dart'; 5 | 6 | class GroupBarPage extends StatefulWidget { 7 | const GroupBarPage({Key? key}) : super(key: key); 8 | 9 | @override 10 | State createState() => _GroupBarPageState(); 11 | } 12 | 13 | class _GroupBarPageState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | appBar: AppBar( 18 | actions: [ 19 | Padding( 20 | padding: const EdgeInsets.only( 21 | right: 20.0, 22 | ), 23 | child: GestureDetector( 24 | onTap: () => setState(() {}), 25 | child: const Icon( 26 | Icons.refresh, 27 | size: 26.0, 28 | ), 29 | ), 30 | ), 31 | ], 32 | backgroundColor: Colors.transparent, 33 | elevation: 0.0, 34 | title: const Text('Group bar'), 35 | ), 36 | backgroundColor: const Color(0xFF1B0E41), 37 | body: Center( 38 | child: Container( 39 | constraints: const BoxConstraints( 40 | maxHeight: 400.0, 41 | maxWidth: 600.0, 42 | ), 43 | padding: const EdgeInsets.all(24.0), 44 | child: Chart( 45 | layers: layers(), 46 | padding: const EdgeInsets.symmetric(horizontal: 12.0).copyWith( 47 | bottom: 12.0, 48 | ), 49 | ), 50 | ), 51 | ), 52 | ); 53 | } 54 | 55 | List layers() { 56 | return [ 57 | ChartAxisLayer( 58 | settings: ChartAxisSettings( 59 | x: ChartAxisSettingsAxis( 60 | frequency: 1.0, 61 | max: 12.0, 62 | min: 7.0, 63 | textStyle: TextStyle( 64 | color: Colors.white.withOpacity(0.6), 65 | fontSize: 10.0, 66 | ), 67 | ), 68 | y: ChartAxisSettingsAxis( 69 | frequency: 100.0, 70 | max: 300.0, 71 | min: 0.0, 72 | textStyle: TextStyle( 73 | color: Colors.white.withOpacity(0.6), 74 | fontSize: 10.0, 75 | ), 76 | ), 77 | ), 78 | labelX: (value) => value.toInt().toString(), 79 | labelY: (value) => value.toInt().toString(), 80 | ), 81 | ChartGroupBarLayer( 82 | items: List.generate( 83 | 12 - 7 + 1, 84 | (index) => [ 85 | ChartGroupBarDataItem( 86 | color: const Color(0xFF8043F9), 87 | x: index + 7, 88 | value: Random().nextInt(280) + 20, 89 | ), 90 | ChartGroupBarDataItem( 91 | color: const Color(0xFFFF4150), 92 | x: index + 7, 93 | value: Random().nextInt(280) + 20, 94 | ), 95 | ], 96 | ), 97 | settings: const ChartGroupBarSettings( 98 | thickness: 8.0, 99 | radius: BorderRadius.all(Radius.circular(4.0)), 100 | ), 101 | ), 102 | ChartTooltipLayer( 103 | shape: () => ChartTooltipBarShape( 104 | backgroundColor: Colors.white, 105 | currentPos: (item) => item.currentValuePos, 106 | currentSize: (item) => item.currentValueSize, 107 | onTextValue: (item) => '€${item.value.toString()}', 108 | marginBottom: 6.0, 109 | padding: const EdgeInsets.symmetric( 110 | horizontal: 12.0, 111 | vertical: 8.0, 112 | ), 113 | radius: 6.0, 114 | textStyle: const TextStyle( 115 | color: Color(0xFF8043F9), 116 | letterSpacing: 0.2, 117 | fontSize: 14.0, 118 | fontWeight: FontWeight.w700, 119 | ), 120 | ), 121 | ), 122 | ]; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /example/lib/pages/line_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:intl/intl.dart'; 5 | import 'package:mrx_charts/mrx_charts.dart'; 6 | 7 | class LinePage extends StatefulWidget { 8 | const LinePage({Key? key}) : super(key: key); 9 | 10 | @override 11 | State createState() => _LinePageState(); 12 | } 13 | 14 | class _LinePageState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | appBar: AppBar( 19 | actions: [ 20 | Padding( 21 | padding: const EdgeInsets.only( 22 | right: 20.0, 23 | ), 24 | child: GestureDetector( 25 | onTap: () => setState(() {}), 26 | child: const Icon( 27 | Icons.refresh, 28 | size: 26.0, 29 | ), 30 | ), 31 | ), 32 | ], 33 | backgroundColor: Colors.transparent, 34 | elevation: 0.0, 35 | title: const Text('Line'), 36 | ), 37 | backgroundColor: const Color(0xFF1B0E41), 38 | body: Center( 39 | child: Container( 40 | constraints: const BoxConstraints( 41 | maxHeight: 400.0, 42 | maxWidth: 600.0, 43 | ), 44 | padding: const EdgeInsets.all(24.0), 45 | child: Chart( 46 | layers: layers(), 47 | padding: const EdgeInsets.symmetric(horizontal: 30.0).copyWith( 48 | bottom: 12.0, 49 | ), 50 | ), 51 | ), 52 | ), 53 | ); 54 | } 55 | 56 | List layers() { 57 | final from = DateTime(2021, 4); 58 | final to = DateTime(2021, 8); 59 | final frequency = 60 | (to.millisecondsSinceEpoch - from.millisecondsSinceEpoch) / 3.0; 61 | return [ 62 | ChartHighlightLayer( 63 | shape: () => ChartHighlightLineShape( 64 | backgroundColor: const Color(0xFF331B6D), 65 | currentPos: (item) => item.currentValuePos, 66 | radius: const BorderRadius.all(Radius.circular(8.0)), 67 | width: 60.0, 68 | ), 69 | ), 70 | ChartAxisLayer( 71 | settings: ChartAxisSettings( 72 | x: ChartAxisSettingsAxis( 73 | frequency: frequency, 74 | max: to.millisecondsSinceEpoch.toDouble(), 75 | min: from.millisecondsSinceEpoch.toDouble(), 76 | textStyle: TextStyle( 77 | color: Colors.white.withOpacity(0.6), 78 | fontSize: 10.0, 79 | ), 80 | ), 81 | y: ChartAxisSettingsAxis( 82 | frequency: 100.0, 83 | max: 400.0, 84 | min: 0.0, 85 | textStyle: TextStyle( 86 | color: Colors.white.withOpacity(0.6), 87 | fontSize: 10.0, 88 | ), 89 | ), 90 | ), 91 | labelX: (value) => DateFormat('MMM') 92 | .format(DateTime.fromMillisecondsSinceEpoch(value.toInt())), 93 | labelY: (value) => value.toInt().toString(), 94 | ), 95 | ChartLineLayer( 96 | items: List.generate( 97 | 4, 98 | (index) => ChartLineDataItem( 99 | x: (index * frequency) + from.millisecondsSinceEpoch, 100 | value: Random().nextInt(380) + 20, 101 | ), 102 | ), 103 | settings: const ChartLineSettings( 104 | color: Color(0xFF8043F9), 105 | thickness: 4.0, 106 | ), 107 | ), 108 | ChartTooltipLayer( 109 | shape: () => ChartTooltipLineShape( 110 | backgroundColor: Colors.white, 111 | circleBackgroundColor: Colors.white, 112 | circleBorderColor: const Color(0xFF331B6D), 113 | circleSize: 4.0, 114 | circleBorderThickness: 2.0, 115 | currentPos: (item) => item.currentValuePos, 116 | onTextValue: (item) => '€${item.value.toString()}', 117 | marginBottom: 6.0, 118 | padding: const EdgeInsets.symmetric( 119 | horizontal: 12.0, 120 | vertical: 8.0, 121 | ), 122 | radius: 6.0, 123 | textStyle: const TextStyle( 124 | color: Color(0xFF8043F9), 125 | letterSpacing: 0.2, 126 | fontSize: 14.0, 127 | fontWeight: FontWeight.w700, 128 | ), 129 | ), 130 | ), 131 | ]; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /example/lib/pages/pie_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:mrx_charts/mrx_charts.dart'; 5 | 6 | class PiePage extends StatefulWidget { 7 | const PiePage({Key? key}) : super(key: key); 8 | 9 | @override 10 | State createState() => _PiePageState(); 11 | } 12 | 13 | class _PiePageState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | appBar: AppBar( 18 | actions: [ 19 | Padding( 20 | padding: const EdgeInsets.only( 21 | right: 20.0, 22 | ), 23 | child: GestureDetector( 24 | onTap: () => setState(() {}), 25 | child: const Icon( 26 | Icons.refresh, 27 | size: 26.0, 28 | ), 29 | ), 30 | ), 31 | ], 32 | backgroundColor: Colors.transparent, 33 | elevation: 0.0, 34 | title: const Text('Pie'), 35 | ), 36 | backgroundColor: const Color(0xFF1B0E41), 37 | body: Center( 38 | child: Container( 39 | constraints: const BoxConstraints( 40 | maxHeight: 400.0, 41 | maxWidth: 600.0, 42 | ), 43 | padding: const EdgeInsets.all(24.0), 44 | child: Chart( 45 | layers: layers(), 46 | ), 47 | ), 48 | ), 49 | ); 50 | } 51 | 52 | List layers() { 53 | return [ 54 | ChartGroupPieLayer( 55 | items: List.generate( 56 | 2, 57 | (index) => List.generate( 58 | Random().nextInt(4) + 2, 59 | (index) => ChartGroupPieDataItem( 60 | amount: Random().nextInt(300) * Random().nextDouble(), 61 | color: [ 62 | Colors.orangeAccent, 63 | Colors.pinkAccent, 64 | Colors.redAccent, 65 | Colors.blueAccent, 66 | Colors.cyanAccent, 67 | Colors.tealAccent, 68 | ][Random().nextInt(6)], 69 | label: [ 70 | 'Life', 71 | 'Work', 72 | 'Medicine', 73 | 'Bills', 74 | 'Hobby', 75 | 'Holiday', 76 | ][Random().nextInt(6)]), 77 | ), 78 | ), 79 | settings: const ChartGroupPieSettings(), 80 | ), 81 | ChartTooltipLayer( 82 | shape: () => ChartTooltipPieShape( 83 | onTextName: (item) => item.label, 84 | onTextValue: (item) => '€${item.amount.toString()}', 85 | radius: 10.0, 86 | backgroundColor: Colors.white, 87 | padding: const EdgeInsets.all(12.0), 88 | nameTextStyle: const TextStyle( 89 | color: Color(0xFF8043F9), 90 | fontWeight: FontWeight.w700, 91 | height: 1.47, 92 | fontSize: 12.0, 93 | ), 94 | valueTextStyle: const TextStyle( 95 | color: Color(0xFF1B0E41), 96 | fontWeight: FontWeight.w700, 97 | fontSize: 12.0, 98 | ), 99 | ), 100 | ) 101 | ]; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.4" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.0" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | url: "https://pub.dartlang.org" 70 | source: hosted 71 | version: "1.0.4" 72 | flutter_test: 73 | dependency: "direct dev" 74 | description: flutter 75 | source: sdk 76 | version: "0.0.0" 77 | intl: 78 | dependency: "direct main" 79 | description: 80 | name: intl 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "0.17.0" 84 | lints: 85 | dependency: transitive 86 | description: 87 | name: lints 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.0.1" 91 | matcher: 92 | dependency: transitive 93 | description: 94 | name: matcher 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.12.11" 98 | material_color_utilities: 99 | dependency: transitive 100 | description: 101 | name: material_color_utilities 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "0.1.3" 105 | meta: 106 | dependency: transitive 107 | description: 108 | name: meta 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "1.7.0" 112 | mrx_charts: 113 | dependency: "direct main" 114 | description: 115 | path: ".." 116 | relative: true 117 | source: path 118 | version: "0.1.2" 119 | path: 120 | dependency: transitive 121 | description: 122 | name: path 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "1.8.0" 126 | sky_engine: 127 | dependency: transitive 128 | description: flutter 129 | source: sdk 130 | version: "0.0.99" 131 | source_span: 132 | dependency: transitive 133 | description: 134 | name: source_span 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.8.1" 138 | stack_trace: 139 | dependency: transitive 140 | description: 141 | name: stack_trace 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.10.0" 145 | stream_channel: 146 | dependency: transitive 147 | description: 148 | name: stream_channel 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "2.1.0" 152 | string_scanner: 153 | dependency: transitive 154 | description: 155 | name: string_scanner 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.1.0" 159 | term_glyph: 160 | dependency: transitive 161 | description: 162 | name: term_glyph 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.2.0" 166 | test_api: 167 | dependency: transitive 168 | description: 169 | name: test_api 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "0.4.8" 173 | typed_data: 174 | dependency: transitive 175 | description: 176 | name: typed_data 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.3.0" 180 | vector_math: 181 | dependency: transitive 182 | description: 183 | name: vector_math 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.1.1" 187 | sdks: 188 | dart: ">=2.16.1 <3.0.0" 189 | flutter: ">=1.17.0" 190 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | publish_to: 'none' 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: ">=2.16.1 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | cupertino_icons: ^1.0.2 14 | mrx_charts: 15 | path: ../ 16 | intl: ^0.17.0 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | flutter_lints: ^1.0.0 22 | 23 | flutter: 24 | uses-material-design: true -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | example 33 | 34 | 35 | 36 | 39 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /lib/mrx_charts.dart: -------------------------------------------------------------------------------- 1 | library mrx_charts; 2 | 3 | export 'src/chart.dart'; 4 | export 'src/models/animation/chart_animation.dart'; 5 | export 'src/models/axis/chart_axis_layer.dart'; 6 | export 'src/models/bar/chart_bar_layer.dart'; 7 | export 'src/models/candle/chart_candle_layer.dart'; 8 | export 'src/models/chart_axis_value.dart'; 9 | export 'src/models/chart_data_item.dart'; 10 | export 'src/models/chart_layer.dart'; 11 | export 'src/models/chart_painter_data.dart'; 12 | export 'src/models/grid/chart_grid_layer.dart'; 13 | export 'src/models/group/bar/chart_group_bar_layer.dart'; 14 | export 'src/models/group/pie/chart_group_pie_layer.dart'; 15 | export 'src/models/highlight/chart_highlight_layer.dart'; 16 | export 'src/models/highlight/shape/chart_highlight_shape.dart'; 17 | export 'src/models/line/chart_line_layer.dart'; 18 | export 'src/models/tooltip/chart_tooltip_layer.dart'; 19 | export 'src/models/tooltip/shape/chart_tooltip_shape.dart'; 20 | export 'src/models/touchable/arc_shape.dart'; 21 | export 'src/models/touchable/rectangle_shape.dart'; 22 | export 'src/models/touchable/touchable_shape.dart'; 23 | export 'src/painter/chart_painter.dart'; 24 | export 'src/touch/chart_touch_callback_data.dart'; 25 | export 'src/touch/chart_touch_detector.dart'; 26 | -------------------------------------------------------------------------------- /lib/src/chart.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 2 | import 'package:mrx_charts/src/models/chart_layer.dart'; 3 | import 'package:mrx_charts/src/models/touchable/touchable_shape.dart'; 4 | import 'package:mrx_charts/src/painter/chart_painter.dart'; 5 | import 'package:mrx_charts/src/touch/chart_touch_detector.dart'; 6 | import 'package:mrx_charts/src/touch/chart_touch_callback_data.dart'; 7 | import 'package:flutter/material.dart'; 8 | 9 | /// Widget of charts. 10 | class Chart extends StatefulWidget { 11 | /// The duration of the chart animations. 12 | /// 13 | /// Defaults to Duration(milliseconds: 300) 14 | final Duration duration; 15 | 16 | /// The layers of charts. 17 | final List layers; 18 | 19 | /// The padding of charts. 20 | /// 21 | /// Defaults to EdgeInsets.zero 22 | final EdgeInsets padding; 23 | 24 | const Chart({ 25 | this.duration = const Duration( 26 | milliseconds: 300, 27 | ), 28 | this.layers = const [], 29 | this.padding = EdgeInsets.zero, 30 | Key? key, 31 | }) : super(key: key); 32 | 33 | @override 34 | State createState() => _ChartState(); 35 | } 36 | 37 | class _ChartState extends State with TickerProviderStateMixin { 38 | late final AnimationController _controller; 39 | List? oldLayers; 40 | List> _touchableShapes = []; 41 | ChartTouchCallbackData? _touchedData; 42 | 43 | @override 44 | void initState() { 45 | super.initState(); 46 | _controller = AnimationController( 47 | duration: widget.duration, 48 | vsync: this, 49 | ); 50 | WidgetsBinding.instance.addPostFrameCallback( 51 | (_) => _controller 52 | ..stop() 53 | ..reset() 54 | ..forward(), 55 | ); 56 | } 57 | 58 | @override 59 | void didUpdateWidget(covariant Chart oldWidget) { 60 | if (widget.layers != oldWidget.layers) { 61 | setState(() { 62 | oldLayers = oldWidget.layers; 63 | _touchedData = null; 64 | _disposeOldLayers(); 65 | _controller 66 | ..stop() 67 | ..reset() 68 | ..forward(); 69 | }); 70 | } 71 | super.didUpdateWidget(oldWidget); 72 | } 73 | 74 | @override 75 | void dispose() { 76 | _controller.dispose(); 77 | super.dispose(); 78 | } 79 | 80 | @override 81 | Widget build(BuildContext context) { 82 | return Column( 83 | crossAxisAlignment: CrossAxisAlignment.stretch, 84 | mainAxisSize: MainAxisSize.min, 85 | children: [ 86 | Expanded( 87 | child: AnimatedBuilder( 88 | animation: _controller, 89 | builder: (_, __) => ChartTouchDetector( 90 | onShapes: () => _touchableShapes, 91 | onTap: ((touchPosition, data) => setState(() { 92 | _touchedData = data == null 93 | ? null 94 | : ChartTouchCallbackData( 95 | clickedPos: touchPosition, 96 | selectedItem: data, 97 | ); 98 | })), 99 | child: CustomPaint( 100 | painter: ChartPainter( 101 | controller: _controller, 102 | layers: widget.layers, 103 | oldLayers: oldLayers, 104 | onUpdateTouchableShapes: (shapes) => 105 | _touchableShapes = shapes, 106 | padding: widget.padding, 107 | touchedData: _touchedData, 108 | ), 109 | ), 110 | ), 111 | ), 112 | ), 113 | ], 114 | ); 115 | } 116 | 117 | void _disposeOldLayers() { 118 | for (final ChartLayer layer in oldLayers ?? []) { 119 | layer.dispose(); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/src/models/animation/chart_animation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | part 'chart_color_animation.dart'; 4 | part 'chart_double_animation.dart'; 5 | part 'chart_position_animation.dart'; 6 | part 'chart_size_animation.dart'; 7 | part 'chart_text_style_animation.dart'; 8 | 9 | /// Abstract class for animation. 10 | abstract class ChartAnimation { 11 | void dispose(); 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/models/animation/chart_color_animation.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_animation.dart'; 2 | 3 | /// Provides color animation values. 4 | class ChartColorAnimation implements ChartAnimation { 5 | Animation? _animation; 6 | Color _lastColor = Colors.transparent; 7 | 8 | ChartColorAnimation(); 9 | 10 | /// Current value during the animation. 11 | /// 12 | /// Defaults to Colors.transparent 13 | Color get current => _lastColor = _animation?.value ?? Colors.transparent; 14 | 15 | /// Last value on finish/stop animation. 16 | /// 17 | /// Defaults to Colors.transparent 18 | Color get last => _lastColor; 19 | 20 | /// Dispose animation. 21 | @override 22 | void dispose() { 23 | _animation = null; 24 | } 25 | 26 | /// Initialize animation. 27 | void setup({ 28 | required Color color, 29 | required AnimationController controller, 30 | Curve curve = Curves.easeInOut, 31 | Color? initialColor, 32 | ChartColorAnimation? oldAnimation, 33 | }) { 34 | final Animation animation = ColorTween( 35 | begin: oldAnimation?._lastColor ?? initialColor ?? Colors.transparent, 36 | end: color, 37 | ).animate( 38 | CurvedAnimation( 39 | parent: controller, 40 | curve: curve, 41 | ), 42 | ); 43 | _animation = animation; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/models/animation/chart_double_animation.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_animation.dart'; 2 | 3 | /// Provides double animation values. 4 | class ChartDoubleAnimation implements ChartAnimation { 5 | Animation? _animation; 6 | double _lastValue = 0.0; 7 | 8 | ChartDoubleAnimation(); 9 | 10 | /// Current value during the animation. 11 | /// 12 | /// Defaults to 0.0 13 | double get current => _lastValue = _animation?.value ?? 0.0; 14 | 15 | /// Last double value on finish/stop animation. 16 | /// 17 | /// Defaults to 0.0 18 | double get last => _lastValue; 19 | 20 | /// Dispose animation. 21 | @override 22 | void dispose() { 23 | _animation = null; 24 | } 25 | 26 | /// Initialize animation. 27 | void setup({ 28 | required AnimationController controller, 29 | required double value, 30 | Curve curve = Curves.easeOutExpo, 31 | double? initialValue, 32 | ChartDoubleAnimation? oldAnimation, 33 | }) { 34 | final Animation animation = Tween( 35 | begin: oldAnimation?._lastValue ?? initialValue ?? value, 36 | end: value, 37 | ).animate( 38 | CurvedAnimation( 39 | parent: controller, 40 | curve: curve, 41 | ), 42 | ); 43 | _animation = animation; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/models/animation/chart_position_animation.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_animation.dart'; 2 | 3 | /// Provides position animation values. 4 | class ChartPositionAnimation implements ChartAnimation { 5 | Animation? _animation; 6 | Offset _lastPosition = Offset.zero; 7 | 8 | ChartPositionAnimation(); 9 | 10 | /// Current value during the animation. 11 | /// 12 | /// Defaults to Offset.zero 13 | Offset get current => _lastPosition = _animation?.value ?? Offset.zero; 14 | 15 | /// Last value on finish/stop animation. 16 | /// 17 | /// Defaults to Offset.zero 18 | Offset get last => _lastPosition; 19 | 20 | /// Dispose animation. 21 | @override 22 | void dispose() { 23 | _animation = null; 24 | } 25 | 26 | /// Initialize animation. 27 | void setup({ 28 | required AnimationController controller, 29 | required Offset position, 30 | Curve curve = Curves.easeOutExpo, 31 | Offset? initialPosition, 32 | ChartPositionAnimation? oldAnimation, 33 | }) { 34 | final Animation animation = Tween( 35 | begin: oldAnimation?._lastPosition ?? initialPosition ?? position, 36 | end: position, 37 | ).animate( 38 | CurvedAnimation( 39 | parent: controller, 40 | curve: curve, 41 | ), 42 | ); 43 | _animation = animation; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/models/animation/chart_size_animation.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_animation.dart'; 2 | 3 | /// Provides size animation values. 4 | class ChartSizeAnimation implements ChartAnimation { 5 | Animation? _animation; 6 | Size _lastSize = Size.zero; 7 | 8 | ChartSizeAnimation(); 9 | 10 | /// Current value during the animation. 11 | /// 12 | /// Defaults to Size.zero 13 | Size get current => _lastSize = _animation?.value ?? Size.zero; 14 | 15 | /// Last value on finish/stop animation. 16 | /// 17 | /// Defaults to Size.zero 18 | Size get last => _lastSize; 19 | 20 | /// Dispose animation. 21 | @override 22 | void dispose() { 23 | _animation = null; 24 | } 25 | 26 | /// Initialize animation. 27 | void setup({ 28 | required AnimationController controller, 29 | required Size size, 30 | Curve curve = Curves.easeOutExpo, 31 | Size? initialSize, 32 | ChartSizeAnimation? oldAnimation, 33 | }) { 34 | final Animation animation = Tween( 35 | begin: oldAnimation?._lastSize ?? initialSize ?? size, 36 | end: size, 37 | ).animate( 38 | CurvedAnimation( 39 | parent: controller, 40 | curve: curve, 41 | ), 42 | ); 43 | _animation = animation; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/models/animation/chart_text_style_animation.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_animation.dart'; 2 | 3 | /// Provides text style animation values. 4 | class ChartTextStyleAnimation implements ChartAnimation { 5 | Animation? _animation; 6 | TextStyle _lastTextStyle = const TextStyle( 7 | color: Colors.transparent, 8 | ); 9 | 10 | ChartTextStyleAnimation(); 11 | 12 | /// Current value during the animation. 13 | /// 14 | /// Defaults to TextStyle(color: Colors.transparent) 15 | TextStyle get current => _lastTextStyle = _animation?.value ?? 16 | const TextStyle( 17 | color: Colors.transparent, 18 | ); 19 | 20 | /// Last value on finish/stop animation. 21 | /// 22 | /// Defaults to TextStyle(color: Colors.transparent) 23 | TextStyle get last => _lastTextStyle; 24 | 25 | /// Dispose animation. 26 | @override 27 | void dispose() { 28 | _animation = null; 29 | } 30 | 31 | /// Initialize animation. 32 | void setup({ 33 | required AnimationController controller, 34 | required TextStyle textStyle, 35 | Curve curve = Curves.easeOutExpo, 36 | TextStyle? initialTextSyle, 37 | ChartTextStyleAnimation? oldAnimation, 38 | }) { 39 | final Animation animation = TextStyleTween( 40 | begin: oldAnimation?._lastTextStyle ?? 41 | initialTextSyle ?? 42 | const TextStyle( 43 | color: Colors.transparent, 44 | ), 45 | end: textStyle, 46 | ).animate( 47 | CurvedAnimation( 48 | parent: controller, 49 | curve: curve, 50 | ), 51 | ); 52 | _animation = animation; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/src/models/axis/chart_axis_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 3 | import 'package:mrx_charts/src/models/chart_layer.dart'; 4 | 5 | part 'data/chart_axis_data.dart'; 6 | part 'data/chart_axis_data_item.dart'; 7 | part 'settings/chart_axis_settings.dart'; 8 | part 'settings/chart_axis_settings_axis.dart'; 9 | 10 | /// This layer allows to render axises. 11 | class ChartAxisLayer extends ChartLayer { 12 | /// The x of the axis. 13 | final ChartAxisData x; 14 | 15 | /// The y of the axis. 16 | final ChartAxisData y; 17 | 18 | /// The settings of the axis. 19 | final ChartAxisSettings settings; 20 | 21 | ChartAxisLayer({ 22 | required String Function(double) labelX, 23 | required String Function(double) labelY, 24 | required this.settings, 25 | }) : x = settings.x.generate( 26 | label: labelX, 27 | ), 28 | y = settings.y.generate( 29 | label: labelY, 30 | ); 31 | 32 | /// Disposing all animations. 33 | @override 34 | void dispose() { 35 | x.dispose(); 36 | y.dispose(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/models/axis/data/chart_axis_data.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_axis_layer.dart'; 2 | 3 | /// Providing datas of the selected axis. 4 | class ChartAxisData { 5 | /// The items data of axis. 6 | final List items; 7 | 8 | /// The max value in the data. 9 | final double max; 10 | 11 | /// The min value in the data. 12 | final double min; 13 | 14 | ChartAxisData({ 15 | required this.items, 16 | required this.max, 17 | required this.min, 18 | }); 19 | 20 | /// Disposing all animations. 21 | void dispose() { 22 | for (final ChartAxisDataItem item in items) { 23 | item.dispose(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/models/axis/data/chart_axis_data_item.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_axis_layer.dart'; 2 | 3 | /// A collection of values for an axis in a chart. 4 | class ChartAxisDataItem { 5 | /// The label of data item. 6 | final String label; 7 | 8 | /// The value of data item. 9 | final double value; 10 | 11 | final ChartPositionAnimation _pos; 12 | final ChartTextStyleAnimation _textStyle; 13 | 14 | ChartAxisDataItem({ 15 | required this.label, 16 | required this.value, 17 | }) : _pos = ChartPositionAnimation(), 18 | _textStyle = ChartTextStyleAnimation(); 19 | 20 | /// Current position during the animation. 21 | /// 22 | /// Defaults to Offset.zero 23 | Offset get currentPos => _pos.current; 24 | 25 | /// Current TextStyle during the animation. 26 | /// 27 | /// Defaults to TextStyle(color: Colors.transparent) 28 | TextStyle get currentTextStyle => _textStyle.current; 29 | 30 | /// Last position on finish/stop animation. 31 | /// 32 | /// Defaults to Offset.zero 33 | Offset get lastPos => _pos.last; 34 | 35 | /// Last TextStyle on finish/stop animation. 36 | /// 37 | /// Defaults to TextStyle(color: Colors.transparent) 38 | TextStyle get lastTextStyle => _textStyle.last; 39 | 40 | /// Disposing all animations. 41 | void dispose() { 42 | _pos.dispose(); 43 | _textStyle.dispose(); 44 | } 45 | 46 | /// Initialize animation. 47 | void setup({ 48 | required AnimationController controller, 49 | required Offset pos, 50 | required TextStyle textStyle, 51 | Offset? initialPos, 52 | TextStyle? initialTextStyle, 53 | ChartAxisDataItem? oldItem, 54 | }) { 55 | _pos.setup( 56 | controller: controller, 57 | initialPosition: initialPos, 58 | oldAnimation: oldItem?._pos, 59 | position: pos, 60 | ); 61 | _textStyle.setup( 62 | controller: controller, 63 | initialTextSyle: initialTextStyle, 64 | oldAnimation: oldItem?._textStyle, 65 | textStyle: textStyle, 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/src/models/axis/settings/chart_axis_settings.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_axis_layer.dart'; 2 | 3 | /// A collection of values for settings in axises. 4 | class ChartAxisSettings { 5 | /// The x of the axis. 6 | final ChartAxisSettingsAxis x; 7 | 8 | /// The y of the axis. 9 | final ChartAxisSettingsAxis y; 10 | 11 | const ChartAxisSettings({ 12 | required this.x, 13 | required this.y, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/models/axis/settings/chart_axis_settings_axis.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_axis_layer.dart'; 2 | 3 | /// A collection of values for settings of the selected axis. 4 | class ChartAxisSettingsAxis { 5 | /// The frequency of the value. 6 | final double frequency; 7 | 8 | /// The max of the value in the axis. 9 | final double max; 10 | 11 | /// The min of the value in the axis. 12 | final double min; 13 | 14 | /// The TextStyle in axis. 15 | final TextStyle textStyle; 16 | 17 | const ChartAxisSettingsAxis({ 18 | required this.frequency, 19 | required this.max, 20 | required this.min, 21 | required this.textStyle, 22 | }); 23 | 24 | /// Generate all items of axis. 25 | ChartAxisData generate({ 26 | required String Function(double) label, 27 | }) => 28 | ChartAxisData( 29 | max: max, 30 | min: min, 31 | items: List.generate( 32 | ((max - min) ~/ frequency) + 1, 33 | (index) => ChartAxisDataItem( 34 | label: label(index * frequency + min), 35 | value: index * frequency + min, 36 | ), 37 | ), 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/bar/chart_bar_data_item.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_bar_layer.dart'; 2 | 3 | /// A collection of values for a single bar in a chart. 4 | class ChartBarDataItem extends ChartDataItem { 5 | /// The color of data item. 6 | final Color color; 7 | 8 | /// The value of data item. 9 | final double value; 10 | 11 | /// The axis x of data item. 12 | final double x; 13 | 14 | final _ChartBarDataItemTouch _touch; 15 | final _ChartBarDataItemValue _value; 16 | 17 | ChartBarDataItem({ 18 | required this.color, 19 | required this.value, 20 | required this.x, 21 | }) : _touch = _ChartBarDataItemTouch(), 22 | _value = _ChartBarDataItemValue(); 23 | 24 | /// Current touch area position during the animation. 25 | /// 26 | /// Defaults to Offset.zero 27 | Offset get currentTouchPos => _touch.currentPos; 28 | 29 | /// Current touch area size during the animation. 30 | /// 31 | /// Defaults to Size.zero 32 | Size get currentTouchSize => _touch.currentSize; 33 | 34 | /// Current color during the animation. 35 | /// 36 | /// Defaults to Colors.transparent 37 | Color get currentValueColor => _value.currentColor; 38 | 39 | /// Current position during the animation. 40 | /// 41 | /// Defaults to Offset.zero 42 | Offset get currentValuePos => _value.currentPos; 43 | 44 | /// Current size during the animation. 45 | /// 46 | /// Defaults to Size.zero 47 | Size get currentValueSize => _value.currentSize; 48 | 49 | /// Last touch area position on finish/stop animation. 50 | /// 51 | /// Defaults to Offset.zero 52 | Offset get lastTouchPos => _touch.lastPos; 53 | 54 | /// Last touch area size on finish/stop animation. 55 | /// 56 | /// Defaults to Size.zero 57 | Size get lastTouchSize => _touch.lastSize; 58 | 59 | /// Last color on finish/stop animation. 60 | /// 61 | /// Defaults to Colors.transparent 62 | Color get lastValueColor => _value.lastColor; 63 | 64 | /// Last position on finish/stop animation. 65 | /// 66 | /// Defaults to Offset.zero 67 | Offset get lastValuePos => _value.lastPos; 68 | 69 | /// Last size on finish/stop animation. 70 | /// 71 | /// Defaults to Size.zero 72 | Size get lastValueSize => _value.lastSize; 73 | 74 | /// Disposing all animations. 75 | @override 76 | void dispose() { 77 | _touch.dispose(); 78 | _value.dispose(); 79 | } 80 | 81 | /// Initialize touch area animations. 82 | void setupTouch({ 83 | required AnimationController controller, 84 | required Offset pos, 85 | required Size size, 86 | Offset? initialPos, 87 | Size? initialSize, 88 | ChartBarDataItem? oldItem, 89 | }) { 90 | _touch.setup( 91 | controller: controller, 92 | initialPos: initialPos, 93 | initialSize: initialSize, 94 | oldValue: oldItem?._value, 95 | pos: pos, 96 | size: size, 97 | ); 98 | } 99 | 100 | /// Initialize value animations. 101 | void setupValue({ 102 | required Color color, 103 | required AnimationController controller, 104 | required Offset pos, 105 | required Size size, 106 | Color? initialColor, 107 | Offset? initialPos, 108 | Size? initialSize, 109 | ChartBarDataItem? oldItem, 110 | }) { 111 | _value.setup( 112 | color: color, 113 | controller: controller, 114 | initialColor: initialColor, 115 | initialPos: initialPos, 116 | initialSize: initialSize, 117 | oldValue: oldItem?._value, 118 | pos: pos, 119 | size: size, 120 | ); 121 | } 122 | } 123 | 124 | class _ChartBarDataItemTouch { 125 | final ChartPositionAnimation _pos; 126 | final ChartSizeAnimation _size; 127 | 128 | _ChartBarDataItemTouch() 129 | : _pos = ChartPositionAnimation(), 130 | _size = ChartSizeAnimation(); 131 | 132 | /// Current position during the animation. 133 | /// 134 | /// Defaults to Offset.zero 135 | Offset get currentPos => _pos.current; 136 | 137 | /// Current size during the animation. 138 | /// 139 | /// Defaults to Size.zero 140 | Size get currentSize => _size.current; 141 | 142 | /// Last position on finish/stop animation. 143 | /// 144 | /// Defaults to Offset.zero 145 | Offset get lastPos => _pos.last; 146 | 147 | /// Last size on finish/stop animation. 148 | /// 149 | /// Defaults to Size.zero 150 | Size get lastSize => _size.last; 151 | 152 | /// Disposing all animations. 153 | void dispose() { 154 | _pos.dispose(); 155 | _size.dispose(); 156 | } 157 | 158 | /// Initialize animations. 159 | void setup({ 160 | required AnimationController controller, 161 | required Offset pos, 162 | required Size size, 163 | Offset? initialPos, 164 | Size? initialSize, 165 | _ChartBarDataItemValue? oldValue, 166 | }) { 167 | _pos.setup( 168 | controller: controller, 169 | curve: Curves.easeInOut, 170 | initialPosition: initialPos, 171 | oldAnimation: oldValue?._pos, 172 | position: pos, 173 | ); 174 | _size.setup( 175 | controller: controller, 176 | curve: Curves.easeInOut, 177 | initialSize: initialSize, 178 | oldAnimation: oldValue?._size, 179 | size: size, 180 | ); 181 | } 182 | } 183 | 184 | class _ChartBarDataItemValue { 185 | final ChartColorAnimation _color; 186 | final ChartPositionAnimation _pos; 187 | final ChartSizeAnimation _size; 188 | 189 | _ChartBarDataItemValue() 190 | : _color = ChartColorAnimation(), 191 | _pos = ChartPositionAnimation(), 192 | _size = ChartSizeAnimation(); 193 | 194 | /// Current color during the animation. 195 | /// 196 | /// Defaults to Colors.transparent 197 | Color get currentColor => _color.current; 198 | 199 | /// Current position during the animation. 200 | /// 201 | /// Defaults to Offset.zero 202 | Offset get currentPos => _pos.current; 203 | 204 | /// Current size during the animation. 205 | /// 206 | /// Defaults to Size.zero 207 | Size get currentSize => _size.current; 208 | 209 | /// Last color on finish/stop animation. 210 | /// 211 | /// Defaults to Colors.transparent 212 | Color get lastColor => _color.last; 213 | 214 | /// Last position on finish/stop animation. 215 | /// 216 | /// Defaults to Offset.zero 217 | Offset get lastPos => _pos.last; 218 | 219 | /// Last size on finish/stop animation. 220 | /// 221 | /// Defaults to Size.zero 222 | Size get lastSize => _size.last; 223 | 224 | /// Disposing all animations. 225 | void dispose() { 226 | _color.dispose(); 227 | _pos.dispose(); 228 | _size.dispose(); 229 | } 230 | 231 | /// Initialize animations. 232 | void setup({ 233 | required Color color, 234 | required AnimationController controller, 235 | required Offset pos, 236 | required Size size, 237 | Color? initialColor, 238 | Offset? initialPos, 239 | Size? initialSize, 240 | _ChartBarDataItemValue? oldValue, 241 | }) { 242 | _color.setup( 243 | color: color, 244 | controller: controller, 245 | initialColor: initialColor, 246 | oldAnimation: oldValue?._color, 247 | ); 248 | _pos.setup( 249 | controller: controller, 250 | curve: Curves.easeInOut, 251 | initialPosition: initialPos, 252 | oldAnimation: oldValue?._pos, 253 | position: pos, 254 | ); 255 | _size.setup( 256 | controller: controller, 257 | curve: Curves.easeInOut, 258 | initialSize: initialSize, 259 | oldAnimation: oldValue?._size, 260 | size: size, 261 | ); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /lib/src/models/bar/chart_bar_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 2 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 3 | import 'package:mrx_charts/src/models/chart_layer.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part 'chart_bar_data_item.dart'; 7 | part 'chart_bar_settings.dart'; 8 | 9 | /// This layer allows to render bars. 10 | class ChartBarLayer extends ChartLayer { 11 | /// The items data of bars. 12 | final List items; 13 | 14 | /// The settings of bars. 15 | final ChartBarSettings settings; 16 | 17 | const ChartBarLayer({ 18 | required this.items, 19 | required this.settings, 20 | }); 21 | 22 | /// Disposing all animations. 23 | @override 24 | void dispose() { 25 | for (final ChartBarDataItem item in items) { 26 | item.dispose(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/bar/chart_bar_settings.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_bar_layer.dart'; 2 | 3 | /// A collection of values for settings in bars. 4 | class ChartBarSettings { 5 | /// The radius of bars. 6 | /// 7 | /// Defaults to 4.0 8 | final BorderRadius radius; 9 | 10 | /// The thickness of bars. 11 | /// 12 | /// Defaults to BorderRadius.zero 13 | final double thickness; 14 | 15 | const ChartBarSettings({ 16 | this.thickness = 4.0, 17 | this.radius = BorderRadius.zero, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/models/candle/chart_candle_data_item.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_candle_layer.dart'; 2 | 3 | /// A collection of values for a candle in a chart. 4 | class ChartCandleDataItem { 5 | /// The color of candle item. 6 | final Color color; 7 | 8 | /// The value1 of candle item. 9 | final ChartCandleDataItemValue value1; 10 | 11 | /// The value2 of candle item. 12 | final ChartCandleDataItemValue value2; 13 | 14 | /// The x axis of candle item. 15 | final double x; 16 | 17 | const ChartCandleDataItem({ 18 | required this.color, 19 | required this.value1, 20 | required this.value2, 21 | required this.x, 22 | }); 23 | 24 | /// Disposing all animations. 25 | void dispose() { 26 | value1.dispose(); 27 | value2.dispose(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/candle/chart_candle_data_item_value.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_candle_layer.dart'; 2 | 3 | /// A collection of values for per value candle in a chart in. 4 | class ChartCandleDataItemValue { 5 | /// The max of data item. 6 | final double max; 7 | 8 | /// The min of data item. 9 | final double min; 10 | 11 | final ChartColorAnimation _color; 12 | final ChartPositionAnimation _pos; 13 | final ChartSizeAnimation _size; 14 | 15 | ChartCandleDataItemValue({ 16 | required this.max, 17 | required this.min, 18 | }) : _color = ChartColorAnimation(), 19 | _pos = ChartPositionAnimation(), 20 | _size = ChartSizeAnimation(); 21 | 22 | /// Current color during the animation. 23 | /// 24 | /// Defaults to Colors.transparent 25 | Color get currentColor => _color.current; 26 | 27 | /// Current position during the animation. 28 | /// 29 | /// Defaults to Offset.zero 30 | Offset get currentPos => _pos.current; 31 | 32 | /// Current size during the animation. 33 | /// 34 | /// Defaults to Size.zero 35 | Size get currentSize => _size.current; 36 | 37 | /// Last color on finish/stop animation. 38 | /// 39 | /// Defaults to Colors.transparent 40 | Color get lastColor => _color.last; 41 | 42 | /// Last position on finish/stop animation. 43 | /// 44 | /// Defaults to Offset.zero 45 | Offset get lastPos => _pos.last; 46 | 47 | /// Last size on finish/stop animation. 48 | /// 49 | /// Defaults to Size.zero 50 | Size get lastSize => _size.last; 51 | 52 | /// Disposing all animations. 53 | void dispose() { 54 | _color.dispose(); 55 | _pos.dispose(); 56 | _size.dispose(); 57 | } 58 | 59 | /// Initialize animations. 60 | /// 61 | void setup({ 62 | required Color color, 63 | required AnimationController controller, 64 | required Offset pos, 65 | required Size size, 66 | Color? initialColor, 67 | Offset? initialPos, 68 | Size? initialSize, 69 | ChartCandleDataItemValue? oldItem, 70 | }) { 71 | _color.setup( 72 | color: color, 73 | controller: controller, 74 | initialColor: initialColor, 75 | oldAnimation: oldItem?._color, 76 | ); 77 | _pos.setup( 78 | controller: controller, 79 | initialPosition: initialPos, 80 | oldAnimation: oldItem?._pos, 81 | position: pos, 82 | ); 83 | _size.setup( 84 | controller: controller, 85 | initialSize: initialSize, 86 | oldAnimation: oldItem?._size, 87 | size: size, 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/src/models/candle/chart_candle_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 2 | import 'package:mrx_charts/src/models/chart_layer.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | part 'chart_candle_data_item.dart'; 6 | part 'chart_candle_data_item_value.dart'; 7 | part 'chart_candle_settings.dart'; 8 | 9 | /// This layer allows to render candles. 10 | class ChartCandleLayer extends ChartLayer { 11 | /// The items data of candles. 12 | final List items; 13 | 14 | /// The settings of candles. 15 | final ChartCandleSettings settings; 16 | 17 | const ChartCandleLayer({ 18 | required this.items, 19 | required this.settings, 20 | }); 21 | 22 | /// Disposing all animations. 23 | @override 24 | void dispose() { 25 | for (final ChartCandleDataItem item in items) { 26 | item.dispose(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/candle/chart_candle_settings.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_candle_layer.dart'; 2 | 3 | /// A collection of values for settings in candles. 4 | class ChartCandleSettings { 5 | /// The radius of candles. 6 | /// 7 | /// Defaults to 4.0 8 | final double radius; 9 | 10 | /// The thickness of candles. 11 | /// 12 | /// Defaults to 8.0 13 | final double thickness; 14 | 15 | const ChartCandleSettings({ 16 | this.radius = 4.0, 17 | this.thickness = 8.0, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/models/chart_axis_value.dart: -------------------------------------------------------------------------------- 1 | /// A collection of values for the selected axis. 2 | class ChartAxisValue { 3 | /// The max of axis's value. 4 | final double max; 5 | 6 | /// The min of axis's value. 7 | final double min; 8 | 9 | const ChartAxisValue({ 10 | required this.max, 11 | required this.min, 12 | }); 13 | 14 | const ChartAxisValue.empty() 15 | : max = 0.0, 16 | min = 0.0; 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/models/chart_data_item.dart: -------------------------------------------------------------------------------- 1 | /// Abstract class for data item. 2 | abstract class ChartDataItem { 3 | const ChartDataItem(); 4 | 5 | /// Dispose all animations. 6 | void dispose(); 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/models/chart_layer.dart: -------------------------------------------------------------------------------- 1 | /// Abstract class for custom layer. 2 | abstract class ChartLayer { 3 | const ChartLayer(); 4 | 5 | /// Disposing all animations. 6 | void dispose(); 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/models/chart_painter_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// A collection values for painter data. 4 | class ChartPainterData { 5 | /// The position of painter object. 6 | final Offset position; 7 | 8 | /// The size of painter object. 9 | final Size size; 10 | 11 | const ChartPainterData({ 12 | required this.position, 13 | required this.size, 14 | }); 15 | 16 | const ChartPainterData.empty() 17 | : position = Offset.zero, 18 | size = Size.zero; 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/models/grid/chart_grid_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/chart_layer.dart'; 2 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | part 'data/chart_grid_data.dart'; 6 | part 'data/chart_grid_data_item.dart'; 7 | part 'settings/chart_grid_settings.dart'; 8 | part 'settings/chart_grid_settings_axis.dart'; 9 | 10 | /// This layer allows to render grids. 11 | class ChartGridLayer extends ChartLayer { 12 | /// The x axis of grid. 13 | final ChartGridData x; 14 | 15 | /// The y axis of grid. 16 | final ChartGridData y; 17 | 18 | /// The settings of grid. 19 | final ChartGridSettings settings; 20 | 21 | ChartGridLayer({ 22 | required this.settings, 23 | }) : x = settings.x.generate(), 24 | y = settings.y.generate(); 25 | 26 | /// Disposing all animations. 27 | @override 28 | void dispose() { 29 | x.dispose(); 30 | y.dispose(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/models/grid/data/chart_grid_data.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_grid_layer.dart'; 2 | 3 | /// Providing datas of the selected axis. 4 | class ChartGridData { 5 | /// The items data of grid. 6 | final List items; 7 | 8 | /// The max value in the data. 9 | final double max; 10 | 11 | /// The min value in the data. 12 | final double min; 13 | 14 | ChartGridData({ 15 | required this.items, 16 | }) : min = items.isNotEmpty 17 | ? ([...items]..sort((a, b) => a.value.compareTo(b.value))) 18 | .first 19 | .value 20 | : 0.0, 21 | max = items.isNotEmpty 22 | ? ([...items]..sort((a, b) => a.value.compareTo(b.value))) 23 | .last 24 | .value 25 | : 0.0; 26 | 27 | /// Disposing all animations. 28 | void dispose() { 29 | for (final ChartGridDataItem item in items) { 30 | item.dispose(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/models/grid/data/chart_grid_data_item.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_grid_layer.dart'; 2 | 3 | /// A collection of values for a grid in a chart. 4 | class ChartGridDataItem { 5 | /// The value of data item. 6 | final double value; 7 | 8 | final ChartColorAnimation _color; 9 | final ChartPositionAnimation _endPos; 10 | final ChartPositionAnimation _startPos; 11 | 12 | ChartGridDataItem({ 13 | required this.value, 14 | }) : _color = ChartColorAnimation(), 15 | _endPos = ChartPositionAnimation(), 16 | _startPos = ChartPositionAnimation(); 17 | 18 | /// Current color during the animation. 19 | /// 20 | /// Defaults to Colors.transparent 21 | Color get currentColor => _color.current; 22 | 23 | /// Current end position during the animation. 24 | /// 25 | /// Defaults to Offset.zero 26 | Offset get currentEndPos => _endPos.current; 27 | 28 | /// Current start position during the animation. 29 | /// 30 | /// Defaults to Offset.zero 31 | Offset get currentStartPos => _startPos.current; 32 | 33 | /// Last color on finish/stop animation. 34 | /// 35 | /// Defaults to Colors.transparent 36 | Color get lastColor => _color.last; 37 | 38 | /// Last end position on finish/stop animation. 39 | /// 40 | /// Defaults to Offset.zero 41 | Offset get lastEndPos => _endPos.last; 42 | 43 | /// Last start position on finish/stop animation. 44 | /// 45 | /// Defaults to Offset.zero 46 | Offset get lastStartPos => _startPos.last; 47 | 48 | /// Disposing all animations. 49 | void dispose() { 50 | _color.dispose(); 51 | _endPos.dispose(); 52 | _startPos.dispose(); 53 | } 54 | 55 | /// Initialize animations. 56 | void setup({ 57 | required AnimationController controller, 58 | required Color color, 59 | required Offset endPos, 60 | required Offset startPos, 61 | Color? initialColor, 62 | Offset? initialEndPos, 63 | Offset? initialStartPos, 64 | ChartGridDataItem? oldItem, 65 | }) { 66 | _color.setup( 67 | color: color, 68 | controller: controller, 69 | initialColor: initialColor, 70 | oldAnimation: oldItem?._color, 71 | ); 72 | _endPos.setup( 73 | controller: controller, 74 | initialPosition: initialEndPos, 75 | oldAnimation: oldItem?._endPos, 76 | position: endPos, 77 | ); 78 | _startPos.setup( 79 | controller: controller, 80 | initialPosition: initialStartPos, 81 | oldAnimation: oldItem?._startPos, 82 | position: startPos, 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/src/models/grid/settings/chart_grid_settings.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_grid_layer.dart'; 2 | 3 | /// A collection of values for settings in axises. 4 | class ChartGridSettings { 5 | /// The x axis of grid. 6 | final ChartGridSettingsAxis x; 7 | 8 | /// The y axis of grid. 9 | final ChartGridSettingsAxis y; 10 | 11 | const ChartGridSettings({ 12 | required this.x, 13 | required this.y, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/models/grid/settings/chart_grid_settings_axis.dart: -------------------------------------------------------------------------------- 1 | part of '../chart_grid_layer.dart'; 2 | 3 | /// A collection of values for settings of the selected axis. 4 | class ChartGridSettingsAxis { 5 | /// The color of grid in the axis. 6 | final Color color; 7 | 8 | /// The frequency line of grid in the axis. 9 | final double frequency; 10 | 11 | /// The max of the value grid in the axis. 12 | final double max; 13 | 14 | /// The min of the value grid in the axis. 15 | final double min; 16 | 17 | /// The thickness line of grid in the axis. 18 | /// 19 | /// Defaults to 1.0 20 | final double thickness; 21 | 22 | const ChartGridSettingsAxis({ 23 | required this.color, 24 | required this.frequency, 25 | required this.max, 26 | required this.min, 27 | this.thickness = 1.0, 28 | }); 29 | 30 | /// Generate all items of grid in the axis. 31 | ChartGridData generate() => ChartGridData( 32 | items: List.generate( 33 | ((max - min) ~/ frequency) + 1, 34 | (index) => ChartGridDataItem( 35 | value: index * frequency, 36 | ), 37 | ), 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/group/bar/chart_group_bar_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 2 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 3 | import 'package:mrx_charts/src/models/chart_layer.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part 'chart_group_bar_data_item.dart'; 7 | part 'chart_group_bar_settings.dart'; 8 | 9 | /// This layer allows to render group bars. 10 | class ChartGroupBarLayer extends ChartLayer { 11 | /// The items data of group bars. 12 | final List> items; 13 | 14 | /// The settings of group bars. 15 | final ChartGroupBarSettings settings; 16 | 17 | const ChartGroupBarLayer({ 18 | required this.items, 19 | required this.settings, 20 | }); 21 | 22 | /// Disposing all animations. 23 | @override 24 | void dispose() { 25 | for (final List item in items) { 26 | for (final ChartGroupBarDataItem item in item) { 27 | item.dispose(); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/models/group/bar/chart_group_bar_settings.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_group_bar_layer.dart'; 2 | 3 | /// A collection of values for settings in group bars. 4 | class ChartGroupBarSettings { 5 | /// The padding between items of group bars. 6 | /// 7 | /// Defaults to 2.0 8 | final double paddingBetweenItems; 9 | 10 | /// The radius of group bars. 11 | /// 12 | /// Defaults to BorderRadius.zero 13 | final BorderRadius radius; 14 | 15 | /// The thickness of group bars. 16 | /// 17 | /// Defaults to 4.0 18 | final double thickness; 19 | 20 | const ChartGroupBarSettings({ 21 | this.paddingBetweenItems = 2.0, 22 | this.radius = BorderRadius.zero, 23 | this.thickness = 4.0, 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/models/group/pie/chart_group_pie_data_item.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_group_pie_layer.dart'; 2 | 3 | /// A collection of values for a group pies in a chart. 4 | class ChartGroupPieDataItem extends ChartDataItem { 5 | /// The amount of data item. 6 | final double amount; 7 | 8 | /// The color of data item. 9 | final Color color; 10 | 11 | /// The label of data item. 12 | final String label; 13 | 14 | final _ChartGroupPieDataItemValue _value; 15 | 16 | ChartGroupPieDataItem({ 17 | required this.amount, 18 | required this.color, 19 | required this.label, 20 | }) : _value = _ChartGroupPieDataItemValue(); 21 | 22 | /// Current color during the animation. 23 | /// 24 | /// Defaults to Colors.transparent 25 | Color get currentValueColor => _value.currentColor; 26 | 27 | /// Current start during the animation. 28 | /// 29 | /// Defaults to 0.0 30 | double get currentValueStart => _value.currentStart; 31 | 32 | /// Current sweep during the animation. 33 | /// 34 | /// Defaults to 0.0 35 | double get currentValueSweep => _value.currentSweep; 36 | 37 | /// Last color on finish/stop animation. 38 | /// 39 | /// Defaults to Colors.transparent 40 | Color get lastValueColor => _value.lastColor; 41 | 42 | /// Last start on finish/stop animation. 43 | /// 44 | /// Defaults to 0.0 45 | double get lastValueStart => _value.lastStart; 46 | 47 | /// Last sweep on finish/stop animation. 48 | /// 49 | /// Defaults to 0.0 50 | double get lastValueSweep => _value.lastSweep; 51 | 52 | /// Disposing all animations. 53 | @override 54 | void dispose() { 55 | _value.dispose(); 56 | } 57 | 58 | /// Initialize animations. 59 | void setupValue({ 60 | required AnimationController controller, 61 | required Color color, 62 | required double startAngle, 63 | required double sweepAngle, 64 | Color? initialColor, 65 | double? initialStartAngle, 66 | double? initialSweepAngle, 67 | ChartGroupPieDataItem? oldItem, 68 | }) { 69 | _value.setup( 70 | color: color, 71 | controller: controller, 72 | initialColor: initialColor, 73 | initialStartAngle: initialStartAngle, 74 | initialSweepAngle: initialSweepAngle, 75 | oldAnimation: oldItem?._value, 76 | startAngle: startAngle, 77 | sweepAngle: sweepAngle, 78 | ); 79 | } 80 | } 81 | 82 | class _ChartGroupPieDataItemValue { 83 | final ChartColorAnimation _color; 84 | final ChartDoubleAnimation _start; 85 | final ChartDoubleAnimation _sweep; 86 | 87 | _ChartGroupPieDataItemValue() 88 | : _color = ChartColorAnimation(), 89 | _start = ChartDoubleAnimation(), 90 | _sweep = ChartDoubleAnimation(); 91 | 92 | /// Current color during the animation. 93 | /// 94 | /// Defaults to Colors.transparent 95 | Color get currentColor => _color.current; 96 | 97 | /// Current start during the animation. 98 | /// 99 | /// Defaults to 0.0 100 | double get currentStart => _start.current; 101 | 102 | /// Current sweep during the animation. 103 | /// 104 | /// Defaults to 0.0 105 | double get currentSweep => _sweep.current; 106 | 107 | /// Last color value on finish/stop animation. 108 | /// 109 | /// Defaults to Colors.transparent 110 | Color get lastColor => _color.last; 111 | 112 | /// Last double start on finish/stop animation. 113 | /// 114 | /// Defaults to 0.0 115 | double get lastStart => _start.last; 116 | 117 | /// Last double sweep on finish/stop animation. 118 | /// 119 | /// Defaults to 0.0 120 | double get lastSweep => _sweep.last; 121 | 122 | /// Disposing all animations. 123 | void dispose() { 124 | _color.dispose(); 125 | _start.dispose(); 126 | _sweep.dispose(); 127 | } 128 | 129 | /// Initialize animations. 130 | void setup({ 131 | required AnimationController controller, 132 | required Color color, 133 | required double startAngle, 134 | required double sweepAngle, 135 | Color? initialColor, 136 | double? initialStartAngle, 137 | double? initialSweepAngle, 138 | _ChartGroupPieDataItemValue? oldAnimation, 139 | }) { 140 | _color.setup( 141 | color: color, 142 | controller: controller, 143 | initialColor: initialColor, 144 | oldAnimation: oldAnimation?._color, 145 | ); 146 | _start.setup( 147 | controller: controller, 148 | curve: Curves.easeInOutExpo, 149 | initialValue: initialStartAngle, 150 | oldAnimation: oldAnimation?._start, 151 | value: startAngle, 152 | ); 153 | _sweep.setup( 154 | controller: controller, 155 | curve: Curves.easeInOutExpo, 156 | initialValue: initialSweepAngle, 157 | oldAnimation: oldAnimation?._sweep, 158 | value: sweepAngle, 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /lib/src/models/group/pie/chart_group_pie_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 2 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 3 | import 'package:mrx_charts/src/models/chart_layer.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part 'chart_group_pie_data_item.dart'; 7 | part 'chart_group_pie_settings.dart'; 8 | 9 | /// This layer allows to render group pies. 10 | class ChartGroupPieLayer extends ChartLayer { 11 | /// The items data of group pies. 12 | final List> items; 13 | 14 | /// The settings of group pies. 15 | final ChartGroupPieSettings settings; 16 | 17 | const ChartGroupPieLayer({ 18 | required this.items, 19 | required this.settings, 20 | }); 21 | 22 | /// Disposing all animations. 23 | @override 24 | void dispose() { 25 | for (final List item in items) { 26 | for (final ChartGroupPieDataItem item in item) { 27 | item.dispose(); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/models/group/pie/chart_group_pie_settings.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_group_pie_layer.dart'; 2 | 3 | /// A collection of values for settings in group pies. 4 | class ChartGroupPieSettings { 5 | /// The angle offset of group pies. 6 | /// 7 | /// Defaults to 30.0 8 | final double angleOffset; 9 | 10 | /// The gap between chart circles of group pies. 11 | /// 12 | /// Defaults to 20.0 13 | final double gapBetweenChartCircles; 14 | 15 | /// The gap sweep angle of group pies. 16 | /// 17 | /// Defaults to 10.0 18 | final double gapSweepAngle; 19 | 20 | /// The radius of group pies. 21 | /// 22 | /// Defaults to 4.0 23 | final double radius; 24 | 25 | /// The thickness of group pies. 26 | /// 27 | /// Defaults to 8.0 28 | final double thickness; 29 | 30 | const ChartGroupPieSettings({ 31 | this.angleOffset = 30.0, 32 | this.gapBetweenChartCircles = 20.0, 33 | this.gapSweepAngle = 10.0, 34 | this.radius = 4.0, 35 | this.thickness = 8.0, 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/models/highlight/chart_highlight_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/chart_layer.dart'; 2 | import 'package:mrx_charts/src/models/highlight/shape/chart_highlight_shape.dart'; 3 | 4 | /// This layer allows to render highlight. 5 | class ChartHighlightLayer extends ChartLayer { 6 | /// The function return selected shape. 7 | final ChartHighlightShape Function() shape; 8 | 9 | const ChartHighlightLayer({ 10 | required this.shape, 11 | }); 12 | 13 | /// Disposing all animations. 14 | @override 15 | void dispose() {} 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/models/highlight/shape/chart_highlight_line_shape.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_highlight_shape.dart'; 2 | 3 | /// Provides highlight line shape. 4 | class ChartHighlightLineShape 5 | extends ChartHighlightShape { 6 | /// The background color of shape. 7 | final Color backgroundColor; 8 | 9 | /// The width of shape. 10 | final double width; 11 | 12 | /// The function return current position of shape. 13 | final Offset Function(T) currentPos; 14 | 15 | /// The radius of shape. 16 | /// 17 | /// Defaults to BorderRadius.zero 18 | final BorderRadius radius; 19 | 20 | const ChartHighlightLineShape({ 21 | required this.backgroundColor, 22 | required this.currentPos, 23 | required this.width, 24 | this.radius = BorderRadius.zero, 25 | }); 26 | 27 | /// Draw highlight line shape. 28 | @override 29 | void draw(Canvas canvas, ChartPainterData painterData, 30 | ChartTouchCallbackData touchedData, double tolerance) { 31 | final T item = touchedData.selectedItem as T; 32 | final Offset currentValuePos = currentPos(item); 33 | final Offset pos = Offset( 34 | currentValuePos.dx - width / 2.0, 35 | painterData.position.dy, 36 | ); 37 | canvas.drawRRect( 38 | RRect.fromRectAndCorners( 39 | pos & Size(width, painterData.size.height), 40 | bottomLeft: radius.bottomLeft, 41 | bottomRight: radius.bottomRight, 42 | topLeft: radius.topLeft, 43 | topRight: radius.topRight, 44 | ), 45 | Paint()..color = backgroundColor, 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/models/highlight/shape/chart_highlight_shape.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 2 | import 'package:mrx_charts/src/models/chart_painter_data.dart'; 3 | import 'package:mrx_charts/src/touch/chart_touch_callback_data.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part 'chart_highlight_line_shape.dart'; 7 | 8 | /// Abstract class for hightlight shape. 9 | abstract class ChartHighlightShape { 10 | const ChartHighlightShape(); 11 | 12 | /// Draw custom shape. 13 | void draw(Canvas canvas, ChartPainterData painterData, 14 | ChartTouchCallbackData touchedData, double tolerance); 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/models/line/chart_line_data_item.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_line_layer.dart'; 2 | 3 | /// A collection of values for a line in a chart. 4 | class ChartLineDataItem extends ChartDataItem { 5 | /// The value of data item. 6 | final double value; 7 | 8 | /// The axis x of data item. 9 | final double x; 10 | 11 | final _ChartLineDataItemTouch _touch; 12 | final _ChartLineDataItemValue _value; 13 | 14 | ChartLineDataItem({ 15 | required this.value, 16 | required this.x, 17 | }) : _touch = _ChartLineDataItemTouch(), 18 | _value = _ChartLineDataItemValue(); 19 | 20 | /// Current touch area position during the animation. 21 | /// 22 | /// Defaults to Offset.zero 23 | Offset get currentTouchPos => _touch.currentPos; 24 | 25 | /// Current touch area size during the animation. 26 | /// 27 | /// Defaults to Size.zero 28 | Size get currentTouchSize => _touch.currentSize; 29 | 30 | /// Current color during the animation. 31 | /// 32 | /// Defaults to Colors.transparent 33 | Color get currentValueColor => _value.currentColor; 34 | 35 | /// Current position during the animation. 36 | /// 37 | /// Defaults to Offset.zero 38 | Offset get currentValuePos => _value.currentPos; 39 | 40 | /// Last touch area position on finish/stop animation. 41 | /// 42 | /// Defaults to Offset.zero 43 | Offset get lastTouchPos => _touch.lastPos; 44 | 45 | /// Last touch area size on finish/stop animation. 46 | /// 47 | /// Defaults to Size.zero 48 | Size get lastTouchSize => _touch.lastSize; 49 | 50 | /// Last color on finish/stop animation. 51 | /// 52 | /// Defaults to Colors.transparent 53 | Color get lastValueColor => _value.lastColor; 54 | 55 | /// Last position on finish/stop animation. 56 | /// 57 | /// Defaults to Offset.zero 58 | Offset get lastValuePos => _value.lastPos; 59 | 60 | /// Disposing all animations. 61 | @override 62 | void dispose() { 63 | _value.dispose(); 64 | } 65 | 66 | /// Initialize touch area animations. 67 | void setupTouch({ 68 | required AnimationController controller, 69 | required Offset pos, 70 | required Size size, 71 | Offset? initialPos, 72 | Size? initialSize, 73 | ChartLineDataItem? oldItem, 74 | }) { 75 | _touch.setup( 76 | controller: controller, 77 | initialPos: initialPos, 78 | initialSize: initialSize, 79 | oldValue: oldItem?._touch, 80 | pos: pos, 81 | size: size, 82 | ); 83 | } 84 | 85 | /// Initialuze value animations. 86 | void setupValue({ 87 | required AnimationController controller, 88 | required Color color, 89 | required Offset pos, 90 | Color? initialColor, 91 | Offset? initialPos, 92 | ChartLineDataItem? oldItem, 93 | }) { 94 | _value.setup( 95 | color: color, 96 | controller: controller, 97 | initialColor: initialColor, 98 | initialPos: initialPos, 99 | oldValue: oldItem?._value, 100 | pos: pos, 101 | ); 102 | } 103 | } 104 | 105 | class _ChartLineDataItemTouch { 106 | final ChartPositionAnimation _pos; 107 | final ChartSizeAnimation _size; 108 | 109 | _ChartLineDataItemTouch() 110 | : _pos = ChartPositionAnimation(), 111 | _size = ChartSizeAnimation(); 112 | 113 | /// Current position during the animation. 114 | /// 115 | /// Defaults to Offset.zero 116 | Offset get currentPos => _pos.current; 117 | 118 | /// Current size during the animation. 119 | /// 120 | /// Defaults to Size.zero 121 | Size get currentSize => _size.current; 122 | 123 | /// Last position on finish/stop animation. 124 | /// 125 | /// Defaults to Offset.zero 126 | Offset get lastPos => _pos.last; 127 | 128 | /// Last size on finish/stop animation. 129 | /// 130 | /// Defaults to Size.zero 131 | Size get lastSize => _size.last; 132 | 133 | /// Disposing all animations. 134 | void dispose() { 135 | _pos.dispose(); 136 | _size.dispose(); 137 | } 138 | 139 | /// Initialize animations. 140 | void setup({ 141 | required AnimationController controller, 142 | required Offset pos, 143 | required Size size, 144 | Offset? initialPos, 145 | Size? initialSize, 146 | _ChartLineDataItemTouch? oldValue, 147 | }) { 148 | _pos.setup( 149 | controller: controller, 150 | initialPosition: initialPos, 151 | oldAnimation: oldValue?._pos, 152 | position: pos, 153 | ); 154 | _size.setup( 155 | controller: controller, 156 | initialSize: initialSize, 157 | oldAnimation: oldValue?._size, 158 | size: size, 159 | ); 160 | } 161 | } 162 | 163 | class _ChartLineDataItemValue { 164 | final ChartColorAnimation _color; 165 | final ChartPositionAnimation _pos; 166 | 167 | _ChartLineDataItemValue() 168 | : _color = ChartColorAnimation(), 169 | _pos = ChartPositionAnimation(); 170 | 171 | /// Current color during the animation. 172 | /// 173 | /// Defaults to Colors.transparent 174 | Color get currentColor => _color.current; 175 | 176 | /// Current position during the animation. 177 | /// 178 | /// Defaults to Offset.zero 179 | Offset get currentPos => _pos.current; 180 | 181 | /// Last color on finish/stop animation. 182 | /// 183 | /// Defaults to Colors.transparent 184 | Color get lastColor => _color.last; 185 | 186 | /// Last position on finish/stop animation. 187 | /// 188 | /// Defaults to Offset.zero 189 | Offset get lastPos => _pos.last; 190 | 191 | /// Disposing all animations. 192 | void dispose() { 193 | _color.dispose(); 194 | _pos.dispose(); 195 | } 196 | 197 | /// Initialize animations. 198 | void setup({ 199 | required AnimationController controller, 200 | required Color color, 201 | required Offset pos, 202 | Color? initialColor, 203 | Offset? initialPos, 204 | _ChartLineDataItemValue? oldValue, 205 | }) { 206 | _color.setup( 207 | color: color, 208 | controller: controller, 209 | initialColor: initialColor, 210 | oldAnimation: oldValue?._color, 211 | ); 212 | _pos.setup( 213 | controller: controller, 214 | curve: Curves.easeInOut, 215 | initialPosition: initialPos, 216 | oldAnimation: oldValue?._pos, 217 | position: pos, 218 | ); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /lib/src/models/line/chart_line_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/animation/chart_animation.dart'; 2 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 3 | import 'package:mrx_charts/src/models/chart_layer.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part 'chart_line_data_item.dart'; 7 | part 'chart_line_settings.dart'; 8 | 9 | /// This layer allows to render lines. 10 | class ChartLineLayer extends ChartLayer { 11 | /// The items data of lines. 12 | final List items; 13 | 14 | /// The settings of lines. 15 | final ChartLineSettings settings; 16 | 17 | const ChartLineLayer({ 18 | required this.items, 19 | required this.settings, 20 | }); 21 | 22 | /// Disposing all animations. 23 | @override 24 | void dispose() { 25 | for (final ChartLineDataItem item in items) { 26 | item.dispose(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/line/chart_line_settings.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_line_layer.dart'; 2 | 3 | /// A collection of values for settings in lines. 4 | class ChartLineSettings { 5 | /// The color of lines. 6 | final Color color; 7 | 8 | /// The thickness of lines. 9 | final double thickness; 10 | 11 | const ChartLineSettings({ 12 | required this.color, 13 | required this.thickness, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/models/tooltip/chart_tooltip_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/chart_layer.dart'; 2 | import 'package:mrx_charts/src/models/tooltip/shape/chart_tooltip_shape.dart'; 3 | 4 | /// This layer allows to render tooltip. 5 | class ChartTooltipLayer extends ChartLayer { 6 | /// The function return selected shape. 7 | final ChartTooltipShape Function() shape; 8 | 9 | const ChartTooltipLayer({ 10 | required this.shape, 11 | }); 12 | 13 | /// Disposing all animations. 14 | @override 15 | void dispose() {} 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/models/tooltip/shape/chart_tooltip_bar_shape.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_tooltip_shape.dart'; 2 | 3 | /// Provides tooltip bar shape. 4 | class ChartTooltipBarShape extends ChartTooltipShape { 5 | /// The background color of shape. 6 | final Color backgroundColor; 7 | 8 | /// The margin bottom of shape. 9 | /// 10 | /// Defaults to 0.0 11 | final double marginBottom; 12 | 13 | /// The function return current position of shape. 14 | final Offset Function(T) currentPos; 15 | 16 | /// The function return current size of shape. 17 | final Size Function(T) currentSize; 18 | 19 | /// The function return text value of shape. 20 | final String Function(T) onTextValue; 21 | 22 | /// The padding of shape. 23 | /// 24 | /// Defaults to EdgeInsets.zero 25 | final EdgeInsets padding; 26 | 27 | /// The radius of shape. 28 | final double radius; 29 | 30 | /// The TextStyle of shape. 31 | final TextStyle textStyle; 32 | 33 | /// The triangle side length of shape. 34 | /// 35 | /// Defaults to 10.0 36 | final double triangleSideLength; 37 | 38 | const ChartTooltipBarShape({ 39 | required this.backgroundColor, 40 | required this.currentPos, 41 | required this.currentSize, 42 | required this.onTextValue, 43 | required this.textStyle, 44 | this.marginBottom = 0.0, 45 | this.padding = EdgeInsets.zero, 46 | this.radius = 0.0, 47 | this.triangleSideLength = 10.0, 48 | }); 49 | 50 | /// Draw tooltip bar shape. 51 | @override 52 | void draw(Canvas canvas, ChartPainterData painterData, 53 | ChartTouchCallbackData touchedData, double tolerance) { 54 | final T item = touchedData.selectedItem as T; 55 | final Offset currentValuePos = currentPos(item); 56 | final Size currentValueSize = currentSize(item); 57 | final Offset itemPos = Offset( 58 | currentValuePos.dx + currentValueSize.width / 2.0, currentValuePos.dy); 59 | final TextPainter textPainter = TextPainter( 60 | text: TextSpan( 61 | text: onTextValue(item), 62 | style: textStyle, 63 | ), 64 | textDirection: TextDirection.ltr, 65 | )..layout(); 66 | final Offset pos = Offset( 67 | itemPos.dx - textPainter.width / 2.0, 68 | itemPos.dy - 69 | textPainter.height - 70 | padding.vertical / 2.0 - 71 | marginBottom - 72 | triangleSideLength * 0.5, 73 | ); 74 | final Offset rectPos = Offset( 75 | pos.dx - padding.horizontal / 2.0, 76 | pos.dy - padding.vertical / 2.0, 77 | ); 78 | final Size rectSize = Size( 79 | textPainter.width + padding.horizontal, 80 | textPainter.height + padding.vertical, 81 | ); 82 | final Offset offsetRectAndText = Offset( 83 | painterData.position.dx - tolerance > rectPos.dx 84 | ? -(painterData.position.dx - tolerance - rectPos.dx) 85 | : painterData.position.dx + tolerance + painterData.size.width < 86 | rectPos.dx + rectSize.width 87 | ? -(painterData.position.dx + 88 | painterData.size.width + 89 | tolerance - 90 | rectPos.dx - 91 | rectSize.width) 92 | : 0.0, 93 | rectPos.dy < 0 ? rectPos.dy : 0.0, 94 | ); 95 | final Path rectanglePath = Path() 96 | ..addRRect( 97 | RRect.fromRectAndRadius( 98 | Offset(rectPos.dx - offsetRectAndText.dx, 99 | rectPos.dy - offsetRectAndText.dy) & 100 | rectSize, 101 | Radius.circular(radius), 102 | ), 103 | ); 104 | final Offset triangleCenterPos = Offset( 105 | rectPos.dx + rectSize.width / 2.0, 106 | rectPos.dy + rectSize.height - offsetRectAndText.dy, 107 | ); 108 | final Path trianglePath = Path() 109 | ..moveTo( 110 | triangleCenterPos.dx - triangleSideLength / 2.0, 111 | triangleCenterPos.dy - 1.0, 112 | ) 113 | ..lineTo( 114 | triangleCenterPos.dx + triangleSideLength / 2.0, 115 | triangleCenterPos.dy - 1.0, 116 | ) 117 | ..lineTo( 118 | triangleCenterPos.dx, 119 | triangleCenterPos.dy + triangleSideLength * 0.5 - 1.0, 120 | ) 121 | ..close(); 122 | canvas 123 | ..drawPath( 124 | rectanglePath, 125 | Paint()..color = backgroundColor, 126 | ) 127 | ..drawPath( 128 | trianglePath, 129 | Paint()..color = backgroundColor, 130 | ); 131 | textPainter.paint( 132 | canvas, 133 | Offset( 134 | pos.dx - offsetRectAndText.dx, 135 | pos.dy - offsetRectAndText.dy, 136 | ), 137 | ); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /lib/src/models/tooltip/shape/chart_tooltip_line_shape.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_tooltip_shape.dart'; 2 | 3 | /// Provides tooltip line shape. 4 | class ChartTooltipLineShape extends ChartTooltipShape { 5 | /// The background color of shape. 6 | final Color backgroundColor; 7 | 8 | /// The circle background color of shape. 9 | final Color circleBackgroundColor; 10 | 11 | /// The circle border background color of shape. 12 | final Color circleBorderColor; 13 | 14 | /// The circle size of shape. 15 | /// 16 | /// Defaults to 6.0 17 | final double circleSize; 18 | 19 | /// The circle border thickness of shape. 20 | /// 21 | /// Defaults to 2.0 22 | final double circleBorderThickness; 23 | 24 | /// The function return current position of shape. 25 | final Offset Function(T) currentPos; 26 | 27 | /// The margin bottom of shape. 28 | /// 29 | /// Defaults to 0.0 30 | final double marginBottom; 31 | 32 | /// The return return text value of shape. 33 | final String Function(T) onTextValue; 34 | 35 | /// The padding of shape. 36 | /// 37 | /// Defaults to EdgeInsets.zero 38 | final EdgeInsets padding; 39 | 40 | /// The radius of shape. 41 | /// 42 | /// Defaults to 0.0 43 | final double radius; 44 | 45 | /// The TextStyle of shape. 46 | final TextStyle textStyle; 47 | 48 | /// The triangle side length of shape. 49 | /// 50 | /// Defaults to 10.0 51 | final double triangleSideLength; 52 | 53 | const ChartTooltipLineShape({ 54 | required this.backgroundColor, 55 | required this.circleBackgroundColor, 56 | required this.circleBorderColor, 57 | required this.currentPos, 58 | required this.onTextValue, 59 | required this.textStyle, 60 | this.circleBorderThickness = 2.0, 61 | this.circleSize = 6.0, 62 | this.marginBottom = 0.0, 63 | this.padding = EdgeInsets.zero, 64 | this.radius = 0.0, 65 | this.triangleSideLength = 10.0, 66 | }); 67 | 68 | /// Draw tooltip line shape. 69 | @override 70 | void draw(Canvas canvas, ChartPainterData painterData, 71 | ChartTouchCallbackData touchedData, double tolerance) { 72 | final T item = touchedData.selectedItem as T; 73 | final Offset currentValuePos = currentPos(item); 74 | final Offset itemPos = Offset(currentValuePos.dx, currentValuePos.dy); 75 | final TextPainter textPainter = TextPainter( 76 | text: TextSpan( 77 | text: onTextValue(item), 78 | style: textStyle, 79 | ), 80 | textDirection: TextDirection.ltr, 81 | )..layout(); 82 | final Offset pos = Offset( 83 | itemPos.dx - textPainter.width / 2.0, 84 | itemPos.dy - 85 | textPainter.height - 86 | padding.vertical / 2.0 - 87 | (marginBottom + circleBorderThickness + circleSize) - 88 | triangleSideLength * 0.5, 89 | ); 90 | final Offset rectPos = Offset( 91 | pos.dx - padding.horizontal / 2.0, 92 | pos.dy - padding.vertical / 2.0, 93 | ); 94 | final Size rectSize = Size( 95 | textPainter.width + padding.horizontal, 96 | textPainter.height + padding.vertical, 97 | ); 98 | final Offset offsetRectAndText = Offset( 99 | painterData.position.dx - tolerance > rectPos.dx 100 | ? -(painterData.position.dx - tolerance - rectPos.dx) 101 | : painterData.position.dx + tolerance + painterData.size.width < 102 | rectPos.dx + rectSize.width 103 | ? -(painterData.position.dx + 104 | painterData.size.width + 105 | tolerance - 106 | rectPos.dx - 107 | rectSize.width) 108 | : 0.0, 109 | rectPos.dy < 0.0 110 | ? rectPos.dy - 111 | currentValuePos.dy - 112 | (marginBottom + circleBorderThickness + circleSize) - 113 | triangleSideLength * 0.5 114 | : 0.0, 115 | ); 116 | final Path rectanglePath = Path() 117 | ..addRRect( 118 | RRect.fromRectAndRadius( 119 | Offset(rectPos.dx - offsetRectAndText.dx, 120 | rectPos.dy - offsetRectAndText.dy) & 121 | rectSize, 122 | Radius.circular(radius), 123 | ), 124 | ); 125 | final Offset triangleCenterPos = Offset( 126 | rectPos.dx + rectSize.width / 2.0, 127 | rectPos.dy + rectSize.height - offsetRectAndText.dy, 128 | ); 129 | final Path trianglePath = Path(); 130 | if (rectPos.dy < 0.0) { 131 | trianglePath 132 | ..moveTo( 133 | triangleCenterPos.dx - triangleSideLength / 2.0, 134 | triangleCenterPos.dy - rectSize.height + 1.0, 135 | ) 136 | ..lineTo( 137 | triangleCenterPos.dx + triangleSideLength / 2.0, 138 | triangleCenterPos.dy - rectSize.height + 1.0, 139 | ) 140 | ..lineTo( 141 | triangleCenterPos.dx, 142 | triangleCenterPos.dy - 143 | rectSize.height - 144 | triangleSideLength * 0.5 + 145 | 1.0, 146 | ) 147 | ..close(); 148 | } else { 149 | trianglePath 150 | ..moveTo( 151 | triangleCenterPos.dx - triangleSideLength / 2.0, 152 | triangleCenterPos.dy - 1.0, 153 | ) 154 | ..lineTo( 155 | triangleCenterPos.dx + triangleSideLength / 2.0, 156 | triangleCenterPos.dy - 1.0, 157 | ) 158 | ..lineTo( 159 | triangleCenterPos.dx, 160 | triangleCenterPos.dy + triangleSideLength * 0.5 - 1.0, 161 | ) 162 | ..close(); 163 | } 164 | canvas 165 | ..drawPath( 166 | rectanglePath, 167 | Paint()..color = backgroundColor, 168 | ) 169 | ..drawPath( 170 | trianglePath, 171 | Paint()..color = backgroundColor, 172 | ); 173 | textPainter.paint( 174 | canvas, 175 | Offset( 176 | pos.dx - offsetRectAndText.dx, 177 | pos.dy - offsetRectAndText.dy, 178 | ), 179 | ); 180 | canvas 181 | ..drawCircle( 182 | currentValuePos, 183 | circleSize + circleBorderThickness, 184 | Paint()..color = circleBorderColor, 185 | ) 186 | ..drawCircle( 187 | currentValuePos, 188 | circleSize, 189 | Paint()..color = circleBackgroundColor, 190 | ); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /lib/src/models/tooltip/shape/chart_tooltip_pie_shape.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_tooltip_shape.dart'; 2 | 3 | /// Provides tooltip pie shape. 4 | class ChartTooltipPieShape extends ChartTooltipShape { 5 | /// The background color of shape. 6 | final Color backgroundColor; 7 | 8 | /// The function return text name of shape. 9 | final String Function(T) onTextName; 10 | 11 | /// The function return text value of shape. 12 | final String Function(T) onTextValue; 13 | 14 | /// The TextStyle for name of shape. 15 | final TextStyle nameTextStyle; 16 | 17 | /// The TextSty;e for value of shape. 18 | final TextStyle valueTextStyle; 19 | 20 | /// The padding of shape. 21 | /// 22 | /// Defaults to EdgeInsets.zero 23 | final EdgeInsets padding; 24 | 25 | /// The radius of shape. 26 | /// 27 | /// Defaults to 0.0 28 | final double radius; 29 | 30 | const ChartTooltipPieShape({ 31 | required this.backgroundColor, 32 | required this.nameTextStyle, 33 | required this.onTextName, 34 | required this.onTextValue, 35 | required this.valueTextStyle, 36 | this.padding = EdgeInsets.zero, 37 | this.radius = 0.0, 38 | }); 39 | 40 | /// Draw tooltip pie shape. 41 | @override 42 | void draw(Canvas canvas, ChartPainterData painterData, 43 | ChartTouchCallbackData touchedData, double tolerance) { 44 | final T item = touchedData.selectedItem as T; 45 | final TextPainter namePainter = TextPainter( 46 | text: TextSpan( 47 | text: onTextName(item), 48 | style: nameTextStyle, 49 | ), 50 | textDirection: TextDirection.ltr, 51 | )..layout(); 52 | final TextPainter valuePainter = TextPainter( 53 | text: TextSpan( 54 | text: onTextValue(item), 55 | style: valueTextStyle, 56 | ), 57 | textDirection: TextDirection.ltr, 58 | )..layout(); 59 | final Offset position = Offset( 60 | (touchedData.clickedPos?.dx ?? 0.0) - 61 | max(namePainter.width, valuePainter.width) / 2.0 - 62 | padding.horizontal / 2.0, 63 | (touchedData.clickedPos?.dy ?? 0.0) - 64 | (namePainter.height + valuePainter.height) / 2.0 - 65 | padding.vertical / 2.0, 66 | ); 67 | final Size size = Size( 68 | max(namePainter.width, valuePainter.width) + padding.horizontal, 69 | namePainter.height + valuePainter.height + padding.vertical, 70 | ); 71 | canvas.drawRRect( 72 | RRect.fromRectAndRadius( 73 | position & size, 74 | Radius.circular(radius), 75 | ), 76 | Paint()..color = backgroundColor, 77 | ); 78 | namePainter.paint( 79 | canvas, 80 | Offset( 81 | position.dx + (size.width - namePainter.width) / 2.0, 82 | position.dy + padding.top, 83 | ), 84 | ); 85 | valuePainter.paint( 86 | canvas, 87 | Offset( 88 | position.dx + (size.width - valuePainter.width) / 2.0, 89 | position.dy + namePainter.height + padding.top, 90 | ), 91 | ); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/src/models/tooltip/shape/chart_tooltip_shape.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 4 | import 'package:mrx_charts/src/models/chart_painter_data.dart'; 5 | import 'package:mrx_charts/src/touch/chart_touch_callback_data.dart'; 6 | import 'package:flutter/material.dart'; 7 | 8 | part 'chart_tooltip_bar_shape.dart'; 9 | part 'chart_tooltip_line_shape.dart'; 10 | part 'chart_tooltip_pie_shape.dart'; 11 | 12 | /// Base class for tooltip shape that allows draw custom shape. 13 | abstract class ChartTooltipShape { 14 | const ChartTooltipShape(); 15 | 16 | /// Draw custom shape. 17 | void draw(Canvas canvas, ChartPainterData painterData, 18 | ChartTouchCallbackData touchedData, double tolerance); 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/models/touchable/arc_shape.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui'; 3 | 4 | import 'package:mrx_charts/src/models/touchable/touchable_shape.dart'; 5 | 6 | /// Provides touchable arc shape. 7 | class ArcShape extends TouchableShape { 8 | static const double twoPi = 2.0 * pi; 9 | 10 | /// The center of arc. 11 | final Offset center; 12 | 13 | /// The inner radius of arc. 14 | final double innerRadius; 15 | 16 | /// The outer radius of arc. 17 | final double outerRadius; 18 | 19 | /// The start angle of arc. 20 | final double startAngle; 21 | 22 | /// The sweep angel of arc. 23 | final double sweepAngle; 24 | 25 | ArcShape({ 26 | required this.center, 27 | required this.innerRadius, 28 | required this.outerRadius, 29 | required double startAngle, 30 | required this.sweepAngle, 31 | required T data, 32 | }) : startAngle = startAngle % twoPi, 33 | super( 34 | data: data, 35 | ); 36 | 37 | /// Check arc bas been clicked. 38 | @override 39 | bool isHit(Offset offset) { 40 | final double x = offset.dx - center.dx; 41 | final double y = offset.dy - center.dy; 42 | final double radius = sqrt(x * x + y * y); 43 | final double cosine = x / radius; 44 | final double sine = y / radius; 45 | final double arcCosine = acos(cosine); 46 | final double angle = (sine >= 0) ? arcCosine : twoPi - arcCosine; 47 | if (radius < innerRadius || radius > outerRadius) { 48 | return false; 49 | } 50 | final double endAngle = startAngle + sweepAngle; 51 | if (endAngle >= twoPi) { 52 | if ((startAngle <= angle && angle < twoPi) || 53 | (0 <= angle && angle <= endAngle % twoPi)) { 54 | return true; 55 | } 56 | } else { 57 | if (startAngle <= angle && angle <= endAngle) { 58 | return true; 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | @override 65 | bool operator ==(Object other) { 66 | if (other is! ArcShape) { 67 | return false; 68 | } 69 | return center == other.center && 70 | innerRadius == other.innerRadius && 71 | outerRadius == other.outerRadius && 72 | startAngle == other.startAngle && 73 | sweepAngle == other.sweepAngle && 74 | data == other.data; 75 | } 76 | 77 | @override 78 | int get hashCode => Object.hashAll([ 79 | center, 80 | innerRadius, 81 | outerRadius, 82 | startAngle, 83 | sweepAngle, 84 | data, 85 | ]); 86 | } 87 | -------------------------------------------------------------------------------- /lib/src/models/touchable/rectangle_shape.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:mrx_charts/src/models/touchable/touchable_shape.dart'; 4 | 5 | /// Provides touchable rectangle shape. 6 | class RectangleShape extends TouchableShape { 7 | /// The position of rectangle. 8 | final Offset rectOffset; 9 | 10 | /// The size of rectangle. 11 | final Size rectSize; 12 | 13 | RectangleShape({ 14 | required this.rectOffset, 15 | required this.rectSize, 16 | required T data, 17 | }) : super( 18 | data: data, 19 | ); 20 | 21 | /// Check rectangle has been clicked. 22 | @override 23 | bool isHit(Offset offset) { 24 | return rectOffset.dx <= offset.dx && 25 | (rectOffset.dx + rectSize.width >= offset.dx) && 26 | rectOffset.dy <= offset.dy && 27 | (rectOffset.dy + rectSize.height >= offset.dy); 28 | } 29 | 30 | @override 31 | bool operator ==(Object other) { 32 | if (other is! RectangleShape) { 33 | return false; 34 | } 35 | return rectOffset == other.rectOffset && 36 | rectSize == other.rectSize && 37 | data == other.data; 38 | } 39 | 40 | @override 41 | int get hashCode => Object.hashAll([ 42 | rectOffset, 43 | rectSize, 44 | data, 45 | ]); 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/models/touchable/touchable_shape.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | /// Abstract class for touchable shape. 4 | abstract class TouchableShape { 5 | TouchableShape({ 6 | required this.data, 7 | }); 8 | 9 | /// The data of T. 10 | final T data; 11 | 12 | /// Check object has been clicked. 13 | bool isHit(Offset offset); 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/painter/chart_axis_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for axis. 4 | class _ChartAxisPainter { 5 | const _ChartAxisPainter._(); 6 | 7 | /// Draw axis. 8 | static void draw({ 9 | required Canvas canvas, 10 | required AnimationController controller, 11 | required ChartAxisLayer layer, 12 | required ChartPainterData painterDataAxisX, 13 | required ChartPainterData painterDataAxisY, 14 | ChartAxisLayer? oldLayer, 15 | }) { 16 | _drawX( 17 | canvas: canvas, 18 | controller: controller, 19 | data: layer.x, 20 | oldData: oldLayer?.x, 21 | painterData: painterDataAxisX, 22 | settings: layer.settings.x, 23 | ); 24 | _drawY( 25 | canvas: canvas, 26 | controller: controller, 27 | data: layer.y, 28 | oldData: oldLayer?.y, 29 | painterData: painterDataAxisY, 30 | settings: layer.settings.y, 31 | ); 32 | } 33 | 34 | static void _calculateX({ 35 | required AnimationController controller, 36 | required ChartAxisDataItem item, 37 | required ChartPainterData painterData, 38 | required ChartAxisSettingsAxis settings, 39 | ChartAxisDataItem? oldItem, 40 | }) { 41 | final double offsetX = painterData.size.width * 42 | (item.value - settings.min) / 43 | (settings.max - settings.min); 44 | final Offset pos = Offset( 45 | painterData.position.dx + offsetX, 46 | painterData.position.dy, 47 | ); 48 | item.setup( 49 | controller: controller, 50 | initialPos: oldItem?.lastPos ?? pos, 51 | pos: pos, 52 | initialTextStyle: oldItem?.lastTextStyle ?? 53 | settings.textStyle.copyWith( 54 | color: Colors.transparent, 55 | ), 56 | textStyle: settings.textStyle, 57 | oldItem: oldItem, 58 | ); 59 | } 60 | 61 | static void _calculateY({ 62 | required AnimationController controller, 63 | required ChartAxisDataItem item, 64 | required ChartPainterData painterData, 65 | required ChartAxisSettingsAxis settings, 66 | ChartAxisDataItem? oldItem, 67 | }) { 68 | final TextPainter textPainter = TextPainter( 69 | text: TextSpan( 70 | text: item.label, 71 | style: settings.textStyle, 72 | ), 73 | textDirection: TextDirection.ltr, 74 | )..layout(); 75 | final double diff = settings.max - settings.min; 76 | final double offsetY = painterData.size.height - 77 | painterData.size.height * (item.value - settings.min) / diff; 78 | final Offset pos = Offset( 79 | painterData.position.dx + painterData.size.width, 80 | painterData.position.dy + offsetY - textPainter.height.half, 81 | ); 82 | item.setup( 83 | controller: controller, 84 | initialPos: oldItem?.lastPos ?? pos, 85 | initialTextStyle: settings.textStyle.copyWith( 86 | color: Colors.transparent, 87 | ), 88 | oldItem: oldItem, 89 | pos: pos, 90 | textStyle: settings.textStyle, 91 | ); 92 | } 93 | 94 | static void _drawX({ 95 | required Canvas canvas, 96 | required AnimationController controller, 97 | required ChartAxisData data, 98 | required ChartPainterData painterData, 99 | required ChartAxisSettingsAxis settings, 100 | ChartAxisData? oldData, 101 | }) { 102 | for (int i = 0; i < data.items.length; i++) { 103 | final ChartAxisDataItem item = data.items[i]; 104 | _calculateX( 105 | controller: controller, 106 | item: item, 107 | oldItem: (oldData?.items)?.getOrNull(i), 108 | painterData: painterData, 109 | settings: settings, 110 | ); 111 | final TextPainter textPainter = TextPainter( 112 | text: TextSpan( 113 | text: item.label, 114 | style: item.currentTextStyle, 115 | ), 116 | textDirection: TextDirection.ltr, 117 | )..layout(); 118 | textPainter.paint( 119 | canvas, 120 | Offset( 121 | item.currentPos.dx - textPainter.width.half, 122 | item.currentPos.dy, 123 | ), 124 | ); 125 | } 126 | } 127 | 128 | static void _drawY({ 129 | required Canvas canvas, 130 | required AnimationController controller, 131 | required ChartAxisData data, 132 | required ChartPainterData painterData, 133 | required ChartAxisSettingsAxis settings, 134 | ChartAxisData? oldData, 135 | }) { 136 | for (int i = 0; i < data.items.length; i++) { 137 | final ChartAxisDataItem item = data.items[i]; 138 | _calculateY( 139 | controller: controller, 140 | item: item, 141 | oldItem: (oldData?.items)?.getOrNull(i), 142 | painterData: painterData, 143 | settings: settings, 144 | ); 145 | final textPainter = TextPainter( 146 | text: TextSpan( 147 | text: item.label, 148 | style: item.currentTextStyle, 149 | ), 150 | textDirection: TextDirection.ltr, 151 | )..layout(); 152 | textPainter.paint( 153 | canvas, 154 | Offset( 155 | item.currentPos.dx - textPainter.width, 156 | item.currentPos.dy, 157 | ), 158 | ); 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /lib/src/painter/chart_bar_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for bar. 4 | class _ChartBarPainter { 5 | const _ChartBarPainter._(); 6 | 7 | /// Draw bar. 8 | static void draw({ 9 | required Canvas canvas, 10 | required AnimationController controller, 11 | required ChartBarLayer layer, 12 | required ChartPainterData painterData, 13 | required List> touchableShapes, 14 | required ChartAxisValue xValue, 15 | required ChartAxisValue yValue, 16 | ChartBarLayer? oldLayer, 17 | }) { 18 | for (int i = 0; i < layer.items.length; i++) { 19 | final ChartBarDataItem item = layer.items[i]; 20 | _calculate( 21 | controller: controller, 22 | item: item, 23 | oldItem: (oldLayer?.items)?.getOrNull(i), 24 | painterData: painterData, 25 | settings: layer.settings, 26 | xValue: xValue, 27 | yValue: yValue, 28 | ); 29 | canvas.drawRRect( 30 | RRect.fromRectAndCorners( 31 | item.currentValuePos & item.currentValueSize, 32 | bottomLeft: layer.settings.radius.bottomLeft, 33 | bottomRight: layer.settings.radius.bottomRight, 34 | topLeft: layer.settings.radius.topLeft, 35 | topRight: layer.settings.radius.topRight, 36 | ), 37 | Paint()..color = item.currentValueColor, 38 | ); 39 | touchableShapes.add( 40 | RectangleShape( 41 | data: item, 42 | rectOffset: item.currentTouchPos, 43 | rectSize: item.currentTouchSize, 44 | ), 45 | ); 46 | } 47 | } 48 | 49 | static void _calculate({ 50 | required AnimationController controller, 51 | required ChartBarDataItem item, 52 | required ChartPainterData painterData, 53 | required ChartBarSettings settings, 54 | required ChartAxisValue xValue, 55 | required ChartAxisValue yValue, 56 | ChartBarDataItem? oldItem, 57 | }) { 58 | final double offsetX = painterData.size.width * 59 | (item.x - xValue.min) / 60 | (xValue.max - xValue.min); 61 | final Size size = Size( 62 | settings.thickness, 63 | painterData.size.height * 64 | (item.value - yValue.min) / 65 | (yValue.max - yValue.min), 66 | ); 67 | final Offset pos = Offset( 68 | painterData.position.dx + offsetX - size.width.half, 69 | painterData.position.dy + painterData.size.height - size.height, 70 | ); 71 | item.setupValue( 72 | color: item.color, 73 | controller: controller, 74 | initialColor: oldItem?.lastValueColor ?? Colors.transparent, 75 | initialPos: oldItem?.lastValuePos ?? 76 | Offset(pos.dx, painterData.position.dy + painterData.size.height), 77 | initialSize: oldItem?.lastValueSize ?? Size(size.width, 0.0), 78 | pos: pos, 79 | size: size, 80 | ); 81 | item.setupTouch( 82 | controller: controller, 83 | initialPos: 84 | oldItem?.lastValuePos ?? Offset(pos.dx, painterData.position.dy), 85 | initialSize: 86 | oldItem?.lastValueSize ?? Size(size.width, painterData.size.height), 87 | pos: Offset(pos.dx, painterData.position.dy), 88 | size: Size(size.width, painterData.size.height), 89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/src/painter/chart_candle_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for candle. 4 | class _ChartCandlePainter { 5 | const _ChartCandlePainter._(); 6 | 7 | /// Draw candle. 8 | static void draw({ 9 | required Canvas canvas, 10 | required AnimationController controller, 11 | required ChartCandleLayer layer, 12 | required ChartPainterData painterData, 13 | required ChartAxisValue xValue, 14 | required ChartAxisValue yValue, 15 | ChartCandleLayer? oldLayer, 16 | }) { 17 | for (int i = 0; i < layer.items.length; i++) { 18 | final ChartCandleDataItem item = layer.items[i]; 19 | _calculate( 20 | controller: controller, 21 | item: item, 22 | oldItem: (oldLayer?.items)?.getOrNull(i), 23 | painterData: painterData, 24 | settings: layer.settings, 25 | xValue: xValue, 26 | yValue: yValue, 27 | ); 28 | canvas 29 | ..drawRRect( 30 | RRect.fromRectAndRadius( 31 | item.value1.currentPos & item.value1.currentSize, 32 | Radius.circular(layer.settings.radius), 33 | ), 34 | Paint()..color = item.value1.currentColor, 35 | ) 36 | ..drawRRect( 37 | RRect.fromRectAndRadius( 38 | item.value2.currentPos & item.value2.currentSize, 39 | Radius.circular(layer.settings.radius), 40 | ), 41 | Paint()..color = item.value2.currentColor, 42 | ); 43 | } 44 | } 45 | 46 | static void _calculate({ 47 | required AnimationController controller, 48 | required ChartCandleDataItem item, 49 | required ChartPainterData painterData, 50 | required ChartCandleSettings settings, 51 | required ChartAxisValue xValue, 52 | required ChartAxisValue yValue, 53 | ChartCandleDataItem? oldItem, 54 | }) { 55 | final double offsetX = painterData.size.width * 56 | (item.x - xValue.min) / 57 | (xValue.max - xValue.min); 58 | final Size size1 = Size( 59 | settings.thickness, 60 | painterData.size.height * 61 | (item.value1.max - item.value1.min) / 62 | (yValue.max - yValue.min), 63 | ); 64 | final Offset pos1 = Offset( 65 | painterData.position.dx - size1.width.half + offsetX, 66 | painterData.position.dy + 67 | painterData.size.height * 68 | (yValue.max - item.value1.max) / 69 | (yValue.max - yValue.min), 70 | ); 71 | item.value1.setup( 72 | color: item.color, 73 | controller: controller, 74 | initialColor: (oldItem?.value1)?.lastColor, 75 | initialPos: (oldItem?.value1)?.lastPos ?? 76 | Offset( 77 | pos1.dx, 78 | painterData.position.dy + painterData.size.height, 79 | ), 80 | initialSize: (oldItem?.value1)?.lastSize ?? Size(size1.width, 0.0), 81 | oldItem: oldItem?.value1, 82 | pos: pos1, 83 | size: size1, 84 | ); 85 | final Size size2 = Size( 86 | 1.0, 87 | painterData.size.height * 88 | (item.value2.max - item.value2.min) / 89 | (yValue.max - yValue.min), 90 | ); 91 | final Offset pos2 = Offset( 92 | painterData.position.dx - size2.width.half + offsetX, 93 | painterData.position.dy + 94 | painterData.size.height * 95 | (yValue.max - item.value2.max) / 96 | (yValue.max - yValue.min), 97 | ); 98 | item.value2.setup( 99 | color: item.color, 100 | controller: controller, 101 | initialColor: (oldItem?.value1)?.lastColor, 102 | initialPos: (oldItem?.value2)?.lastPos ?? 103 | Offset( 104 | pos1.dx, 105 | painterData.position.dy + painterData.size.height, 106 | ), 107 | initialSize: (oldItem?.value2)?.lastSize ?? Size(size2.width, 0.0), 108 | oldItem: oldItem?.value2, 109 | pos: pos2, 110 | size: size2, 111 | ); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /lib/src/painter/chart_grid_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for grid. 4 | class _ChartGridPainter { 5 | const _ChartGridPainter._(); 6 | 7 | /// Draw grid. 8 | static void draw({ 9 | required Canvas canvas, 10 | required AnimationController controller, 11 | required ChartGridLayer layer, 12 | required ChartPainterData painterData, 13 | ChartGridLayer? oldLayer, 14 | }) { 15 | _drawX( 16 | canvas: canvas, 17 | controller: controller, 18 | data: layer.x, 19 | oldData: oldLayer?.x, 20 | painterData: painterData, 21 | settings: layer.settings.x, 22 | ); 23 | _drawY( 24 | canvas: canvas, 25 | controller: controller, 26 | data: layer.y, 27 | oldData: oldLayer?.y, 28 | painterData: painterData, 29 | settings: layer.settings.y, 30 | ); 31 | } 32 | 33 | static void _calculateX({ 34 | required AnimationController controller, 35 | required ChartGridDataItem item, 36 | required ChartPainterData painterData, 37 | required ChartGridSettingsAxis settings, 38 | ChartGridDataItem? oldItem, 39 | }) { 40 | final double offsetX = 41 | painterData.size.width * item.value / (settings.max - settings.min); 42 | final Offset startPos = Offset( 43 | painterData.position.dx + offsetX, 44 | painterData.position.dy, 45 | ); 46 | final Offset endPos = Offset( 47 | startPos.dx, 48 | painterData.position.dy + painterData.size.height, 49 | ); 50 | item.setup( 51 | color: settings.color, 52 | controller: controller, 53 | endPos: endPos, 54 | initialColor: oldItem?.lastColor, 55 | initialEndPos: oldItem?.lastEndPos ?? endPos, 56 | initialStartPos: oldItem?.lastStartPos ?? startPos, 57 | oldItem: oldItem, 58 | startPos: startPos, 59 | ); 60 | } 61 | 62 | static void _calculateY({ 63 | required AnimationController controller, 64 | required ChartGridDataItem item, 65 | required ChartPainterData painterData, 66 | required ChartGridSettingsAxis settings, 67 | ChartGridDataItem? oldItem, 68 | }) { 69 | final double offsetY = 70 | painterData.size.height * item.value / (settings.max - settings.min); 71 | final Offset startPos = Offset( 72 | painterData.position.dx, 73 | painterData.position.dy + offsetY, 74 | ); 75 | final Offset endPos = Offset( 76 | painterData.position.dx + painterData.size.width, 77 | startPos.dy, 78 | ); 79 | item.setup( 80 | color: settings.color, 81 | controller: controller, 82 | endPos: endPos, 83 | initialColor: oldItem?.lastColor, 84 | initialEndPos: oldItem?.lastEndPos ?? endPos, 85 | initialStartPos: oldItem?.lastStartPos ?? startPos, 86 | oldItem: oldItem, 87 | startPos: startPos, 88 | ); 89 | } 90 | 91 | static void _drawX({ 92 | required Canvas canvas, 93 | required AnimationController controller, 94 | required ChartGridData data, 95 | required ChartPainterData painterData, 96 | required ChartGridSettingsAxis settings, 97 | ChartGridData? oldData, 98 | }) { 99 | final Paint paint = Paint()..strokeWidth = settings.thickness; 100 | for (int i = 0; i < data.items.length; i++) { 101 | final ChartGridDataItem item = data.items[i]; 102 | _calculateX( 103 | controller: controller, 104 | item: item, 105 | oldItem: (oldData?.items)?.getOrNull(i), 106 | painterData: painterData, 107 | settings: settings, 108 | ); 109 | canvas.drawLine( 110 | item.currentStartPos, 111 | item.currentEndPos, 112 | paint..color = item.currentColor, 113 | ); 114 | } 115 | } 116 | 117 | static void _drawY({ 118 | required Canvas canvas, 119 | required AnimationController controller, 120 | required ChartGridData data, 121 | required ChartPainterData painterData, 122 | required ChartGridSettingsAxis settings, 123 | ChartGridData? oldData, 124 | }) { 125 | final Paint paint = Paint()..strokeWidth = settings.thickness; 126 | for (int i = 0; i < data.items.length; i++) { 127 | final ChartGridDataItem item = data.items[i]; 128 | _calculateY( 129 | controller: controller, 130 | item: item, 131 | oldItem: (oldData?.items)?.getOrNull(i), 132 | painterData: painterData, 133 | settings: settings, 134 | ); 135 | canvas.drawLine( 136 | item.currentStartPos, 137 | item.currentEndPos, 138 | paint..color = item.currentColor, 139 | ); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /lib/src/painter/chart_group_bar_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for group bar. 4 | class _ChartGroupBarPainter { 5 | const _ChartGroupBarPainter._(); 6 | 7 | /// Draw group bar. 8 | static void draw({ 9 | required Canvas canvas, 10 | required AnimationController controller, 11 | required ChartGroupBarLayer layer, 12 | required ChartPainterData painterData, 13 | required List> touchableShapes, 14 | required ChartAxisValue xValue, 15 | required ChartAxisValue yValue, 16 | ChartGroupBarLayer? oldLayer, 17 | }) { 18 | for (int i = 0; i < layer.items.length; i++) { 19 | for (int j = 0; j < layer.items[i].length; j++) { 20 | final ChartGroupBarDataItem item = layer.items[i][j]; 21 | _calculate( 22 | controller: controller, 23 | currentIndex: j + 1, 24 | item: item, 25 | maxIndex: layer.items[i].length, 26 | oldItem: (oldLayer?.items)?.getOrNull(i)?.getOrNull(j), 27 | painterData: painterData, 28 | settings: layer.settings, 29 | xValue: xValue, 30 | yValue: yValue, 31 | ); 32 | canvas.drawRRect( 33 | RRect.fromRectAndCorners( 34 | item.currentValuePos & item.currentValueSize, 35 | bottomLeft: layer.settings.radius.bottomLeft, 36 | bottomRight: layer.settings.radius.bottomRight, 37 | topLeft: layer.settings.radius.topLeft, 38 | topRight: layer.settings.radius.topRight, 39 | ), 40 | Paint()..color = item.currentValueColor, 41 | ); 42 | } 43 | } 44 | final double v1 = 45 | ((layer.items.getOrNull(1)?.firstOrNull)?.currentValuePos)?.dx ?? 0.0; 46 | final double v2 = 47 | ((layer.items.firstOrNull?.lastOrNull)?.currentValuePos)?.dx ?? 0.0; 48 | final double weight = (max(v1, v2) - min(v1, v2)).half * 0.7; 49 | for (int i = 0; i < layer.items.length; i++) { 50 | for (int j = 0; j < layer.items[i].length; j++) { 51 | final ChartGroupBarDataItem item = layer.items[i][j]; 52 | _calculateTouch( 53 | controller: controller, 54 | innerCurrentIndex: j, 55 | innerMaxIndex: layer.items[i].length, 56 | item: item, 57 | mainCurrentIndex: i, 58 | mainMaxIndex: layer.items.length, 59 | painterData: painterData, 60 | settings: layer.settings, 61 | weight: weight, 62 | xValue: xValue, 63 | yValue: yValue, 64 | ); 65 | touchableShapes.add( 66 | RectangleShape( 67 | data: item, 68 | rectOffset: item.currentTouchPos, 69 | rectSize: item.currentTouchSize, 70 | ), 71 | ); 72 | } 73 | } 74 | } 75 | 76 | static void _calculate({ 77 | required AnimationController controller, 78 | required int currentIndex, 79 | required ChartGroupBarDataItem item, 80 | required int maxIndex, 81 | required ChartPainterData painterData, 82 | required ChartGroupBarSettings settings, 83 | required ChartAxisValue xValue, 84 | required ChartAxisValue yValue, 85 | ChartGroupBarDataItem? oldItem, 86 | }) { 87 | final double offsetX = painterData.size.width * 88 | (item.x - xValue.min) / 89 | (xValue.max - xValue.min); 90 | final Size size = Size( 91 | settings.thickness, 92 | painterData.size.height * 93 | (item.value - yValue.min) / 94 | (yValue.max - yValue.min), 95 | ); 96 | final double groupWidth = maxIndex * settings.thickness + 97 | (maxIndex - 1) * settings.paddingBetweenItems; 98 | final Offset pos = Offset( 99 | painterData.position.dx + 100 | offsetX - 101 | (maxIndex - currentIndex + 1) * settings.thickness - 102 | (maxIndex - currentIndex) * settings.paddingBetweenItems + 103 | groupWidth.half, 104 | painterData.position.dy + painterData.size.height - size.height, 105 | ); 106 | item.setupValue( 107 | color: item.color, 108 | controller: controller, 109 | initialColor: oldItem?.lastValueColor ?? Colors.transparent, 110 | initialPos: oldItem?.lastValuePos ?? 111 | Offset(pos.dx, painterData.position.dy + painterData.size.height), 112 | initialSize: oldItem?.lastValueSize ?? Size(size.width, 0.0), 113 | oldItem: oldItem, 114 | pos: pos, 115 | size: size, 116 | ); 117 | } 118 | 119 | static void _calculateTouch({ 120 | required AnimationController controller, 121 | required int innerCurrentIndex, 122 | required int innerMaxIndex, 123 | required ChartGroupBarDataItem item, 124 | required int mainCurrentIndex, 125 | required int mainMaxIndex, 126 | required ChartPainterData painterData, 127 | required ChartGroupBarSettings settings, 128 | required double weight, 129 | required ChartAxisValue xValue, 130 | required ChartAxisValue yValue, 131 | ChartGroupBarDataItem? oldItem, 132 | }) { 133 | final double extraWidth = ((mainCurrentIndex == 0 && 134 | innerCurrentIndex == 0) || 135 | (mainCurrentIndex == mainMaxIndex - 1 && 136 | innerCurrentIndex == innerMaxIndex - 1) 137 | ? 0.0 138 | : ((innerCurrentIndex == 0 || innerCurrentIndex == innerMaxIndex - 1) 139 | ? weight 140 | : 0.0)); 141 | final Size size = Size( 142 | settings.thickness + extraWidth, 143 | painterData.size.height, 144 | ); 145 | final Offset pos = Offset( 146 | item.currentValuePos.dx + 147 | (innerCurrentIndex == 0 ? (-size.width + settings.thickness) : 0.0), 148 | painterData.position.dy, 149 | ); 150 | item.setupTouch( 151 | controller: controller, 152 | initialPos: oldItem?.lastTouchPos ?? pos, 153 | initialSize: oldItem?.lastTouchSize ?? size, 154 | oldItem: oldItem, 155 | pos: pos, 156 | size: size, 157 | ); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /lib/src/painter/chart_group_pie_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for group pie. 4 | class _ChartGroupPiePainter { 5 | const _ChartGroupPiePainter._(); 6 | 7 | static double _sliceCursor = 0.0; 8 | 9 | /// Draw group pie. 10 | static void draw({ 11 | required Canvas canvas, 12 | required AnimationController controller, 13 | required ChartGroupPieLayer layer, 14 | required ChartPainterData painterData, 15 | required List> touchableShapes, 16 | ChartGroupPieLayer? oldLayer, 17 | }) { 18 | _sliceCursor = 0.0; 19 | final double radius = painterData.size.height * .35; 20 | final double centerX = painterData.size.width.half; 21 | final double centerY = painterData.size.height.half; 22 | final Paint paint = Paint() 23 | ..style = PaintingStyle.stroke 24 | ..strokeCap = StrokeCap.round 25 | ..strokeWidth = layer.settings.thickness; 26 | for (int i = 0; i < layer.items.length; i++) { 27 | final List items = layer.items[i]; 28 | final double gapSweepSize = 29 | items.length < 2 ? 0.0 : layer.settings.gapSweepAngle * items.length; 30 | final double sliceSweepTotal = 360.0 - gapSweepSize; 31 | final double total = items.map((e) => e.amount).sum; 32 | _sliceCursor = 33 | layer.settings.angleOffset + layer.settings.gapSweepAngle.half; 34 | final double itemRadius = 35 | radius + i * layer.settings.gapBetweenChartCircles; 36 | final Rect rect = Rect.fromCircle( 37 | center: Offset(centerX, centerY), 38 | radius: itemRadius, 39 | ); 40 | for (int j = 0; j < items.length; j++) { 41 | final ChartGroupPieDataItem item = items[j]; 42 | _calculate( 43 | controller: controller, 44 | gapSweepAngle: layer.settings.gapSweepAngle, 45 | item: item, 46 | oldItem: (oldLayer?.items)?.getOrNull(i)?.getOrNull(j), 47 | sliceCursor: _sliceCursor, 48 | sliceSweepTotal: sliceSweepTotal, 49 | total: total, 50 | ); 51 | canvas.drawArc( 52 | rect, 53 | item.currentValueStart, 54 | item.currentValueSweep, 55 | false, 56 | paint..color = item.currentValueColor, 57 | ); 58 | const double twoPi = 2.0 * pi; 59 | final double circumference = itemRadius * twoPi; 60 | final double strokeAngle = 61 | twoPi * layer.settings.thickness / circumference; 62 | touchableShapes.add( 63 | ArcShape( 64 | center: rect.center, 65 | innerRadius: itemRadius - layer.settings.thickness, 66 | outerRadius: itemRadius + layer.settings.thickness, 67 | startAngle: item.currentValueStart - strokeAngle, 68 | sweepAngle: item.currentValueSweep + 2.0 * strokeAngle, 69 | data: item, 70 | ), 71 | ); 72 | } 73 | } 74 | } 75 | 76 | static void _calculate({ 77 | required AnimationController controller, 78 | required double gapSweepAngle, 79 | required ChartGroupPieDataItem item, 80 | required double sliceCursor, 81 | required double sliceSweepTotal, 82 | required double total, 83 | ChartGroupPieDataItem? oldItem, 84 | }) { 85 | final double slicePercentage = item.amount * 100.0 / total; 86 | final double currentSweepDegree = slicePercentage * sliceSweepTotal / 100.0; 87 | item.setupValue( 88 | color: item.color, 89 | controller: controller, 90 | initialColor: oldItem?.lastValueColor, 91 | initialSweepAngle: oldItem?.lastValueSweep, 92 | initialStartAngle: oldItem?.lastValueStart != null 93 | ? _degreeToRad(_radToDegree(oldItem?.lastValueStart ?? 0.0) - 360.0) 94 | : 0.0, 95 | startAngle: _degreeToRad(sliceCursor + 360.0), 96 | sweepAngle: _degreeToRad(currentSweepDegree), 97 | ); 98 | _sliceCursor += currentSweepDegree + gapSweepAngle; 99 | } 100 | 101 | static double _degreeToRad(double degree) => degree * pi / 180.0; 102 | 103 | static double _radToDegree(double rad) => rad * 180.0 / pi; 104 | } 105 | -------------------------------------------------------------------------------- /lib/src/painter/chart_highlight_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for highlight. 4 | class _ChartHighlightPainter { 5 | const _ChartHighlightPainter._(); 6 | 7 | /// Draw highlight shape. 8 | static void draw({ 9 | required Canvas canvas, 10 | required ChartHighlightLayer layer, 11 | required ChartPainterData painterData, 12 | required double tolerance, 13 | required ChartTouchCallbackData touchedData, 14 | }) { 15 | final ChartHighlightShape shape = layer.shape(); 16 | shape.draw(canvas, painterData, touchedData, tolerance); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/painter/chart_line_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for line. 4 | class _ChartLinePainter { 5 | const _ChartLinePainter._(); 6 | 7 | /// Draw line. 8 | static void draw({ 9 | required Canvas canvas, 10 | required AnimationController controller, 11 | required ChartLineLayer layer, 12 | required ChartPainterData painterData, 13 | required List> touchableShapes, 14 | required ChartAxisValue xValue, 15 | required ChartAxisValue yValue, 16 | ChartLineLayer? oldLayer, 17 | }) { 18 | for (int i = 0; i < layer.items.length; i++) { 19 | final ChartLineDataItem item = layer.items[i]; 20 | _calculate( 21 | controller: controller, 22 | item: item, 23 | oldItem: (oldLayer?.items)?.getOrNull(i), 24 | oldLayer: oldLayer, 25 | painterData: painterData, 26 | settings: layer.settings, 27 | xValue: xValue, 28 | yValue: yValue, 29 | ); 30 | } 31 | _draw( 32 | canvas: canvas, 33 | layer: layer, 34 | ); 35 | final double v1 = (layer.items.getOrNull(1)?.currentValuePos)?.dx ?? 0.0; 36 | final double v2 = (layer.items.firstOrNull?.currentValuePos)?.dx ?? 0.0; 37 | final double weight = (max(v1, v2) - min(v1, v2)) * 0.9; 38 | for (int i = 0; i < layer.items.length; i++) { 39 | final ChartLineDataItem item = layer.items[i]; 40 | _calculateTouch( 41 | controller: controller, 42 | item: item, 43 | oldItem: (oldLayer?.items)?.getOrNull(i), 44 | painterData: painterData, 45 | weight: weight, 46 | ); 47 | touchableShapes.add( 48 | RectangleShape( 49 | data: item, 50 | rectOffset: item.currentTouchPos, 51 | rectSize: item.currentTouchSize, 52 | ), 53 | ); 54 | } 55 | } 56 | 57 | static void _calculate({ 58 | required AnimationController controller, 59 | required ChartLineDataItem item, 60 | required ChartPainterData painterData, 61 | required ChartLineSettings settings, 62 | required ChartAxisValue xValue, 63 | required ChartAxisValue yValue, 64 | ChartLineLayer? oldLayer, 65 | ChartLineDataItem? oldItem, 66 | }) { 67 | final double offsetX = painterData.size.width * 68 | (item.x - xValue.min) / 69 | (xValue.max - xValue.min); 70 | final Offset pos = Offset( 71 | painterData.position.dx + offsetX, 72 | painterData.position.dy + 73 | painterData.size.height - 74 | (painterData.size.height * 75 | (item.value - yValue.min) / 76 | (yValue.max - yValue.min)), 77 | ); 78 | final ChartLineDataItem? oldItemLast = (oldLayer?.items)?.lastOrNull; 79 | item.setupValue( 80 | controller: controller, 81 | color: settings.color, 82 | initialColor: oldItem?.lastValueColor ?? Colors.transparent, 83 | initialPos: oldItem?.lastValuePos ?? 84 | (oldItemLast != null 85 | ? Offset(painterData.position.dx + painterData.size.width, 86 | oldItemLast.lastValuePos.dy) 87 | : Offset( 88 | pos.dx, painterData.position.dy + painterData.size.height)), 89 | pos: pos, 90 | oldItem: oldItem, 91 | ); 92 | } 93 | 94 | static void _calculateTouch({ 95 | required AnimationController controller, 96 | required ChartLineDataItem item, 97 | required ChartPainterData painterData, 98 | required double weight, 99 | ChartLineDataItem? oldItem, 100 | }) { 101 | final Size size = Size( 102 | weight, 103 | painterData.size.height, 104 | ); 105 | final Offset pos = Offset( 106 | item.currentValuePos.dx - weight.half, 107 | painterData.position.dy, 108 | ); 109 | item.setupTouch( 110 | controller: controller, 111 | initialPos: oldItem?.lastTouchPos ?? pos, 112 | initialSize: oldItem?.lastTouchSize ?? size, 113 | oldItem: oldItem, 114 | pos: pos, 115 | size: size, 116 | ); 117 | } 118 | 119 | static void _draw({ 120 | required Canvas canvas, 121 | required ChartLineLayer layer, 122 | }) { 123 | final Path curvePath = Path(); 124 | final Paint paint = Paint() 125 | ..strokeWidth = layer.settings.thickness 126 | ..style = PaintingStyle.stroke 127 | ..color = layer.settings.color; 128 | late Offset previousPos; 129 | for (int i = 0; i < layer.items.length; i++) { 130 | final ChartLineDataItem lineItem = layer.items[i]; 131 | final Offset currentPos = lineItem.currentValuePos; 132 | if (i < 1) { 133 | curvePath.moveTo(currentPos.dx, currentPos.dy); 134 | } else { 135 | final Offset controlPos = Offset( 136 | previousPos.dx + (currentPos.dx - previousPos.dx).half, 137 | previousPos.dy, 138 | ); 139 | final Offset controlPos2 = Offset( 140 | currentPos.dx + (previousPos.dx - currentPos.dx).half, 141 | currentPos.dy, 142 | ); 143 | curvePath.cubicTo( 144 | controlPos.dx, 145 | controlPos.dy, 146 | controlPos2.dx, 147 | controlPos2.dy, 148 | currentPos.dx, 149 | currentPos.dy, 150 | ); 151 | } 152 | previousPos = currentPos; 153 | } 154 | canvas.drawPath( 155 | curvePath, 156 | paint 157 | ..color = 158 | layer.items.firstOrNull?.currentValueColor ?? Colors.transparent, 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /lib/src/painter/chart_tooltip_painter.dart: -------------------------------------------------------------------------------- 1 | part of 'chart_painter.dart'; 2 | 3 | /// Layer painter for tooltip. 4 | class _ChartTooltipPainter { 5 | const _ChartTooltipPainter._(); 6 | 7 | /// Draw tooltip shape. 8 | static void draw({ 9 | required Canvas canvas, 10 | required ChartTooltipLayer layer, 11 | required ChartPainterData painterData, 12 | required double tolerance, 13 | required ChartTouchCallbackData touchedData, 14 | }) { 15 | final ChartTooltipShape shape = layer.shape(); 16 | shape.draw(canvas, painterData, touchedData, tolerance); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/touch/chart_touch_callback_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/chart_data_item.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Provides callback touched data. 5 | class ChartTouchCallbackData { 6 | /// The last position has been clicked. 7 | final Offset? clickedPos; 8 | 9 | /// The last item has been clicked. 10 | final ChartDataItem selectedItem; 11 | 12 | const ChartTouchCallbackData({ 13 | required this.selectedItem, 14 | this.clickedPos, 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/touch/chart_touch_detector.dart: -------------------------------------------------------------------------------- 1 | import 'package:mrx_charts/src/models/touchable/touchable_shape.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | 4 | /// Provides touch detector. 5 | class ChartTouchDetector extends StatelessWidget { 6 | final Widget? child; 7 | 8 | /// The function reacted by tap on widget. 9 | final void Function(Offset touchPosition, T? data)? onTap; 10 | 11 | /// The list of shapes. 12 | final List>? shapes; 13 | 14 | /// The function return list of shapes. 15 | final List> Function() onShapes; 16 | 17 | const ChartTouchDetector({ 18 | required this.onShapes, 19 | this.child, 20 | this.onTap, 21 | this.shapes, 22 | Key? key, 23 | }) : super(key: key); 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return GestureDetector( 28 | onTapUp: (TapUpDetails tapUpDetails) { 29 | if (onTap == null) { 30 | return; 31 | } 32 | for (final TouchableShape shape in onShapes()) { 33 | if (shape.isHit(tapUpDetails.localPosition)) { 34 | onTap?.call(tapUpDetails.localPosition, shape.data); 35 | return; 36 | } 37 | } 38 | onTap?.call(tapUpDetails.localPosition, null); 39 | }, 40 | child: child, 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: mrx_charts 2 | description: Simple, high-performance Flutter charts with beautiful animations. 3 | version: 0.1.3 4 | repository: https://github.com/merixstudio/mrx-flutter-charts 5 | issue_tracker: https://github.com/merixstudio/mrx-flutter-charts/issues 6 | homepage: 7 | 8 | environment: 9 | sdk: ">=2.16.1 <3.0.0" 10 | flutter: ">=1.17.0" 11 | 12 | dependencies: 13 | flutter: 14 | sdk: flutter 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | flutter_lints: ^1.0.0 20 | 21 | flutter: -------------------------------------------------------------------------------- /screenshots/chart_bar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/screenshots/chart_bar.gif -------------------------------------------------------------------------------- /screenshots/chart_candle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/screenshots/chart_candle.gif -------------------------------------------------------------------------------- /screenshots/chart_group_bar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/screenshots/chart_group_bar.gif -------------------------------------------------------------------------------- /screenshots/chart_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/screenshots/chart_line.gif -------------------------------------------------------------------------------- /screenshots/chart_pie.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merixstudio/mrx-flutter-charts/9e1c63e8655ece160ca9b7347724b741d4e449f0/screenshots/chart_pie.gif --------------------------------------------------------------------------------