2017-11-02 23:48:58 +00:00
|
|
|
import 'dart:ui' show lerpDouble;
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_circular_chart/src/entry.dart';
|
|
|
|
import 'package:flutter_circular_chart/src/segment.dart';
|
|
|
|
import 'package:flutter_circular_chart/src/tween.dart';
|
|
|
|
|
|
|
|
const double _kMaxAngle = 360.0;
|
|
|
|
|
|
|
|
class CircularChartStack implements MergeTweenable<CircularChartStack> {
|
|
|
|
CircularChartStack(
|
2018-03-21 00:38:05 +00:00
|
|
|
this.rank,
|
|
|
|
this.radius,
|
|
|
|
this.width,
|
|
|
|
this.startAngle,
|
|
|
|
this.segments,
|
|
|
|
);
|
2017-11-02 23:48:58 +00:00
|
|
|
|
|
|
|
final int rank;
|
|
|
|
final double radius;
|
|
|
|
final double width;
|
|
|
|
final double startAngle;
|
|
|
|
final List<CircularChartSegment> segments;
|
|
|
|
|
|
|
|
factory CircularChartStack.fromData(
|
|
|
|
int stackRank,
|
|
|
|
List<CircularSegmentEntry> entries,
|
|
|
|
Map<String, int> entryRanks,
|
|
|
|
bool percentageValues,
|
|
|
|
double startRadius,
|
|
|
|
double stackWidth,
|
|
|
|
double startAngle,
|
|
|
|
) {
|
|
|
|
final double valueSum = percentageValues
|
|
|
|
? 100.0
|
|
|
|
: entries.fold(
|
|
|
|
0.0,
|
2018-03-21 00:38:05 +00:00
|
|
|
(double prev, CircularSegmentEntry element) => prev + element.value,
|
|
|
|
);
|
2017-11-02 23:48:58 +00:00
|
|
|
|
|
|
|
double previousSweepAngle = 0.0;
|
|
|
|
List<CircularChartSegment> segments =
|
|
|
|
new List<CircularChartSegment>.generate(entries.length, (i) {
|
|
|
|
double sweepAngle =
|
|
|
|
(entries[i].value / valueSum * _kMaxAngle) + previousSweepAngle;
|
|
|
|
previousSweepAngle = sweepAngle;
|
|
|
|
int rank = entryRanks[entries[i].rankKey] ?? i;
|
|
|
|
return new CircularChartSegment(rank, sweepAngle, entries[i].color);
|
|
|
|
});
|
|
|
|
|
|
|
|
return new CircularChartStack(
|
|
|
|
stackRank,
|
|
|
|
startRadius,
|
|
|
|
stackWidth,
|
|
|
|
startAngle,
|
|
|
|
segments.reversed.toList(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
CircularChartStack get empty => new CircularChartStack(
|
|
|
|
rank, radius, 0.0, startAngle, <CircularChartSegment>[]);
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool operator <(CircularChartStack other) => rank < other.rank;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Tween<CircularChartStack> tweenTo(CircularChartStack other) =>
|
|
|
|
new CircularChartStackTween(this, other);
|
|
|
|
}
|
|
|
|
|
|
|
|
class CircularChartStackTween extends Tween<CircularChartStack> {
|
|
|
|
CircularChartStackTween(CircularChartStack begin, CircularChartStack end)
|
|
|
|
: _circularSegmentsTween =
|
|
|
|
new MergeTween<CircularChartSegment>(begin.segments, end.segments),
|
|
|
|
super(begin: begin, end: end) {
|
|
|
|
assert(begin.rank == end.rank);
|
|
|
|
}
|
|
|
|
|
|
|
|
final MergeTween<CircularChartSegment> _circularSegmentsTween;
|
|
|
|
|
|
|
|
@override
|
|
|
|
CircularChartStack lerp(double t) => new CircularChartStack(
|
|
|
|
begin.rank,
|
|
|
|
lerpDouble(begin.radius, end.radius, t),
|
|
|
|
lerpDouble(begin.width, end.width, t),
|
|
|
|
lerpDouble(begin.startAngle, end.startAngle, t),
|
|
|
|
_circularSegmentsTween.lerp(t),
|
|
|
|
);
|
|
|
|
}
|