Commit 422b5d5
Changed files (2)
app
lib
features
statistics
screens
app/lib/features/statistics/value_graph.dart
@@ -3,6 +3,7 @@ import 'dart:ui' as ui;
import 'package:blood_pressure_app/model/horizontal_graph_line.dart';
import 'package:blood_pressure_app/model/storage/storage.dart';
+import 'package:blood_pressure_app/screens/loading_screen.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:health_data_store/health_data_store.dart';
@@ -24,6 +25,7 @@ class Tmp extends StatelessWidget {
width: 1000,
child: BloodPressureValueGraph(
settings: Settings(
+ animationSpeed: 1000,
/*drawRegressionLines: true,
horizontalGraphLines: [
HorizontalGraphLine(Colors.blue, 117),
@@ -62,12 +64,9 @@ class BloodPressureValueGraph extends StatelessWidget {
required this.records,
required this.colors,
}): assert(records.sysGraph().length >= 2
- || records.diaGraph().length >= 2
- || records.pulGraph().length >= 2),
- assert(records.isSorted((a, b) => a.time.compareTo(b.time)));
-
- // TODO Add new feature:
- // - load lines animation
+ || records.diaGraph().length >= 2
+ || records.pulGraph().length >= 2),
+ assert(records.isSorted((a, b) => a.time.compareTo(b.time)));
/// Data to draw lines and determine decorations from.
///
@@ -83,13 +82,18 @@ class BloodPressureValueGraph extends StatelessWidget {
@override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.only(top: 4.0),
- child: CustomPaint(
- painter: _ValueGraphPainter(
- brightness: Theme.of(context).brightness,
- settings: settings,
- labelStyle: Theme.of(context).textTheme.bodySmall ?? TextStyle(),
- records: records,
- colors: colors,
+ child: TweenAnimationBuilder(
+ tween: Tween(begin: 0.0, end: 1.0),
+ duration: Duration(milliseconds: 8 * settings.animationSpeed),
+ builder: (BuildContext context, double value, Widget? child) => CustomPaint(
+ painter: _ValueGraphPainter(
+ brightness: Theme.of(context).brightness,
+ settings: settings,
+ labelStyle: Theme.of(context).textTheme.bodySmall ?? TextStyle(),
+ records: records,
+ colors: colors,
+ progress: value,
+ ),
),
),
);
@@ -102,7 +106,8 @@ class _ValueGraphPainter extends CustomPainter {
required this.labelStyle,
required this.records,
required this.colors,
- });
+ required this.progress,
+ }): assert(1.0 >= progress && progress >= 0.0);
final Settings settings;
@@ -120,6 +125,9 @@ class _ValueGraphPainter extends CustomPainter {
static const double _kLeftLegendWidth = 35.0;
static const double _kBottomLegendHeight = 50.0;
+ /// Percentage of data line rendering (from 0 to 1).
+ final double progress;
+
void _paintDecorations(Canvas canvas, Size size, DateTimeRange range, double minY, double maxY) {
assert(size.width > _kLeftLegendWidth && size.height > _kBottomLegendHeight);
@@ -261,6 +269,7 @@ class _ValueGraphPainter extends CustomPainter {
}
if (path == null) return;
+ path = subPath(path, progress);
if (warnValue != null) {
final graphPath = Path();
@@ -436,6 +445,7 @@ class _ValueGraphPainter extends CustomPainter {
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => oldDelegate is! _ValueGraphPainter
+ || oldDelegate.progress != progress
|| oldDelegate.brightness != brightness
|| oldDelegate.settings.preferredPressureUnit != settings.preferredPressureUnit
|| oldDelegate.settings.sysColor != settings.sysColor
app/lib/screens/loading_screen.dart
@@ -64,46 +64,46 @@ class _LogoPainter extends CustomPainter {
path.lineTo(size.width * 0.82, size.height * 0.42);
path.lineTo(size.width * 0.818, size.height * 0.45);
path.lineTo(size.width * 0.65, size.height * 0.65);
- canvas.drawPath(_subPath(path, progress), paint);
+ canvas.drawPath(subPath(path, progress), paint);
}
@override
bool shouldRepaint(_LogoPainter oldDelegate) =>
oldDelegate.progress != progress;
+}
- /// Get a percentage of [originalPath].
- ///
- /// [animationPercent] is a value from 0 to 1.
- Path _subPath(Path originalPath, double animationPercent,) {
- final totalLength = originalPath
- .computeMetrics()
- .fold(0.0, (double prev, PathMetric metric) => prev + metric.length);
-
- return _extractPathUntilLength(originalPath, totalLength * animationPercent);
- }
+/// Get a percentage of [originalPath].
+///
+/// [animationPercent] is a value from 0 to 1.
+Path subPath(Path originalPath, double animationPercent) {
+ final totalLength = originalPath
+ .computeMetrics()
+ .fold(0.0, (double prev, PathMetric metric) => prev + metric.length);
- Path _extractPathUntilLength(Path originalPath, double length,) {
- final path = Path();
+ return _extractPathUntilLength(originalPath, totalLength * animationPercent);
+}
- final metricsIterator = originalPath.computeMetrics().iterator;
- var isLastSegment = false;
- var currentLength = 0.0;
+Path _extractPathUntilLength(Path originalPath, double length,) {
+ final path = Path();
- while (metricsIterator.moveNext() && !isLastSegment) {
- final metric = metricsIterator.current;
+ final metricsIterator = originalPath.computeMetrics().iterator;
+ var isLastSegment = false;
+ var currentLength = 0.0;
- final nextLength = currentLength + metric.length;
- isLastSegment = (nextLength > length);
+ while (metricsIterator.moveNext() && !isLastSegment) {
+ final metric = metricsIterator.current;
- assert(length - currentLength >= 0);
- final pathSegment = metric.extractPath(0.0,
- min(length - currentLength, metric.length),);
+ final nextLength = currentLength + metric.length;
+ isLastSegment = (nextLength > length);
- path.addPath(pathSegment, Offset.zero);
+ assert(length - currentLength >= 0);
+ final pathSegment = metric.extractPath(0.0,
+ min(length - currentLength, metric.length),);
- currentLength = nextLength;
- }
+ path.addPath(pathSegment, Offset.zero);
- return path;
+ currentLength = nextLength;
}
+
+ return path;
}