display dashed graph
This commit is contained in:
parent
12f41cad55
commit
6475847cb0
2
android/local.properties
Normal file
2
android/local.properties
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
sdk.dir=/Users/aksel/Library/Android/sdk
|
||||||
|
flutter.sdk=/Users/aksel/development/flutter
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:real_time_chart/real_time_chart.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
@ -29,39 +30,44 @@ class MyHomePage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
int _counter = 0;
|
|
||||||
|
|
||||||
void _incrementCounter() {
|
|
||||||
setState(() {
|
|
||||||
_counter++;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(widget.title),
|
title: Text(widget.title),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Container(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
color: Colors.red,
|
||||||
children: <Widget>[
|
width: MediaQuery.of(context).size.width,
|
||||||
const Text(
|
height: MediaQuery.of(context).size.width,
|
||||||
'You have pushed the button this many times:',
|
child: RealTimeGraph(
|
||||||
),
|
key: const Key('LiveGraph'),
|
||||||
Text(
|
stream: getDataStream(),
|
||||||
'$_counter',
|
),
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: _incrementCounter,
|
|
||||||
tooltip: 'Increment',
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
bool up = true;
|
||||||
|
|
||||||
|
Stream<double> getDataStream() {
|
||||||
|
return Stream.periodic(const Duration(milliseconds: 10), (_) {
|
||||||
|
if (count >= 100) {
|
||||||
|
up = false;
|
||||||
|
} else if (count <= 0) {
|
||||||
|
up = true;
|
||||||
|
}
|
||||||
|
if (up) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count * 1.0;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,13 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.8.2"
|
||||||
|
real_time_chart:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: ".."
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "0.0.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -186,3 +193,4 @@ packages:
|
|||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.19.2 <3.0.0"
|
dart: ">=2.19.2 <3.0.0"
|
||||||
|
flutter: ">=1.17.0"
|
||||||
|
@ -1,90 +1,28 @@
|
|||||||
name: example
|
name: example
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
# The following line prevents the package from being accidentally published to
|
publish_to: 'none'
|
||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|
||||||
|
|
||||||
# The following defines the version and build number for your application.
|
|
||||||
# A version number is three numbers separated by dots, like 1.2.43
|
|
||||||
# followed by an optional build number separated by a +.
|
|
||||||
# Both the version and the builder number may be overridden in flutter
|
|
||||||
# build by specifying --build-name and --build-number, respectively.
|
|
||||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
|
||||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
|
||||||
# Read more about iOS versioning at
|
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
|
||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.19.2 <3.0.0'
|
sdk: '>=2.19.2 <3.0.0'
|
||||||
|
|
||||||
# Dependencies specify other packages that your package needs in order to work.
|
|
||||||
# To automatically upgrade your package dependencies to the latest versions
|
|
||||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
|
||||||
# dependencies can be manually updated by changing the version numbers below to
|
|
||||||
# the latest version available on pub.dev. To see which dependencies have newer
|
|
||||||
# versions available, run `flutter pub outdated`.
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
|
real_time_chart:
|
||||||
|
path: ../
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
# The "flutter_lints" package below contains a set of recommended lints to
|
|
||||||
# encourage good coding practices. The lint set provided by the package is
|
|
||||||
# activated in the `analysis_options.yaml` file located at the root of your
|
|
||||||
# package. See that file for information about deactivating specific lint
|
|
||||||
# rules and activating additional ones.
|
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
|
||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
# The following line ensures that the Material Icons font is
|
|
||||||
# included with your application, so that you can use the icons in
|
|
||||||
# the material Icons class.
|
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
|
||||||
# assets:
|
|
||||||
# - images/a_dot_burr.jpeg
|
|
||||||
# - images/a_dot_ham.jpeg
|
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
|
||||||
|
|
||||||
# For details regarding adding assets from package dependencies, see
|
|
||||||
# https://flutter.dev/assets-and-images/#from-packages
|
|
||||||
|
|
||||||
# To add custom fonts to your application, add a fonts section here,
|
|
||||||
# in this "flutter" section. Each entry in this list should have a
|
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
|
||||||
# list giving the asset and other descriptors for the font. For
|
|
||||||
# example:
|
|
||||||
# fonts:
|
|
||||||
# - family: Schyler
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/Schyler-Regular.ttf
|
|
||||||
# - asset: fonts/Schyler-Italic.ttf
|
|
||||||
# style: italic
|
|
||||||
# - family: Trajan Pro
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/TrajanPro.ttf
|
|
||||||
# - asset: fonts/TrajanPro_Bold.ttf
|
|
||||||
# weight: 700
|
|
||||||
#
|
|
||||||
# For details regarding fonts from package dependencies,
|
|
||||||
# see https://flutter.dev/custom-fonts/#from-packages
|
|
||||||
|
14
ios/Flutter/Generated.xcconfig
Normal file
14
ios/Flutter/Generated.xcconfig
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// This is a generated file; do not edit or check into version control.
|
||||||
|
FLUTTER_ROOT=/Users/aksel/development/flutter
|
||||||
|
FLUTTER_APPLICATION_PATH=/Users/aksel/Documents/GitHub/real_time_chart
|
||||||
|
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||||
|
FLUTTER_TARGET=lib/main.dart
|
||||||
|
FLUTTER_BUILD_DIR=build
|
||||||
|
FLUTTER_BUILD_NAME=0.0.1
|
||||||
|
FLUTTER_BUILD_NUMBER=0.0.1
|
||||||
|
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||||
|
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
|
||||||
|
DART_OBFUSCATION=false
|
||||||
|
TRACK_WIDGET_CREATION=true
|
||||||
|
TREE_SHAKE_ICONS=false
|
||||||
|
PACKAGE_CONFIG=.dart_tool/package_config.json
|
13
ios/Flutter/flutter_export_environment.sh
Executable file
13
ios/Flutter/flutter_export_environment.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# This is a generated file; do not edit or check into version control.
|
||||||
|
export "FLUTTER_ROOT=/Users/aksel/development/flutter"
|
||||||
|
export "FLUTTER_APPLICATION_PATH=/Users/aksel/Documents/GitHub/real_time_chart"
|
||||||
|
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||||
|
export "FLUTTER_TARGET=lib/main.dart"
|
||||||
|
export "FLUTTER_BUILD_DIR=build"
|
||||||
|
export "FLUTTER_BUILD_NAME=0.0.1"
|
||||||
|
export "FLUTTER_BUILD_NUMBER=0.0.1"
|
||||||
|
export "DART_OBFUSCATION=false"
|
||||||
|
export "TRACK_WIDGET_CREATION=true"
|
||||||
|
export "TREE_SHAKE_ICONS=false"
|
||||||
|
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
@ -1,7 +1,4 @@
|
|||||||
library real_time_chart;
|
library real_time_chart;
|
||||||
|
|
||||||
/// A Calculator.
|
export 'src/point.dart';
|
||||||
class Calculator {
|
export 'src/live_chart.dart';
|
||||||
/// Returns [value] plus 1.
|
|
||||||
int addOne(int value) => value + 1;
|
|
||||||
}
|
|
123
lib/src/live_chart.dart
Normal file
123
lib/src/live_chart.dart
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'point.dart';
|
||||||
|
|
||||||
|
class RealTimeGraph extends StatefulWidget {
|
||||||
|
final Stream<double> stream;
|
||||||
|
|
||||||
|
const RealTimeGraph({Key? key, required this.stream}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
RealTimeGraphState createState() => RealTimeGraphState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class RealTimeGraphState extends State<RealTimeGraph>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
StreamSubscription<double>? streamSubscription;
|
||||||
|
List<Point<double>> _data = [];
|
||||||
|
Timer? timer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
// Subscribe to the stream provided in the constructor
|
||||||
|
streamSubscription = widget.stream.listen(_listener);
|
||||||
|
|
||||||
|
// Start a periodic timer to update the data for visualization
|
||||||
|
timer = Timer.periodic(const Duration(milliseconds: 50), (_) {
|
||||||
|
//_data.removeWhere((element) => element.y > 100);
|
||||||
|
|
||||||
|
// Clone the data to avoid modifying the original list while iterating
|
||||||
|
List<Point<double>> data = _data.map((e) => e).toList();
|
||||||
|
|
||||||
|
// Increment the x value of each data point
|
||||||
|
for (var element in data) {
|
||||||
|
element.x = element.x - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger a rebuild with the updated data
|
||||||
|
setState(() {
|
||||||
|
_data = data;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
if (!constraints.maxWidth.isFinite || !constraints.maxHeight.isFinite) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
key: Key('${constraints.maxWidth}${constraints.maxHeight}'),
|
||||||
|
height: constraints.maxWidth,
|
||||||
|
width: constraints.maxHeight,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: _GraphPainter(data: _data),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _listener(double data) {
|
||||||
|
// Insert the new data point in the beginning of the list
|
||||||
|
_data.insert(0, Point(0, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// Clean up resources when the widget is removed from the tree
|
||||||
|
streamSubscription?.cancel();
|
||||||
|
timer?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GraphPainter extends CustomPainter {
|
||||||
|
final List<Point<double>> data;
|
||||||
|
|
||||||
|
_GraphPainter({required this.data});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final paint = Paint()
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1.5
|
||||||
|
..color = Colors.white;
|
||||||
|
List<Offset> points = [];
|
||||||
|
|
||||||
|
// Iterate over the data points and add intermediate points if necessary
|
||||||
|
for (int i = 0; i < data.length - 1; i++) {
|
||||||
|
double y1 = size.height - data[i].y;
|
||||||
|
double x1 = data[i].x + size.width;
|
||||||
|
double y2 = size.height - data[i + 1].y;
|
||||||
|
double x2 = data[i + 1].x + size.width;
|
||||||
|
double yDiff = y1 - y2;
|
||||||
|
double xDiff = x1 - x2;
|
||||||
|
|
||||||
|
// If the difference in y values is small, add intermediate points
|
||||||
|
if (xDiff.abs() <= 10) {
|
||||||
|
int numOfIntermediatePoints = (xDiff / 2).round();
|
||||||
|
double yInterval = yDiff / numOfIntermediatePoints;
|
||||||
|
double xInterval = xDiff / numOfIntermediatePoints;
|
||||||
|
for (int j = 1; j <= numOfIntermediatePoints; j++) {
|
||||||
|
double intermediateY = y1 + yInterval * j;
|
||||||
|
double intermediateX = x1 + xInterval * j;
|
||||||
|
points.add(Offset(intermediateX, intermediateY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawPoints(PointMode.points, points, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => true;
|
||||||
|
}
|
16
lib/src/point.dart
Normal file
16
lib/src/point.dart
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
class Point<T extends num> {
|
||||||
|
T x;
|
||||||
|
T y;
|
||||||
|
|
||||||
|
Point(this.x, this.y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Point{x: $x, y: $y}';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user