OLD | NEW |
1 // | 1 // |
2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
3 // | 3 // |
4 // Use of this source code is governed by a BSD-style | 4 // Use of this source code is governed by a BSD-style |
5 // license that can be found in the LICENSE file or at | 5 // license that can be found in the LICENSE file or at |
6 // https://developers.google.com/open-source/licenses/bsd | 6 // https://developers.google.com/open-source/licenses/bsd |
7 // | 7 // |
8 | 8 |
9 part of charted.svg.shapes; | 9 part of charted.svg.shapes; |
10 | 10 |
11 /// Function to convert a list of points to path. | 11 /// Function to convert a list of points to path. |
12 typedef String LineInterpolator(Iterable<math.Point> points, int tension); | 12 typedef String LineInterpolator(Iterable<math.Point> points, int tension); |
13 | 13 |
14 /// | 14 /// |
15 /// [SvgLine] provides a data-driven way to create path descriptions | 15 /// [SvgLine] provides a data-driven way to create path descriptions |
16 /// that can be used to draw lines. | 16 /// that can be used to draw lines. |
17 /// | 17 /// |
18 class SvgLine implements SvgShape { | 18 class SvgLine implements SvgShape { |
19 static const LINE_INTERPOLATOR_LINEAR = 'linear'; | 19 static const LINE_INTERPOLATOR_LINEAR = 'linear'; |
20 | 20 |
21 static final LINE_INTERPOLATORS = { | 21 static final LINE_INTERPOLATORS = {LINE_INTERPOLATOR_LINEAR: _linear}; |
22 LINE_INTERPOLATOR_LINEAR: _linear | |
23 }; | |
24 | 22 |
25 /// Callback to access/convert datum to x coordinate value. | 23 /// Callback to access/convert datum to x coordinate value. |
26 final SelectionValueAccessor<num> xValueAccessor; | 24 final SelectionValueAccessor<num> xValueAccessor; |
27 | 25 |
28 /// Callback to access/convert datum to y coordinate value. | 26 /// Callback to access/convert datum to y coordinate value. |
29 final SelectionValueAccessor<num> yValueAccessor; | 27 final SelectionValueAccessor<num> yValueAccessor; |
30 | 28 |
31 /// Callback that is used to determine if a value is considered valid. | 29 /// Callback that is used to determine if a value is considered valid. |
32 /// If [isDefined] returns false at any time, the value isn't part | 30 /// If [isDefined] returns false at any time, the value isn't part |
33 /// of the line - the line would be split. | 31 /// of the line - the line would be split. |
34 final SelectionCallback<bool> isDefined; | 32 final SelectionCallback<bool> isDefined; |
35 | 33 |
36 /// Interpolator that is used for creating the path. | 34 /// Interpolator that is used for creating the path. |
37 final LineInterpolator interpolator; | 35 final LineInterpolator interpolator; |
38 | 36 |
39 /// Tension of the line, as used by a few interpolators. | 37 /// Tension of the line, as used by a few interpolators. |
40 final int tension; | 38 final int tension; |
41 | 39 |
42 SvgLine({ | 40 SvgLine( |
43 this.xValueAccessor: defaultDataToX, | 41 {this.xValueAccessor: defaultDataToX, |
44 this.yValueAccessor: defaultDataToY, | 42 this.yValueAccessor: defaultDataToY, |
45 this.isDefined: defaultIsDefined, | 43 this.isDefined: defaultIsDefined, |
46 this.tension: 0, | 44 this.tension: 0, |
47 String interpolate: LINE_INTERPOLATOR_LINEAR }) | 45 String interpolate: LINE_INTERPOLATOR_LINEAR}) |
48 : interpolator = LINE_INTERPOLATORS[interpolate] { | 46 : interpolator = LINE_INTERPOLATORS[interpolate] { |
49 assert(interpolator != null); | 47 assert(interpolator != null); |
50 } | 48 } |
51 | 49 |
52 /// Generates path for drawing a line based in the selected [interpolator] | 50 /// Generates path for drawing a line based in the selected [interpolator] |
53 @override | 51 @override |
54 String path(data, int index, Element e) { | 52 String path(data, int index, Element e) { |
55 assert(data is Iterable); | 53 assert(data is Iterable); |
56 var segments = new StringBuffer(), | 54 var segments = new StringBuffer(), points = []; |
57 points = []; | |
58 for (int i = 0, len = data.length; i < len; ++i) { | 55 for (int i = 0, len = data.length; i < len; ++i) { |
59 final d = data.elementAt(i); | 56 final d = data.elementAt(i); |
60 if (isDefined(d, i, e)) { | 57 if (isDefined(d, i, e)) { |
61 points.add(new math.Point(xValueAccessor(d, i), yValueAccessor(d, i))); | 58 points.add(new math.Point(xValueAccessor(d, i), yValueAccessor(d, i))); |
62 } else if (points.isNotEmpty){ | 59 } else if (points.isNotEmpty) { |
63 segments.write('M${interpolator(points, tension)}'); | 60 segments.write('M${interpolator(points, tension)}'); |
64 points.clear(); | 61 points.clear(); |
65 } | 62 } |
66 } | 63 } |
67 if (points.isNotEmpty) { | 64 if (points.isNotEmpty) { |
68 segments.write('M${interpolator(points, tension)}'); | 65 segments.write('M${interpolator(points, tension)}'); |
69 } | 66 } |
70 return segments.toString(); | 67 return segments.toString(); |
71 } | 68 } |
72 | 69 |
73 /// Default implementation of [xValueAccessor]. | 70 /// Default implementation of [xValueAccessor]. |
74 /// Returns the first element if [d] is an iterable, otherwise returns [d]. | 71 /// Returns the first element if [d] is an iterable, otherwise returns [d]. |
75 static num defaultDataToX(d, i) => d is Iterable ? d.first : d; | 72 static num defaultDataToX(d, i) => d is Iterable ? d.first : d; |
76 | 73 |
77 /// Default implementation of [yValueAccessor]. | 74 /// Default implementation of [yValueAccessor]. |
78 /// Returns the second element if [d] is an iterable, otherwise returns [d]. | 75 /// Returns the second element if [d] is an iterable, otherwise returns [d]. |
79 static num defaultDataToY(d, i) => d is Iterable ? d.elementAt(1) : d; | 76 static num defaultDataToY(d, i) => d is Iterable ? d.elementAt(1) : d; |
80 | 77 |
81 /// Default implementation of [isDefined]. | 78 /// Default implementation of [isDefined]. |
82 /// Returns true for all non-null values of [d]. | 79 /// Returns true for all non-null values of [d]. |
83 static bool defaultIsDefined(d, i, e) => d != null; | 80 static bool defaultIsDefined(d, i, e) => d != null; |
84 | 81 |
85 /// Linear interpolator. | 82 /// Linear interpolator. |
86 static String _linear(Iterable points, _) => | 83 static String _linear(Iterable points, _) => |
87 points.map((pt) => '${pt.x},${pt.y}').join('L'); | 84 points.map((pt) => '${pt.x},${pt.y}').join('L'); |
88 } | 85 } |
OLD | NEW |