|
|
|
@ -33,11 +33,10 @@ import '../scatter_plot/point_renderer.dart' show PointRenderer;
|
|
|
|
|
import '../scatter_plot/point_renderer_config.dart' show PointRendererConfig;
|
|
|
|
|
import 'line_renderer_config.dart' show LineRendererConfig;
|
|
|
|
|
|
|
|
|
|
const styleSegmentsKey = const AttributeKey<List<_LineRendererElement>>(
|
|
|
|
|
'LineRenderer.styleSegments');
|
|
|
|
|
const styleSegmentsKey =
|
|
|
|
|
AttributeKey<List<_LineRendererElement>>('LineRenderer.styleSegments');
|
|
|
|
|
|
|
|
|
|
const lineStackIndexKey =
|
|
|
|
|
const AttributeKey<int>('LineRenderer.lineStackIndex');
|
|
|
|
|
const lineStackIndexKey = AttributeKey<int>('LineRenderer.lineStackIndex');
|
|
|
|
|
|
|
|
|
|
class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
// Configuration used to extend the clipping area to extend the draw bounds.
|
|
|
|
@ -69,9 +68,9 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final _currentKeys = <String>[];
|
|
|
|
|
|
|
|
|
|
factory LineRenderer({String rendererId, LineRendererConfig config}) {
|
|
|
|
|
return new LineRenderer._internal(
|
|
|
|
|
return LineRenderer._internal(
|
|
|
|
|
rendererId: rendererId ?? 'line',
|
|
|
|
|
config: config ?? new LineRendererConfig());
|
|
|
|
|
config: config ?? LineRendererConfig());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LineRenderer._internal({String rendererId, this.config})
|
|
|
|
@ -79,8 +78,8 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
rendererId: rendererId,
|
|
|
|
|
layoutPaintOrder: config.layoutPaintOrder,
|
|
|
|
|
symbolRenderer: config.symbolRenderer) {
|
|
|
|
|
_pointRenderer = new PointRenderer<D>(
|
|
|
|
|
config: new PointRendererConfig<D>(radiusPx: this.config.radiusPx));
|
|
|
|
|
_pointRenderer = PointRenderer<D>(
|
|
|
|
|
config: PointRendererConfig<D>(radiusPx: this.config.radiusPx));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@ -96,13 +95,13 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
void configureSeries(List<MutableSeries<D>> seriesList) {
|
|
|
|
|
assignMissingColors(seriesList, emptyCategoryUsesSinglePalette: false);
|
|
|
|
|
|
|
|
|
|
seriesList.forEach((MutableSeries series) {
|
|
|
|
|
seriesList.forEach((series) {
|
|
|
|
|
// Add a default area color function which applies the configured
|
|
|
|
|
// areaOpacity value to the datum's current color.
|
|
|
|
|
series.areaColorFn ??= (int index) {
|
|
|
|
|
series.areaColorFn ??= (index) {
|
|
|
|
|
final color = series.colorFn(index);
|
|
|
|
|
|
|
|
|
|
return new Color(
|
|
|
|
|
return Color(
|
|
|
|
|
r: color.r,
|
|
|
|
|
g: color.g,
|
|
|
|
|
b: color.b,
|
|
|
|
@ -123,7 +122,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
series.measureUpperBoundFn != null &&
|
|
|
|
|
series.measureLowerBoundFn != null);
|
|
|
|
|
|
|
|
|
|
seriesList.forEach((MutableSeries<D> series) {
|
|
|
|
|
seriesList.forEach((series) {
|
|
|
|
|
final colorFn = series.colorFn;
|
|
|
|
|
final areaColorFn = series.areaColorFn;
|
|
|
|
|
final domainFn = series.domainFn;
|
|
|
|
@ -136,7 +135,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final styleSegments = <_LineRendererElement<D>>[];
|
|
|
|
|
var styleSegmentsIndex = 0;
|
|
|
|
|
|
|
|
|
|
final usedKeys = new Set<String>();
|
|
|
|
|
final usedKeys = Set<String>();
|
|
|
|
|
|
|
|
|
|
// Configure style segments for each series.
|
|
|
|
|
String previousSegmentKey;
|
|
|
|
@ -163,8 +162,8 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
// Compare strokeWidthPx to 2 decimals of precision. Any less and you
|
|
|
|
|
// can't see any difference in the canvas anyways.
|
|
|
|
|
final strokeWidthPxRounded = (strokeWidthPx * 100).round() / 100;
|
|
|
|
|
var styleKey = '${series.id}__${styleSegmentsIndex}__${color}'
|
|
|
|
|
'__${dashPattern}__${strokeWidthPxRounded}';
|
|
|
|
|
var styleKey = '${series.id}__${styleSegmentsIndex}__$color'
|
|
|
|
|
'__${dashPattern}__$strokeWidthPxRounded';
|
|
|
|
|
|
|
|
|
|
if (styleKey != previousSegmentKey) {
|
|
|
|
|
// If we have a repeated style segment, update the repeat index and
|
|
|
|
@ -173,8 +172,8 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
if (usedKeys.isNotEmpty && usedKeys.contains(styleKey)) {
|
|
|
|
|
styleSegmentsIndex++;
|
|
|
|
|
|
|
|
|
|
styleKey = '${series.id}__${styleSegmentsIndex}__${color}'
|
|
|
|
|
'__${dashPattern}__${strokeWidthPxRounded}';
|
|
|
|
|
styleKey = '${series.id}__${styleSegmentsIndex}__$color'
|
|
|
|
|
'__${dashPattern}__$strokeWidthPxRounded';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure that the previous style segment extends to the current
|
|
|
|
@ -185,11 +184,11 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a new style segment.
|
|
|
|
|
currentDetails = new _LineRendererElement<D>()
|
|
|
|
|
currentDetails = _LineRendererElement<D>()
|
|
|
|
|
..color = color
|
|
|
|
|
..areaColor = areaColor
|
|
|
|
|
..dashPattern = dashPattern
|
|
|
|
|
..domainExtent = new _Range<D>(domain, domain)
|
|
|
|
|
..domainExtent = _Range<D>(domain, domain)
|
|
|
|
|
..strokeWidthPx = strokeWidthPx
|
|
|
|
|
..styleKey = styleKey
|
|
|
|
|
..roundEndCaps = config.roundEndCaps;
|
|
|
|
@ -273,7 +272,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (int i) => curOffsets[domainFn(i)];
|
|
|
|
|
return (i) => curOffsets[domainFn(i)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Merge the line map and the new series so that the new elements are mixed
|
|
|
|
@ -285,7 +284,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
void _mergeIntoSeriesMap(List<ImmutableSeries<D>> seriesList) {
|
|
|
|
|
List<MapEntry<String, List<_AnimatedElements<D>>>> newLineMap = [];
|
|
|
|
|
|
|
|
|
|
seriesList.forEach((ImmutableSeries<D> series) {
|
|
|
|
|
seriesList.forEach((series) {
|
|
|
|
|
final key = series.id;
|
|
|
|
|
|
|
|
|
|
// First, add all the series from the old map that have been removed from
|
|
|
|
@ -332,7 +331,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
|
|
|
|
|
_mergeIntoSeriesMap(seriesList);
|
|
|
|
|
|
|
|
|
|
seriesList.forEach((ImmutableSeries<D> series) {
|
|
|
|
|
seriesList.forEach((series) {
|
|
|
|
|
final domainAxis = series.getAttr(domainAxisKey) as ImmutableAxis<D>;
|
|
|
|
|
final lineKey = series.id;
|
|
|
|
|
final stackIndex = series.getAttr(lineStackIndexKey);
|
|
|
|
@ -372,12 +371,12 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
// later to display only the relevant parts of data. This ensures that
|
|
|
|
|
// styles that visually depend on the start location, such as dash
|
|
|
|
|
// patterns, are not disrupted by other changes in style.
|
|
|
|
|
styleSegments.forEach((_LineRendererElement styleSegment) {
|
|
|
|
|
styleSegments.forEach((styleSegment) {
|
|
|
|
|
final styleKey = styleSegment.styleKey;
|
|
|
|
|
|
|
|
|
|
// If we already have an AnimatingPoint for that index, use it.
|
|
|
|
|
var animatingElements = elementsList.firstWhere(
|
|
|
|
|
(_AnimatedElements elements) => elements.styleKey == styleKey,
|
|
|
|
|
(elements) => elements.styleKey == styleKey,
|
|
|
|
|
orElse: () => null);
|
|
|
|
|
|
|
|
|
|
if (animatingElements != null) {
|
|
|
|
@ -398,7 +397,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final animatingLines = <_AnimatedLine<D>>[];
|
|
|
|
|
|
|
|
|
|
for (var index = 0; index < lineElementList.length; index++) {
|
|
|
|
|
animatingLines.add(new _AnimatedLine<D>(
|
|
|
|
|
animatingLines.add(_AnimatedLine<D>(
|
|
|
|
|
key: lineElementList[index].styleKey,
|
|
|
|
|
overlaySeries: series.overlaySeries)
|
|
|
|
|
..setNewTarget(lineElementList[index]));
|
|
|
|
@ -410,7 +409,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
animatingAreas = <_AnimatedArea<D>>[];
|
|
|
|
|
|
|
|
|
|
for (var index = 0; index < areaElementList.length; index++) {
|
|
|
|
|
animatingAreas.add(new _AnimatedArea<D>(
|
|
|
|
|
animatingAreas.add(_AnimatedArea<D>(
|
|
|
|
|
key: areaElementList[index].styleKey,
|
|
|
|
|
overlaySeries: series.overlaySeries)
|
|
|
|
|
..setNewTarget(areaElementList[index]));
|
|
|
|
@ -424,14 +423,14 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
animatingBounds ??= <_AnimatedArea<D>>[];
|
|
|
|
|
|
|
|
|
|
for (var index = 0; index < boundsElementList.length; index++) {
|
|
|
|
|
animatingBounds.add(new _AnimatedArea<D>(
|
|
|
|
|
animatingBounds.add(_AnimatedArea<D>(
|
|
|
|
|
key: boundsElementList[index].styleKey,
|
|
|
|
|
overlaySeries: series.overlaySeries)
|
|
|
|
|
..setNewTarget(boundsElementList[index]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
animatingElements = new _AnimatedElements<D>()
|
|
|
|
|
animatingElements = _AnimatedElements<D>()
|
|
|
|
|
..styleKey = styleSegment.styleKey
|
|
|
|
|
..allPoints = allPointList
|
|
|
|
|
..lines = animatingLines
|
|
|
|
@ -458,7 +457,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
// than we did in the previous chart draw cycle.
|
|
|
|
|
// TODO: Nicer animations for incoming segments.
|
|
|
|
|
if (index >= animatingElements.lines.length) {
|
|
|
|
|
animatingElements.lines.add(new _AnimatedLine<D>(
|
|
|
|
|
animatingElements.lines.add(_AnimatedLine<D>(
|
|
|
|
|
key: lineElement.styleKey,
|
|
|
|
|
overlaySeries: series.overlaySeries));
|
|
|
|
|
}
|
|
|
|
@ -473,7 +472,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
// cycle than we did in the previous chart draw cycle.
|
|
|
|
|
// TODO: Nicer animations for incoming segments.
|
|
|
|
|
if (index >= animatingElements.areas.length) {
|
|
|
|
|
animatingElements.areas.add(new _AnimatedArea<D>(
|
|
|
|
|
animatingElements.areas.add(_AnimatedArea<D>(
|
|
|
|
|
key: areaElement.styleKey,
|
|
|
|
|
overlaySeries: series.overlaySeries));
|
|
|
|
|
}
|
|
|
|
@ -489,7 +488,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
// cycle than we did in the previous chart draw cycle.
|
|
|
|
|
// TODO: Nicer animations for incoming segments.
|
|
|
|
|
if (index >= animatingElements.bounds.length) {
|
|
|
|
|
animatingElements.bounds.add(new _AnimatedArea<D>(
|
|
|
|
|
animatingElements.bounds.add(_AnimatedArea<D>(
|
|
|
|
|
key: boundElement.styleKey,
|
|
|
|
|
overlaySeries: series.overlaySeries));
|
|
|
|
|
}
|
|
|
|
@ -506,7 +505,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Animate out lines that don't exist anymore.
|
|
|
|
|
_seriesLineMap.forEach((String key, List<_AnimatedElements<D>> elements) {
|
|
|
|
|
_seriesLineMap.forEach((key, elements) {
|
|
|
|
|
for (var element in elements) {
|
|
|
|
|
if (element.lines != null) {
|
|
|
|
|
for (var line in element.lines) {
|
|
|
|
@ -599,10 +598,10 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final linePointList = lineSegments[index];
|
|
|
|
|
|
|
|
|
|
// Update the set of areas that still exist in the series data.
|
|
|
|
|
final lineStyleKey = '${styleKey}__line__${index}';
|
|
|
|
|
final lineStyleKey = '${styleKey}__line__$index';
|
|
|
|
|
_currentKeys.add(lineStyleKey);
|
|
|
|
|
|
|
|
|
|
lineElements.add(new _LineRendererElement<D>()
|
|
|
|
|
lineElements.add(_LineRendererElement<D>()
|
|
|
|
|
..points = linePointList
|
|
|
|
|
..color = color
|
|
|
|
|
..areaColor = areaColor
|
|
|
|
@ -622,10 +621,10 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final areaPointList = areaSegments[index];
|
|
|
|
|
|
|
|
|
|
// Update the set of areas that still exist in the series data.
|
|
|
|
|
final areaStyleKey = '${styleKey}__area_${index}';
|
|
|
|
|
final areaStyleKey = '${styleKey}__area_$index';
|
|
|
|
|
_currentKeys.add(areaStyleKey);
|
|
|
|
|
|
|
|
|
|
areaElements.add(new _AreaRendererElement<D>()
|
|
|
|
|
areaElements.add(_AreaRendererElement<D>()
|
|
|
|
|
..points = areaPointList
|
|
|
|
|
..color = color
|
|
|
|
|
..areaColor = areaColor
|
|
|
|
@ -643,10 +642,10 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
for (var index = 0; index < boundsSegment.length; index++) {
|
|
|
|
|
final boundsPointList = boundsSegment[index];
|
|
|
|
|
|
|
|
|
|
final boundsStyleKey = '${styleKey}__bounds_${index}';
|
|
|
|
|
final boundsStyleKey = '${styleKey}__bounds_$index';
|
|
|
|
|
_currentKeys.add(boundsStyleKey);
|
|
|
|
|
|
|
|
|
|
boundsElements.add(new _AreaRendererElement<D>()
|
|
|
|
|
boundsElements.add(_AreaRendererElement<D>()
|
|
|
|
|
..points = boundsPointList
|
|
|
|
|
..color = color
|
|
|
|
|
..areaColor = areaColor
|
|
|
|
@ -858,7 +857,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final areaPointList = <_DatumPoint<D>>[];
|
|
|
|
|
|
|
|
|
|
// Add all points for upper bounds.
|
|
|
|
|
areaPointList.addAll(pointList.map((datumPoint) => new _DatumPoint.from(
|
|
|
|
|
areaPointList.addAll(pointList.map((datumPoint) => _DatumPoint.from(
|
|
|
|
|
datumPoint,
|
|
|
|
|
datumPoint.x,
|
|
|
|
|
initializeFromZero
|
|
|
|
@ -869,7 +868,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
|
|
|
|
|
// Add all points for lower bounds, in reverse order.
|
|
|
|
|
areaPointList.addAll(pointList.reversed.map((datumPoint) =>
|
|
|
|
|
new _DatumPoint.from(
|
|
|
|
|
_DatumPoint.from(
|
|
|
|
|
datumPoint,
|
|
|
|
|
datumPoint.x,
|
|
|
|
|
initializeFromZero
|
|
|
|
@ -902,7 +901,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
final endPosition = domainAxis.getLocation(details.domainExtent.end) ??
|
|
|
|
|
drawBounds.right.toDouble();
|
|
|
|
|
|
|
|
|
|
return new _Range<num>(startPosition, endPosition);
|
|
|
|
|
return _Range<num>(startPosition, endPosition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@ -919,9 +918,8 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
if (animationPercent == 1.0) {
|
|
|
|
|
final keysToRemove = <String>[];
|
|
|
|
|
|
|
|
|
|
_seriesLineMap.forEach((String key, List<_AnimatedElements<D>> elements) {
|
|
|
|
|
elements.removeWhere(
|
|
|
|
|
(_AnimatedElements<D> element) => element.animatingOut);
|
|
|
|
|
_seriesLineMap.forEach((key, elements) {
|
|
|
|
|
elements.removeWhere((element) => element.animatingOut);
|
|
|
|
|
|
|
|
|
|
if (elements.isEmpty) {
|
|
|
|
|
keysToRemove.add(key);
|
|
|
|
@ -931,16 +929,15 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
keysToRemove.forEach(_seriesLineMap.remove);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_seriesLineMap.forEach((String key, List<_AnimatedElements<D>> elements) {
|
|
|
|
|
_seriesLineMap.forEach((key, elements) {
|
|
|
|
|
if (config.includeArea) {
|
|
|
|
|
elements
|
|
|
|
|
.map<List<_AnimatedArea<D>>>(
|
|
|
|
|
(_AnimatedElements<D> animatingElement) =>
|
|
|
|
|
animatingElement.areas)
|
|
|
|
|
.expand<_AnimatedArea<D>>((List<_AnimatedArea<D>> areas) => areas)
|
|
|
|
|
.map<_AreaRendererElement<D>>((_AnimatedArea<D> animatingArea) =>
|
|
|
|
|
(animatingElement) => animatingElement.areas)
|
|
|
|
|
.expand<_AnimatedArea<D>>((areas) => areas)
|
|
|
|
|
.map<_AreaRendererElement<D>>((animatingArea) =>
|
|
|
|
|
animatingArea?.getCurrentArea(animationPercent))
|
|
|
|
|
.forEach((_AreaRendererElement area) {
|
|
|
|
|
.forEach((area) {
|
|
|
|
|
if (area != null) {
|
|
|
|
|
canvas.drawPolygon(
|
|
|
|
|
clipBounds: _getClipBoundsForExtent(area.positionExtent),
|
|
|
|
@ -953,12 +950,11 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
if (_hasMeasureBounds) {
|
|
|
|
|
elements
|
|
|
|
|
.map<List<_AnimatedArea<D>>>(
|
|
|
|
|
(_AnimatedElements<D> animatingElement) =>
|
|
|
|
|
animatingElement.bounds)
|
|
|
|
|
.expand<_AnimatedArea<D>>((List<_AnimatedArea<D>> bounds) => bounds)
|
|
|
|
|
.map<_AreaRendererElement<D>>((_AnimatedArea<D> animatingBounds) =>
|
|
|
|
|
(animatingElement) => animatingElement.bounds)
|
|
|
|
|
.expand<_AnimatedArea<D>>((bounds) => bounds)
|
|
|
|
|
.map<_AreaRendererElement<D>>((animatingBounds) =>
|
|
|
|
|
animatingBounds?.getCurrentArea(animationPercent))
|
|
|
|
|
.forEach((_AreaRendererElement bound) {
|
|
|
|
|
.forEach((bound) {
|
|
|
|
|
if (bound != null) {
|
|
|
|
|
canvas.drawPolygon(
|
|
|
|
|
clipBounds: _getClipBoundsForExtent(bound.positionExtent),
|
|
|
|
@ -971,12 +967,11 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
if (config.includeLine) {
|
|
|
|
|
elements
|
|
|
|
|
.map<List<_AnimatedLine<D>>>(
|
|
|
|
|
(_AnimatedElements<D> animatingElement) =>
|
|
|
|
|
animatingElement.lines)
|
|
|
|
|
.expand<_AnimatedLine<D>>((List<_AnimatedLine<D>> lines) => lines)
|
|
|
|
|
.map<_LineRendererElement<D>>((_AnimatedLine<D> animatingLine) =>
|
|
|
|
|
(animatingElement) => animatingElement.lines)
|
|
|
|
|
.expand<_AnimatedLine<D>>((lines) => lines)
|
|
|
|
|
.map<_LineRendererElement<D>>((animatingLine) =>
|
|
|
|
|
animatingLine?.getCurrentLine(animationPercent))
|
|
|
|
|
.forEach((_LineRendererElement line) {
|
|
|
|
|
.forEach((line) {
|
|
|
|
|
if (line != null) {
|
|
|
|
|
canvas.drawLine(
|
|
|
|
|
clipBounds: _getClipBoundsForExtent(line.positionExtent),
|
|
|
|
@ -1009,7 +1004,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
? clamp((extent.start), drawBounds.left, drawBounds.right)
|
|
|
|
|
: clamp((extent.end), drawBounds.left, drawBounds.right);
|
|
|
|
|
|
|
|
|
|
return new Rectangle<num>(
|
|
|
|
|
return Rectangle<num>(
|
|
|
|
|
left,
|
|
|
|
|
drawBounds.top - drawBoundTopExtensionPx,
|
|
|
|
|
right - left,
|
|
|
|
@ -1035,7 +1030,7 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
? measureAxis.getLocation(measureValue + measureOffsetValue)
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
return new _DatumPoint<D>(
|
|
|
|
|
return _DatumPoint<D>(
|
|
|
|
|
datum: datum,
|
|
|
|
|
domain: domainValue,
|
|
|
|
|
series: series,
|
|
|
|
@ -1054,18 +1049,18 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
return nearest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_seriesLineMap.values.forEach((List<_AnimatedElements<D>> seriesSegments) {
|
|
|
|
|
_seriesLineMap.values.forEach((seriesSegments) {
|
|
|
|
|
_DatumPoint<D> nearestPoint;
|
|
|
|
|
double nearestDomainDistance = 10000.0;
|
|
|
|
|
double nearestMeasureDistance = 10000.0;
|
|
|
|
|
double nearestRelativeDistance = 10000.0;
|
|
|
|
|
|
|
|
|
|
seriesSegments.forEach((_AnimatedElements<D> segment) {
|
|
|
|
|
seriesSegments.forEach((segment) {
|
|
|
|
|
if (segment.overlaySeries) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
segment.allPoints.forEach((Point p) {
|
|
|
|
|
segment.allPoints.forEach((p) {
|
|
|
|
|
// Don't look at points not in the drawArea.
|
|
|
|
|
if (p.x < componentBounds.left || p.x > componentBounds.right) {
|
|
|
|
|
return;
|
|
|
|
@ -1108,8 +1103,8 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
|
|
|
|
|
// Found a point, add it to the list.
|
|
|
|
|
if (nearestPoint != null) {
|
|
|
|
|
nearest.add(new DatumDetails<D>(
|
|
|
|
|
chartPosition: new Point<double>(nearestPoint.x, nearestPoint.y),
|
|
|
|
|
nearest.add(DatumDetails<D>(
|
|
|
|
|
chartPosition: Point<double>(nearestPoint.x, nearestPoint.y),
|
|
|
|
|
datum: nearestPoint.datum,
|
|
|
|
|
domain: nearestPoint.domain,
|
|
|
|
|
series: nearestPoint.series,
|
|
|
|
@ -1134,9 +1129,9 @@ class LineRenderer<D> extends BaseCartesianRenderer<D> {
|
|
|
|
|
|
|
|
|
|
final point = _getPoint(seriesDatum.datum, details.domain, series,
|
|
|
|
|
domainAxis, details.measure, details.measureOffset, measureAxis);
|
|
|
|
|
final chartPosition = new Point<double>(point.x, point.y);
|
|
|
|
|
final chartPosition = Point<double>(point.x, point.y);
|
|
|
|
|
|
|
|
|
|
return new DatumDetails.from(details, chartPosition: chartPosition);
|
|
|
|
|
return DatumDetails.from(details, chartPosition: chartPosition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1151,7 +1146,7 @@ class _DatumPoint<D> extends Point<double> {
|
|
|
|
|
: super(x, y);
|
|
|
|
|
|
|
|
|
|
factory _DatumPoint.from(_DatumPoint<D> other, [double x, double y]) {
|
|
|
|
|
return new _DatumPoint<D>(
|
|
|
|
|
return _DatumPoint<D>(
|
|
|
|
|
datum: other.datum,
|
|
|
|
|
domain: other.domain,
|
|
|
|
|
series: other.series,
|
|
|
|
@ -1175,13 +1170,11 @@ class _LineRendererElement<D> {
|
|
|
|
|
bool roundEndCaps;
|
|
|
|
|
|
|
|
|
|
_LineRendererElement<D> clone() {
|
|
|
|
|
return new _LineRendererElement<D>()
|
|
|
|
|
..points = new List<_DatumPoint<D>>.from(points)
|
|
|
|
|
..color = color != null ? new Color.fromOther(color: color) : null
|
|
|
|
|
..areaColor =
|
|
|
|
|
areaColor != null ? new Color.fromOther(color: areaColor) : null
|
|
|
|
|
..dashPattern =
|
|
|
|
|
dashPattern != null ? new List<int>.from(dashPattern) : null
|
|
|
|
|
return _LineRendererElement<D>()
|
|
|
|
|
..points = List<_DatumPoint<D>>.from(points)
|
|
|
|
|
..color = color != null ? Color.fromOther(color: color) : null
|
|
|
|
|
..areaColor = areaColor != null ? Color.fromOther(color: areaColor) : null
|
|
|
|
|
..dashPattern = dashPattern != null ? List<int>.from(dashPattern) : null
|
|
|
|
|
..domainExtent = domainExtent
|
|
|
|
|
..measureAxisPosition = measureAxisPosition
|
|
|
|
|
..positionExtent = positionExtent
|
|
|
|
@ -1207,7 +1200,7 @@ class _LineRendererElement<D> {
|
|
|
|
|
lastPoint = previousPoint;
|
|
|
|
|
} else {
|
|
|
|
|
previousPoint =
|
|
|
|
|
new _DatumPoint<D>.from(targetPoint, targetPoint.x, lastPoint.y);
|
|
|
|
|
_DatumPoint<D>.from(targetPoint, targetPoint.x, lastPoint.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final x = ((targetPoint.x - previousPoint.x) * animationPercent) +
|
|
|
|
@ -1224,9 +1217,9 @@ class _LineRendererElement<D> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (points.length - 1 >= pointIndex) {
|
|
|
|
|
points[pointIndex] = new _DatumPoint<D>.from(targetPoint, x, y);
|
|
|
|
|
points[pointIndex] = _DatumPoint<D>.from(targetPoint, x, y);
|
|
|
|
|
} else {
|
|
|
|
|
points.add(new _DatumPoint<D>.from(targetPoint, x, y));
|
|
|
|
|
points.add(_DatumPoint<D>.from(targetPoint, x, y));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1278,7 +1271,7 @@ class _AnimatedLine<D> {
|
|
|
|
|
for (var index = 0; index < newTarget.points.length; index++) {
|
|
|
|
|
var targetPoint = newTarget.points[index];
|
|
|
|
|
|
|
|
|
|
newPoints.add(new _DatumPoint<D>.from(targetPoint, targetPoint.x,
|
|
|
|
|
newPoints.add(_DatumPoint<D>.from(targetPoint, targetPoint.x,
|
|
|
|
|
newTarget.measureAxisPosition.roundToDouble()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1328,11 +1321,10 @@ class _AreaRendererElement<D> {
|
|
|
|
|
String styleKey;
|
|
|
|
|
|
|
|
|
|
_AreaRendererElement<D> clone() {
|
|
|
|
|
return new _AreaRendererElement<D>()
|
|
|
|
|
..points = new List<_DatumPoint<D>>.from(points)
|
|
|
|
|
..color = color != null ? new Color.fromOther(color: color) : null
|
|
|
|
|
..areaColor =
|
|
|
|
|
areaColor != null ? new Color.fromOther(color: areaColor) : null
|
|
|
|
|
return _AreaRendererElement<D>()
|
|
|
|
|
..points = List<_DatumPoint<D>>.from(points)
|
|
|
|
|
..color = color != null ? Color.fromOther(color: color) : null
|
|
|
|
|
..areaColor = areaColor != null ? Color.fromOther(color: areaColor) : null
|
|
|
|
|
..domainExtent = domainExtent
|
|
|
|
|
..measureAxisPosition = measureAxisPosition
|
|
|
|
|
..positionExtent = positionExtent
|
|
|
|
@ -1356,7 +1348,7 @@ class _AreaRendererElement<D> {
|
|
|
|
|
lastPoint = previousPoint;
|
|
|
|
|
} else {
|
|
|
|
|
previousPoint =
|
|
|
|
|
new _DatumPoint<D>.from(targetPoint, targetPoint.x, lastPoint.y);
|
|
|
|
|
_DatumPoint<D>.from(targetPoint, targetPoint.x, lastPoint.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final x = ((targetPoint.x - previousPoint.x) * animationPercent) +
|
|
|
|
@ -1373,9 +1365,9 @@ class _AreaRendererElement<D> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (points.length - 1 >= pointIndex) {
|
|
|
|
|
points[pointIndex] = new _DatumPoint<D>.from(targetPoint, x, y);
|
|
|
|
|
points[pointIndex] = _DatumPoint<D>.from(targetPoint, x, y);
|
|
|
|
|
} else {
|
|
|
|
|
points.add(new _DatumPoint<D>.from(targetPoint, x, y));
|
|
|
|
|
points.add(_DatumPoint<D>.from(targetPoint, x, y));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1423,7 +1415,7 @@ class _AnimatedArea<D> {
|
|
|
|
|
for (var index = 0; index < newTarget.points.length; index++) {
|
|
|
|
|
var targetPoint = newTarget.points[index];
|
|
|
|
|
|
|
|
|
|
newPoints.add(new _DatumPoint<D>.from(targetPoint, targetPoint.x,
|
|
|
|
|
newPoints.add(_DatumPoint<D>.from(targetPoint, targetPoint.x,
|
|
|
|
|
newTarget.measureAxisPosition.roundToDouble()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|