Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Unified Diff: packages/charted/lib/charts/cartesian_renderers/stackedline_chart_renderer.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packages/charted/lib/charts/cartesian_renderers/stackedline_chart_renderer.dart
diff --git a/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart b/packages/charted/lib/charts/cartesian_renderers/stackedline_chart_renderer.dart
similarity index 62%
copy from packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart
copy to packages/charted/lib/charts/cartesian_renderers/stackedline_chart_renderer.dart
index 4806d2d8c45c52ef70795607bf0a4c83c8c2a6c7..5bac934d0867855060bb39c245331eeb6bbc77c5 100644
--- a/packages/charted/lib/charts/cartesian_renderers/line_chart_renderer.dart
+++ b/packages/charted/lib/charts/cartesian_renderers/stackedline_chart_renderer.dart
@@ -1,5 +1,4 @@
-//
-// Copyright 2014 Google Inc. All rights reserved.
+// Copyright 2017 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
@@ -8,10 +7,11 @@
part of charted.charts;
-class LineChartRenderer extends CartesianRendererBase {
+class StackedLineChartRenderer extends CartesianRendererBase {
final Iterable<int> dimensionsUsingBand = const [];
final bool alwaysAnimate;
+ final bool showHoverCardOnTrackedDataPoints;
final bool trackDataPoints;
final bool trackOnDimensionAxis;
final int quantitativeScaleProximity;
@@ -26,10 +26,11 @@ class LineChartRenderer extends CartesianRendererBase {
int currentDataIndex = -1;
@override
- final String name = "line-rdr";
+ final String name = "stacked-line-rdr";
- LineChartRenderer(
+ StackedLineChartRenderer(
{this.alwaysAnimate: false,
+ this.showHoverCardOnTrackedDataPoints: false,
this.trackDataPoints: true,
this.trackOnDimensionAxis: false,
this.quantitativeScaleProximity: 5});
@@ -39,7 +40,7 @@ class LineChartRenderer extends CartesianRendererBase {
@override
bool prepare(ChartArea area, ChartSeries series) {
_ensureAreaAndSeries(area, series);
- if (trackDataPoints != false) {
+ if (trackDataPoints) {
_trackPointerInArea();
}
return area is CartesianArea;
@@ -52,17 +53,24 @@ class LineChartRenderer extends CartesianRendererBase {
var measureScale = area.measureScales(series).first,
dimensionScale = area.dimensionScales.first;
- // Create lists of values in measure columns.
- var lines = series.measures.map((column) {
- return area.data.rows.map((values) => values[column]).toList();
- }).toList();
-
// We only support one dimension axes, so we always use the
// first dimension.
var x = area.data.rows
.map((row) => row.elementAt(area.config.dimensions.first))
.toList();
+ var accumulated = new List.filled(x.length, 0.0);
+
+ var reversedMeasures = series.measures.toList().reversed.toList();
+ // Create lists of values used for drawing.
+ // First Half: previous values reversed (need for drawing)
+ // Second Half: current accumulated values (need for drawing)
+ var lines = reversedMeasures.map((column) {
+ var row = area.data.rows.map((values) => values[column]).toList();
+ return accumulated.reversed.toList()..addAll(
+ new List.generate(x.length, (i) => accumulated[i] += row[i]));
+ }).toList();
+
var rangeBandOffset =
dimensionScale is OrdinalScale ? dimensionScale.rangeBand / 2 : 0;
@@ -73,28 +81,47 @@ class LineChartRenderer extends CartesianRendererBase {
x.map((val) => dimensionScale.scale(val) + rangeBandOffset).toList();
}
- var line = new SvgLine(
+ var fillLine = new SvgLine(
+ xValueAccessor: (d, i) {
+ // The first x.length values are the bottom part of the path that
+ // should be drawn backword. The second part is the accumulated values
+ // that should be drawn forward.
+ var xval = i < x.length ? x[x.length - i - 1] : x[i - x.length];
+ return dimensionScale.scale(xval) + rangeBandOffset;
+ },
+ yValueAccessor: (d, i) => measureScale.scale(d));
+ var strokeLine = new SvgLine(
xValueAccessor: (d, i) => dimensionScale.scale(x[i]) + rangeBandOffset,
yValueAccessor: (d, i) => measureScale.scale(d));
// Add lines and hook up hover and selection events.
- var svgLines = root.selectAll('.line-rdr-line').data(lines);
- svgLines.enter.append('path').each((d, i, e) {
- e.attributes['fill'] = 'none';
- });
+ var svgLines = root.selectAll('.stacked-line-rdr-line').data(lines.reversed);
+ svgLines.enter.append('g');
svgLines.each((d, i, e) {
var column = series.measures.elementAt(i),
color = colorForColumn(column),
filter = filterForColumn(column),
- styles = stylesForColumn(column);
+ styles = stylesForColumn(column),
+ fill = new SvgElement.tag('path'),
+ stroke = new SvgElement.tag('path'),
+ fillData = d,
+ // Second half contains the accumulated data for this measure
+ strokeData = d.sublist(x.length, d.length);
e.attributes
- ..['d'] = line.path(d, i, e)
..['stroke'] = color
+ ..['fill'] = color
..['class'] = styles.isEmpty
- ? 'line-rdr-line'
- : 'line-rdr-line ${styles.join(' ')}'
+ ? 'stacked-line-rdr-line'
+ : 'stacked-line-rdr-line ${styles.join(' ')}'
..['data-column'] = '$column';
+ fill.attributes
+ ..['d'] = fillLine.path(fillData, i, e)
+ ..['stroke'] = 'none';
+ stroke.attributes
+ ..['d'] = strokeLine.path(strokeData, i, e)
+ ..['fill'] = 'none';
+ e.children = [fill, stroke];
if (isNullOrEmpty(filter)) {
e.attributes.remove('filter');
} else {
@@ -114,15 +141,40 @@ class LineChartRenderer extends CartesianRendererBase {
@override
void dispose() {
- if (root == null) return;
- root.selectAll('.line-rdr-line').remove();
- root.selectAll('.line-rdr-point').remove();
_disposer.dispose();
+ if (root == null) return;
+ root.selectAll('.stacked-line-rdr-line').remove();
+ root.selectAll('.stacked-line-rdr-point').remove();
+ }
+
+ @override
+ Extent get extent {
+ assert(area != null && series != null);
+ var rows = area.data.rows,
+ max = SMALL_INT_MIN,
+ min = SMALL_INT_MAX,
+ rowIndex = 0;
+
+ rows.forEach((row) {
+ var line = null;
+ series.measures.forEach((idx) {
+ var value = row.elementAt(idx);
+ if (value != null && value.isFinite) {
+ if (line == null) line = 0.0;
+ line += value;
+ }
+ });
+ if (line > max) max = line;
+ if (line < min) min = line;
+ rowIndex++;
+ });
+
+ return new Extent(min, max);
}
@override
void handleStateChanges(List<ChangeRecord> changes) {
- var lines = host.querySelectorAll('.line-rdr-line');
+ var lines = host.querySelectorAll('.stacked-line-rdr-line');
if (lines == null || lines.isEmpty) return;
for (int i = 0, len = lines.length; i < len; ++i) {
@@ -132,6 +184,7 @@ class LineChartRenderer extends CartesianRendererBase {
line.classes.removeAll(ChartState.COLUMN_CLASS_NAMES);
line.classes.addAll(stylesForColumn(column));
line.attributes['stroke'] = colorForColumn(column);
+ line.attributes['fill'] = colorForColumn(column);
if (isNullOrEmpty(filter)) {
line.attributes.remove('filter');
@@ -142,9 +195,10 @@ class LineChartRenderer extends CartesianRendererBase {
}
void _createTrackingCircles() {
- var linePoints = root.selectAll('.line-rdr-point').data(series.measures);
+ var linePoints = root.selectAll('.stacked-line-rdr-point')
+ .data(series.measures.toList().reversed);
linePoints.enter.append('circle').each((d, i, e) {
- e.classes.add('line-rdr-point');
+ e.classes.add('stacked-line-rdr-point');
e.attributes['r'] = '4';
});
@@ -166,15 +220,16 @@ class LineChartRenderer extends CartesianRendererBase {
_trackingPointsCreated = true;
}
- void _showTrackingCircles(int row) {
+ void _showTrackingCircles(ChartEvent event, int row) {
if (_trackingPointsCreated == false) {
_createTrackingCircles();
}
+ double cumulated = 0.0;
var yScale = area.measureScales(series).first;
- root.selectAll('.line-rdr-point').each((d, i, e) {
+ root.selectAll('.stacked-line-rdr-point').each((d, i, e) {
var x = _xPositions[row],
- measureVal = area.data.rows.elementAt(row).elementAt(d);
+ measureVal = cumulated += area.data.rows.elementAt(row).elementAt(d);
if (measureVal != null && measureVal.isFinite) {
var color = colorForColumn(d), filter = filterForColumn(d);
e.attributes
@@ -197,16 +252,28 @@ class LineChartRenderer extends CartesianRendererBase {
..setProperty('visibility', 'hidden');
}
});
+
+ if (showHoverCardOnTrackedDataPoints) {
+ var firstMeasureColumn = series.measures.first;
+ mouseOverController.add(new DefaultChartEventImpl(
+ event.source, area, series, row, firstMeasureColumn, 0));
+ _savedOverRow = row;
+ _savedOverColumn = firstMeasureColumn;
+ }
}
- void _hideTrackingCircles() {
- root.selectAll('.line-rdr-point')
+ void _hideTrackingCircles(ChartEvent event) {
+ root.selectAll('.stacked-line-rdr-point')
..style('opacity', '0.0')
..style('visibility', 'hidden');
+ if (showHoverCardOnTrackedDataPoints) {
+ mouseOutController.add(new DefaultChartEventImpl(
+ event.source, area, series, _savedOverRow, _savedOverColumn, 0));
+ }
}
int _getNearestRowIndex(num x) {
- var lastSmallerValue = 0;
+ double lastSmallerValue = 0.0;
var chartX = x - area.layout.renderArea.x;
for (var i = 0; i < _xPositions.length; i++) {
var pos = _xPositions[i];
@@ -226,19 +293,24 @@ class LineChartRenderer extends CartesianRendererBase {
_disposer.add(area.onMouseMove.listen((ChartEvent event) {
if (area.layout.renderArea.contains(event.chartX, event.chartY)) {
var row = _getNearestRowIndex(event.chartX);
- window.animationFrame.then((_) => _showTrackingCircles(row));
+ window.animationFrame.then((_) {
+ _showTrackingCircles(event, row);
+ });
} else {
- _hideTrackingCircles();
+ _hideTrackingCircles(event);
}
}));
_disposer.add(area.onMouseOut.listen((ChartEvent event) {
- _hideTrackingCircles();
+ _hideTrackingCircles(event);
}));
}
void _mouseClickHandler(d, int i, Element e) {
if (area.state != null) {
- area.state.select(int.parse(e.dataset['column']));
+ var selectedColumn = int.parse(e.dataset['column']);
+ area.state.isSelected(selectedColumn)
+ ? area.state.unselect(selectedColumn)
+ : area.state.select(selectedColumn);
}
if (mouseClickController != null && e.tagName == 'circle') {
var row = int.parse(e.dataset['row']),

Powered by Google App Engine
This is Rietveld 408576698