mascot-vis 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/mascot-esm.js +186 -0
  2. package/package.json +3 -6
  3. package/dist/mascot-es.js +0 -27745
  4. package/dist/mascot-min.js +0 -186
  5. package/dist/mascot-umd.js +0 -27781
  6. package/js/depGraphVis.js +0 -66
  7. package/src-new-ts/action/createElement.ts +0 -91
  8. package/src-new-ts/action/encode.js +0 -20
  9. package/src-new-ts/action/repeat.js +0 -128
  10. package/src-new-ts/action/traverseScene.js +0 -41
  11. package/src-new-ts/data/Network.js +0 -2
  12. package/src-new-ts/data/Scope.js +0 -135
  13. package/src-new-ts/data/Table.js +0 -263
  14. package/src-new-ts/data/Tree.js +0 -3
  15. package/src-new-ts/data/field.ts +0 -115
  16. package/src-new-ts/data/import.ts +0 -96
  17. package/src-new-ts/data/predicate.ts +0 -82
  18. package/src-new-ts/depgraph/DepGraph.js +0 -178
  19. package/src-new-ts/depgraph/Edge.js +0 -9
  20. package/src-new-ts/depgraph/SceneGraph2DepGraph.js +0 -110
  21. package/src-new-ts/depgraph/Signal.js +0 -12
  22. package/src-new-ts/depgraph/operator/BoundsEvaluator.js +0 -30
  23. package/src-new-ts/depgraph/operator/Dataflow.js +0 -41
  24. package/src-new-ts/depgraph/operator/DomainBuilder.js +0 -50
  25. package/src-new-ts/depgraph/updateDepGraph.js +0 -45
  26. package/src-new-ts/depgraph/variable/BoundsVar.js +0 -81
  27. package/src-new-ts/depgraph/variable/ChannelVar.js +0 -17
  28. package/src-new-ts/depgraph/variable/DataScopeVar.js +0 -12
  29. package/src-new-ts/depgraph/variable/DomainVar.js +0 -15
  30. package/src-new-ts/depgraph/variable/FieldVar.js +0 -17
  31. package/src-new-ts/depgraph/variable/LayoutParameter.js +0 -8
  32. package/src-new-ts/depgraph/variable/ScaleVar.js +0 -13
  33. package/src-new-ts/depgraph/variable/Variable.js +0 -39
  34. package/src-new-ts/element/gradient/LinearGradient.js +0 -37
  35. package/src-new-ts/element/group/Collection.js +0 -109
  36. package/src-new-ts/element/group/Group.js +0 -307
  37. package/src-new-ts/element/group/Scene.js +0 -98
  38. package/src-new-ts/element/mark/CircleMark.ts +0 -85
  39. package/src-new-ts/element/mark/Mark.ts +0 -233
  40. package/src-new-ts/element/mark/PathMark.js +0 -483
  41. package/src-new-ts/element/mark/Segment.js +0 -29
  42. package/src-new-ts/element/mark/Vertex.js +0 -118
  43. package/src-new-ts/encode/Scale.ts +0 -115
  44. package/src-new-ts/index.ts +0 -19
  45. package/src-new-ts/layout/Layout.ts +0 -3
  46. package/src-new-ts/render/CanvasRenderer.ts +0 -24
  47. package/src-new-ts/render/SVGRenderer.js +0 -316
  48. package/src-new-ts/util.ts +0 -3
  49. package/src-old/action/Classify.js +0 -53
  50. package/src-old/action/Densify.js +0 -199
  51. package/src-old/action/Partition.js +0 -531
  52. package/src-old/action/Repeat.js +0 -106
  53. package/src-old/action/Repopulate.js +0 -44
  54. package/src-old/action/Stratify.js +0 -156
  55. package/src-old/basic/Gradient.js +0 -37
  56. package/src-old/basic/Point.js +0 -51
  57. package/src-old/basic/Rectangle.js +0 -63
  58. package/src-old/bind/bindToAngle.js +0 -56
  59. package/src-old/bind/bindToAreaMark.js +0 -360
  60. package/src-old/bind/bindToColor.js +0 -114
  61. package/src-old/bind/bindToLink.js +0 -81
  62. package/src-old/bind/bindToPosition.js +0 -283
  63. package/src-old/bind/bindToRadialDistance.js +0 -62
  64. package/src-old/bind/bindToSize.js +0 -235
  65. package/src-old/bind/bindToText.js +0 -60
  66. package/src-old/bind/bindToThickness.js +0 -100
  67. package/src-old/constraint/AffixConstraint.js +0 -129
  68. package/src-old/constraint/AlignConstraint.js +0 -58
  69. package/src-old/core/Encoding.js +0 -336
  70. package/src-old/core/Scale.js +0 -322
  71. package/src-old/core/SceneLoader.js +0 -290
  72. package/src-old/core/SceneValidator.js +0 -232
  73. package/src-old/core/SpecExecutor.js +0 -113
  74. package/src-old/core/SpecGenerator.js +0 -350
  75. package/src-old/data/DataImporter.js +0 -64
  76. package/src-old/data/DataScope.js +0 -124
  77. package/src-old/data/DataTable.js +0 -338
  78. package/src-old/data/Network.js +0 -106
  79. package/src-old/data/Tree.js +0 -251
  80. package/src-old/data/transform/Bin.js +0 -46
  81. package/src-old/data/transform/Filter.js +0 -48
  82. package/src-old/data/transform/Groupby.js +0 -18
  83. package/src-old/data/transform/KDE.js +0 -58
  84. package/src-old/data/transform/Sort.js +0 -14
  85. package/src-old/data/transform/Split.js +0 -5
  86. package/src-old/data/transform/partition.js +0 -46
  87. package/src-old/history/UndoRedoStack +0 -0
  88. package/src-old/index.js +0 -271
  89. package/src-old/indexSVG.js +0 -259
  90. package/src-old/interaction/Interaction.js +0 -91
  91. package/src-old/interaction/MouseEvent.js +0 -8
  92. package/src-old/interaction/Selection.js +0 -9
  93. package/src-old/interaction/brush.js +0 -362
  94. package/src-old/item/Segment.js +0 -29
  95. package/src-old/item/Vertex.js +0 -118
  96. package/src-old/item/composite/Collection.js +0 -106
  97. package/src-old/item/composite/Glyph.js +0 -19
  98. package/src-old/item/composite/Group.js +0 -310
  99. package/src-old/item/composite/Scene.js +0 -1251
  100. package/src-old/item/mark/ArcPath.js +0 -181
  101. package/src-old/item/mark/AreaPath.js +0 -78
  102. package/src-old/item/mark/CirclePath.js +0 -102
  103. package/src-old/item/mark/EllipsePath.js +0 -5
  104. package/src-old/item/mark/Image.js +0 -101
  105. package/src-old/item/mark/LinkPath.js +0 -118
  106. package/src-old/item/mark/Mark.js +0 -163
  107. package/src-old/item/mark/Path.js +0 -494
  108. package/src-old/item/mark/PointText.js +0 -201
  109. package/src-old/item/mark/PolygonPath.js +0 -64
  110. package/src-old/item/mark/RectPath.js +0 -88
  111. package/src-old/item/mark/RingPath.js +0 -92
  112. package/src-old/item/refs/Axis.js +0 -362
  113. package/src-old/item/refs/EncodingAxis.js +0 -515
  114. package/src-old/item/refs/Gridlines.js +0 -144
  115. package/src-old/item/refs/LayoutAxis.js +0 -316
  116. package/src-old/item/refs/Legend.js +0 -273
  117. package/src-old/layout/Circular.js +0 -95
  118. package/src-old/layout/Force.js +0 -52
  119. package/src-old/layout/Grid.js +0 -423
  120. package/src-old/layout/Layout.js +0 -13
  121. package/src-old/layout/Packing.js +0 -56
  122. package/src-old/layout/Stack.js +0 -264
  123. package/src-old/layout/Strata.js +0 -88
  124. package/src-old/layout/Sugiyama.js +0 -59
  125. package/src-old/layout/TidyTree.js +0 -105
  126. package/src-old/layout/Treemap.js +0 -87
  127. package/src-old/renderer/SVGInteractionHandler.js +0 -241
  128. package/src-old/renderer/SVGRenderer.js +0 -325
  129. package/src-old/renderer/WebGLRenderer.js +0 -1097
  130. package/src-old/renderer/WebGLRenderer2.js +0 -249
  131. package/src-old/renderer/threejs/Line2.js +0 -18
  132. package/src-old/renderer/threejs/LineGeometry.js +0 -77
  133. package/src-old/renderer/threejs/LineMaterial.js +0 -605
  134. package/src-old/renderer/threejs/LineSegments2.js +0 -281
  135. package/src-old/renderer/threejs/LineSegmentsGeometry.js +0 -226
  136. package/src-old/renderer/threejs/Wireframe.js +0 -51
  137. package/src-old/renderer/threejs/WireframeGeometry2.js +0 -16
  138. package/src-old/scale/areaSize.js +0 -0
  139. package/src-old/scale/domain.js +0 -38
  140. package/src-old/util/Constants.js +0 -180
  141. package/src-old/util/DataUtil.js +0 -35
  142. package/src-old/util/ItemUtil.js +0 -586
  143. package/src-old/util/Numerical.js +0 -33
  144. package/tests/demo-tests/README.md +0 -80
  145. package/tests/demo-tests/SVG2PNG.js +0 -56
  146. package/tests/demo-tests/demos2CanvasPNGs.js +0 -69
  147. package/tests/demo-tests/demos2ScenesSVGs.js +0 -100
  148. package/tests/demo-tests/pathElementWorker.js +0 -91
  149. package/tests/demo-tests/pixelTest.js +0 -62
  150. package/tests/demo-tests/renderDemos.html +0 -132
  151. package/tests/demo-tests/serializationTest.js +0 -36
  152. package/tests/demo-tests/serializeDemos.html +0 -134
  153. package/tests/unit-tests/README.md +0 -4
  154. package/tests/unit-tests/jasmine-browser.json +0 -21
  155. package/tests/unit-tests/jasmine.json +0 -14
  156. package/tests/unit-tests/testSpec.js +0 -274
@@ -1,316 +0,0 @@
1
- import { DataType, ItemType, LayoutType } from "../../util/Constants";
2
- import Path from "../mark/Path";
3
- import PointText from "../mark/PointText";
4
- import Group from "../composite/Group";
5
- import * as d3 from 'd3';
6
- import Axis from "./Axis";
7
- import { sameClass } from "../../util/ItemUtil";
8
-
9
-
10
- export default class LayoutAxis extends Axis {
11
-
12
- constructor(items, layout, channel, field, args) {
13
- super(args);
14
- this._channel = channel;
15
- this._orientation = "orientation" in args ? args["orientation"] :
16
- this._channel === "x" || this._channel == "width" ? "bottom" : "left";
17
- this._posArg = this._channel == "x" || this._channel == "width"? args["pathY"] : args["pathX"];
18
- this._padding = [ItemType.Line, ItemType.Path].indexOf(items[0].type) >= 0 ? 10 : 0;
19
-
20
- this._item = items[0];
21
- this._items = items;
22
- this._mlayout = layout;
23
- this._field = field;
24
- this._titleText = "title" in args ? args["title"] : this._field;
25
- this._showTitle = "showTitle" in args ? args.showTitle : false;
26
-
27
- // if ("labelRotation" in args)
28
- // this._labelRotation = args.labelRotation;
29
-
30
- this._ticks = new Group();
31
- this._ticks.id = this.id + "ticks";
32
- this.addChild(this._ticks);
33
-
34
- this._labels = new Group();
35
- this._labels.id = this.id + "labels";
36
- this.addChild(this._labels);
37
-
38
- //there can be multiple rules if the layout has multiple rows or columns
39
- this._rules = new Group();
40
- this._rules.id = this.id + "paths";
41
- this.addChild(this._rules);
42
-
43
- this._generatePath();
44
- this._generateTicks();
45
- this._generateLabels();
46
- if (this._showTitle) {
47
- this._generateTitle();
48
- }
49
- this._positionPath();
50
- this._positionTicks();
51
- this._positionLabels();
52
- if (this._showTitle) {
53
- this._positionTitle();
54
- }
55
-
56
- }
57
-
58
- toJSON() {
59
- let json = super.toJSON();
60
- json.args.item = this._item.id;
61
- if (this._channel == "x" || this._channel == "width")
62
- json.args.pathY = this._posArg;
63
- else
64
- json.args.pathX = this._posArg;
65
- if (this.classId)
66
- json.classId = this.classId;
67
- return json;
68
- }
69
-
70
- set strokeColor(c) {
71
- this._strokeColor = c;
72
- for (let t of this._ticks.children)
73
- t.strokeColor = c;
74
- for (let t of this._rules.children)
75
- t.strokeColor = c;
76
- }
77
-
78
- get strokeColor() {
79
- return this._strokeColor;
80
- }
81
-
82
- set textColor(c) {
83
- this._textColor = c;
84
- for (let l of this._labels.children)
85
- l.fillColor = c;
86
- if (this._title)
87
- this._title.fillColor = c;
88
- }
89
-
90
- get textColor() {
91
- return this._textColor;
92
- }
93
-
94
- get layout() {
95
- return this._mlayout;
96
- }
97
-
98
- _updateBounds() {
99
- this._bounds = this._rules.bounds.clone();
100
- this._bounds = this._bounds.union(this._ticks.bounds);
101
- this._bounds = this._bounds.union(this._labels.bounds);
102
- if (this._showTitle)
103
- this._bounds = this._bounds.union(this._title.bounds);
104
- }
105
-
106
- _generatePath(){
107
- this._rules.removeAll();
108
- if (this._mlayout.type == LayoutType.Grid) {
109
- let num = this._channel == "x" ? this._mlayout.numRows : this._mlayout.numCols;
110
- for (let i = 0; i < num; i++) {
111
- let t = new Path({"strokeColor": this._strokeColor});
112
- if (!this._pathVisible)
113
- t.visibility = "hidden";
114
- t.type = ItemType.Line;
115
- t.id = this.id + "rule" + i;
116
- this._rules.addChild(t);
117
- }
118
- } else if (this._mlayout.type === LayoutType.Stack) {
119
- let t = new Path({"strokeColor": this._strokeColor});
120
- if (!this._pathVisible)
121
- t.visibility = "hidden";
122
- t.type = ItemType.Line;
123
- t.id = this.id + "rule";
124
- this._rules.addChild(t);
125
- }
126
- }
127
-
128
- _generateTicks() {
129
- this._ticks.removeAll();
130
- for (let i = 0; i < this._mlayout.group.children.length; i++) {
131
- let t = new Path({"strokeColor": this._strokeColor});
132
- if (!this._tickVisible)
133
- t.visibility = "hidden";
134
- t.type = ItemType.Line;
135
- t.id = this.id + "tick" + i;
136
- this._ticks.addChild(t);
137
- }
138
- }
139
-
140
- //TODO: improve efficiency by reusing components
141
- _generateLabels() {
142
- this._labels.removeAll();
143
- let formatter, fieldType = this._item.dataScope.getFieldType(this._field);
144
-
145
- switch (fieldType) {
146
- case DataType.Date:
147
- formatter = d3.timeFormat(this._labelFormat);
148
- break;
149
- case DataType.String:
150
- formatter = function(d) {return d;};
151
- break;
152
- default:
153
- formatter = d3.format(this._labelFormat);
154
- break;
155
- }
156
-
157
- let cb = this._mlayout.cellBounds;
158
- for (let i = 0; i < cb.length; i++) {
159
- if (i >= this._mlayout.group.children.length) break;
160
- let itm = this._mlayout.group.children[i];
161
- let t = new PointText({fillColor: this._textColor, fontSize: this._fontSize, "text": formatter(itm.dataScope.getFieldValue(this._field))});
162
- //let t = new PointText({fillColor: this._textColor, fontSize: this._fontSize, "text": formatter(this._items[i].dataScope.getFieldValue(this._field))});
163
- t.id = this.id + "label" + i;
164
- this._labels.addChild(t);
165
- }
166
- }
167
-
168
- _positionPath(){
169
- if (this._mlayout.type == LayoutType.Grid) {
170
- let cb = this._mlayout.cellBounds;
171
- let num = this._channel == "x" ? this._mlayout.numRows : this._mlayout.numCols;
172
- if (this._channel == "x") {
173
- let left = cb[0].left, numCols = this._mlayout.numCols;
174
- let padding = this._orientation === "bottom" ? this._padding : - this._padding;
175
- for (let r = 0; r < num; r++){
176
- this._rules.children[r]._setVertices([
177
- [left, this._posArg ? cb[r * numCols][this._orientation] + this._posArg - cb[0][this._orientation] : cb[r * numCols][this._orientation] + padding],
178
- [left + cb[0].width * numCols + this._mlayout.colGap * (numCols - 1), this._posArg ? cb[r * numCols][this._orientation] + this._posArg - cb[0][this._orientation] : cb[r * numCols][this._orientation] + padding]
179
- ]);
180
- }
181
- } else {
182
- let top = cb[0].top, numRows = this._mlayout.numRows;
183
- let padding = this._orientation === "left" ? this._padding : - this._padding;
184
- for (let c = 0; c < num; c++){
185
- // this._rules.children[c]._setVertices([
186
- // [this._posArg ? cb[c * numRows][this._orientation] + this._posArg - cb[0][this._orientation] : cb[c * numRows][this._orientation], top ],
187
- // [this._posArg ? cb[c * numRows][this._orientation] + this._posArg - cb[0][this._orientation] : cb[c * numRows][this._orientation], top + cb[0].height * numRows + this._mlayout.rowGap * (numRows - 1), ]
188
- // ]);
189
- this._rules.children[c]._setVertices([
190
- [this._posArg ? cb[c * numRows][this._orientation] + this._posArg - cb[0][this._orientation] : this._mlayout.group.bounds[this._orientation] - padding, top ],
191
- [this._posArg ? cb[c * numRows][this._orientation] + this._posArg - cb[0][this._orientation] : this._mlayout.group.bounds[this._orientation] - padding, top + cb[0].height * numRows + this._mlayout.rowGap * (numRows - 1)]
192
- ]);
193
- }
194
- }
195
- } else if (this._mlayout.type === LayoutType.Stack) {
196
- let b = this._mlayout.group.bounds;
197
- if (this._channel == "x") {
198
- this._rules.children[0]._setVertices([
199
- [b.left, this._posArg ? this._posArg : b[this._orientation] ],
200
- [b.right, this._posArg ? this._posArg : b[this._orientation]]
201
- ]);
202
- } else {
203
- this._rules.children[0]._setVertices([
204
- [this._posArg ? this._posArg : b[this._orientation], b.top ],
205
- [this._posArg ? this._posArg : b[this._orientation], b.bottom ]
206
- ]);
207
- }
208
- }
209
- this._rules.children.forEach(r => r._updateBounds());
210
- this._rules._updateBounds();
211
- this._updateBounds();
212
- }
213
-
214
- _positionTicks(){
215
- let cb = this._mlayout.cellBounds;
216
- if (this._channel == "x") {
217
- let dir = this._orientation == "bottom" ? 1 : -1;
218
- let padding = this._orientation === "bottom" ? this._padding : - this._padding;
219
- for (let [i, t] of this._ticks.children.entries()) {
220
- let pos = this._posArg ? cb[i][this._orientation] + this._posArg - cb[0][this._orientation] + this._tickOffset * dir :
221
- cb[i][this._orientation] + this._tickOffset * dir + padding;
222
- t._setVertices([
223
- [cb[i].x, pos],
224
- [cb[i].x, pos + dir * this._tickSize]
225
- ]);
226
- t._updateBounds();
227
- }
228
- } else if (this._channel == "y"){
229
- let dir = this._orientation == "left" ? -1 : 1;
230
- let padding = this._orientation === "left" ? this._padding : - this._padding;
231
- for (let [i, t] of this._ticks.children.entries()) {
232
- // let xPos = this._posArg ? cb[i][this._orientation] + this._posArg - cb[0][this._orientation] + this._tickOffset * dir :
233
- // cb[i][this._orientation] + this._tickOffset * dir,
234
- let xPos = this._posArg ? cb[i][this._orientation] + this._posArg - cb[0][this._orientation] + this._tickOffset * dir :
235
- this._mlayout.group.bounds[this._orientation] + this._tickOffset * dir - padding,
236
- yPos = this._tickAnchor == "middle" ? cb[i].y : cb[i][this._tickAnchor];
237
- t._setVertices([
238
- [xPos, yPos],
239
- [xPos + dir * this._tickSize, yPos]
240
- ]);
241
- t._updateBounds();
242
- }
243
- }
244
- this._ticks._updateBounds();
245
- this._updateBounds();
246
- }
247
-
248
- _positionLabels(){
249
- let cb = this._mlayout.cellBounds;
250
- if (this._channel == "x") {
251
- let anchor = this._orientation == "bottom" ? ["center", "top"] : ["center", "bottom"],
252
- offset = this._orientation == "bottom" ? this._labelOffset : -this._labelOffset;
253
- let padding = this._orientation === "bottom" ? this._padding : - this._padding;
254
- for (let [i, l] of this._labels.children.entries()) {
255
- l.x = cb[i].x;
256
- l.y = this._posArg ? cb[i][this._orientation] + this._posArg - cb[0][this._orientation] + offset :
257
- cb[i][this._orientation] + offset + padding;
258
- l.anchor = anchor;
259
- if (this._labelRotation){
260
- l._rotate = [this._labelRotation, l.x, l.y];
261
- l.anchor = ["right", anchor[1]];
262
- }
263
-
264
- }
265
- } else if (this._channel == "y"){
266
- let anchor = this._orientation == "left" ? ["right", "middle"] : ["left", "middle"],
267
- offset = this._orientation == "left" ? - this._labelOffset : this._labelOffset;
268
- let padding = this._orientation === "left" ? this._padding : - this._padding;
269
- for (let [i, l] of this._labels.children.entries()) {
270
- // l.x = this._posArg ? cb[i][this._orientation] + this._posArg - cb[0][this._orientation] + offset
271
- // : cb[i][this._orientation] + offset;
272
- l.x = this._posArg ? cb[i][this._orientation] + this._posArg - cb[0][this._orientation] + offset
273
- : this._mlayout.group.bounds[this._orientation] + offset - padding;
274
- l.y = this._tickAnchor == "middle" ? cb[i].y : cb[i][this._tickAnchor];
275
- l.anchor = anchor;
276
- if (this._labelRotation) {
277
- l._rotate = [this._labelRotation, l.x, l.y];
278
- }
279
- }
280
- }
281
- this._labels._updateBounds();
282
- this._updateBounds();
283
- }
284
-
285
- _positionTitle(){
286
- let pb = this._rules.bounds;
287
- this._title.achor = this._titleAnchor;
288
- if (!this._titlePosition) {
289
- if (this._channel == "x") {
290
- this._title.x = pb.x;
291
- this._titleOffset = this._labels.bounds.height + this._labelOffset + 15;
292
- this._title.y = this._orientation == "top" ? pb.top - this._titleOffset : pb.bottom + this._titleOffset;
293
- } else {
294
- this._titleOffset = this._labels.bounds.width + this._labelOffset + 15;
295
- this._title.x = this._orientation == "left" ? pb.left - this._titleOffset : pb.right + this._titleOffset;
296
- this._title.y = pb.y;
297
- if (this._rotateYTitle)
298
- this._title._rotate = this._orientation == "left" ? [-90, this._title.bounds.x, this._title.bounds.y] : [90, this._title.bounds.x, this._title.bounds.y];
299
- }
300
- } else {
301
- this._title.x = this._titlePosition[0];
302
- this._title.y = this._titlePosition[1];
303
- if (this._channel == "y" || this._channel == "height") {
304
- if (this._rotateYTitle)
305
- this._title._rotate = this._orientation == "left" ? [-90, this._title.bounds.x, this._title.bounds.y] : [90, this._title.bounds.x, this._title.bounds.y];
306
- }
307
- }
308
- this._title._updateBounds();
309
- this._updateBounds();
310
- }
311
-
312
- matches(item) {
313
- return sameClass(this._item, item);
314
- //return getEncodingKey(this._item).split("_")[0] === getEncodingKey(item).split("_")[0];
315
- }
316
- }
@@ -1,273 +0,0 @@
1
- import Group from "../composite/Group";
2
- import { DataType, ItemType, Orientation } from "../../util/Constants";
3
- import PointText from "../mark/PointText";
4
- import { ItemCounter, getLeafItems, isPath, getEncodingKey } from "../../util/ItemUtil";
5
- import LinearGradient from "../../basic/Gradient";
6
- import DataTable from "../../data/DataTable";
7
- import { uniqueNumbers } from "../../util/DataUtil";
8
- import GridLayout from "../../layout/Grid";
9
-
10
-
11
- export default class Legend extends Group {
12
-
13
- constructor(encoding, args) {
14
- super();
15
- this.type = ItemType.Legend;
16
- this.id = this.type + ItemCounter[this.type]++;
17
- this.encoding = encoding;
18
- this._textColor = ("textColor" in args) ? args["textColor"] : "#555";
19
- this._strokeColor = ("strokeColor" in args) ? args["strokeColor"] : "#555";
20
- this._fontSize = "fontSize" in args? args.fontSize: "12px";
21
- this._x = ("x" in args) ? args["x"] : 0;
22
- this._y = ("y" in args) ? args["y"] : 0;
23
- this._showTitle = ("showTitle" in args) ? args["showTitle"] : true;
24
- this._orientation = ("orientation" in args) ? args["orientation"] : Orientation.Vertical;
25
-
26
- //for categorical legend
27
- if (!("numCols" in args) && !("numRows" in args)) {
28
- if (this._orientation === Orientation.Vertical)
29
- this._numCols = 1;
30
- else
31
- this._numRows = 1;
32
- }
33
- else {
34
- this._numCols = args["numCols"];
35
- this._numRows = args["numRows"];
36
- }
37
- this._initialize();
38
- }
39
-
40
- toJSON(){
41
- let json = super.toJSON();
42
- if (!("args" in json))
43
- json.args = {};
44
- json.args.textColor = this._textColor;
45
- json.channel = this.encoding.channel;
46
- json.field = this.encoding.field;
47
- json.args.strokeColor = this._strokeColor;
48
- json.args.x = this._x;
49
- json.args.y = this._y;
50
- json.args.orientation = this._orientation;
51
- return json;
52
- }
53
-
54
- get field() {
55
- return this.encoding.field;
56
- }
57
-
58
- get channel() {
59
- return this.encoding.channel;
60
- }
61
-
62
- get fieldType() {
63
- return this.encoding.datatable.getFieldType(this.field);
64
- }
65
-
66
- _initialize() {
67
- let scene = this.encoding.scene, f = this.encoding.field;
68
- switch (this.encoding.datatable.getFieldType(f)) {
69
- case DataType.String:
70
- this._createCategoricalColorLegend(scene, f);
71
- break;
72
- case DataType.Date:
73
- case DataType.Number:
74
- case DataType.Integer:
75
- this._createNumericalColorLegend(scene, f);
76
- break;
77
- }
78
- this._updateBounds();
79
- }
80
-
81
- _createNumericalColorLegend(scene, f) {
82
- let wd, ht;
83
- if (this._orientation == Orientation.Vertical) {
84
- wd = 15;
85
- ht = 300;
86
- } else {
87
- wd = 300;
88
- ht = 15;
89
- }
90
- let titleSize;
91
- if (this._showTitle){
92
- let title = scene.mark("text", {fillColor: this._textColor, "text": f, x: this._x + wd/2, y: this._y, "anchor": ["center", "middle"]});
93
- this.addChild(title);
94
- titleSize = 20;
95
- } else {
96
- titleSize = 0;
97
- }
98
-
99
- let rect = scene.mark("rect", {"top": this._y + titleSize, "left": this._x, "width": wd, "height": ht, "strokeWidth": 0, opacity: this.encoding.anyItem.opacity});
100
- let domain = [Math.min(...this.encoding.data), Math.max(...this.encoding.data)], mapping = this.encoding.scale.mapping;
101
- let gradient;
102
- let texts = [], ticks = [], offset = 5, tickSize = 5;
103
- if (mapping) {
104
- let values = Object.keys(mapping).map(d => parseFloat(d)).sort((a,b) => a - b);
105
- if (this._orientation == Orientation.Vertical) {
106
- gradient = new LinearGradient({x1: 0, y1: 100, x2: 0, y2: 0});
107
- values.forEach(d => {
108
- let p = (d - domain[0])/(domain[1] - domain[0]);
109
- gradient.addStop(p*100, mapping[d], 1.0);
110
- let tk = scene.mark("line", {"x1": this._x + wd, "x2": this._x + wd + tickSize, "y1": this._y + ht - p * ht + titleSize, "y2": this._y + ht - p * ht+ titleSize, "strokeColor": this._strokeColor});
111
- ticks.push(tk);
112
- let t = scene.mark("text", {fillColor: this._textColor, "text": d.toFixed(0), x: this._x + wd + offset + tickSize, y: this._y + ht - p * ht + titleSize, "anchor": ["left", "middle"]});
113
- texts.push(t);
114
- })
115
- } else {
116
- gradient = new LinearGradient({x1: 0, y1: 0, x2: 100, y2: 0});
117
- values.forEach(d => {
118
- let p = (d - domain[0])/(domain[1] - domain[0]);
119
- gradient.addStop(p*100, mapping[d], 1.0);
120
- let tk = scene.mark("line", {"x1": this._x + p * wd, "x2": this._x + p * wd, "y1": this._y + 20 - tickSize + titleSize, "y2": this._y + ht + tickSize + titleSize, "strokeColor": this._strokeColor});
121
- ticks.push(tk);
122
- let t = scene.mark("text", {fillColor: this._textColor, "text": d.toFixed(0), x: this._x + p * wd, y: this._y + ht + offset + titleSize, "anchor": ["center", "top"]});
123
- texts.push(t);
124
- })
125
- }
126
- } else {
127
- let domain = this.encoding.scale.domain, dt = this.encoding.datatable, ft = dt.getFieldType(f);
128
- let stops = [], uniqueVals = ft === DataType.Date? dt.getUniqueFieldValues(f) : uniqueNumbers(this.encoding.data);
129
- if (uniqueVals.length <= 10){
130
- stops = uniqueVals;
131
- stops.sort((a, b) => a - b);
132
- } else {
133
- if (ft === DataType.Date) {
134
- uniqueVals.sort((a, b) => a - b);
135
- for (let i = 0; i < uniqueVals.length; i+= Math.ceil(uniqueVals.length/10))
136
- stops.push(uniqueVals[i]);
137
- } else {
138
- let incr = (domain[1] - domain[0])/9;
139
- for (let i = 0; i < 10; i++)
140
- stops.push(domain[0] + i * incr);
141
- }
142
- }
143
- //determine decimal places
144
- let decimalPlaces = 0, interval = (stops[stops.length - 1] - stops[0])/stops.length;
145
- while (interval < 1) {
146
- interval *= 10;
147
- decimalPlaces++;
148
- }
149
- stops = stops.map(d => d.toFixed(decimalPlaces));
150
- if (this._orientation == Orientation.Vertical) {
151
- gradient = new LinearGradient({x1: 0, y1: 100, x2: 0, y2: 0});
152
- stops.forEach(d => {
153
- let p = (d - domain[0])/(domain[1] - domain[0]);
154
- gradient.addStop(p*100, this.encoding.scale.map(d), 1.0);
155
- let tk = scene.mark("line", {"x1": this._x + wd, "x2": this._x + wd + tickSize, "y1": this._y + ht - p * ht + titleSize, "y2": this._y + ht - p * ht + titleSize, "strokeColor": this._strokeColor});
156
- ticks.push(tk);
157
- let t = scene.mark("text", {fillColor: this._textColor, "text": ft === DataType.Date? dt.getRawValue(f, d) : d, x: this._x + wd + offset + tickSize, y: this._y + ht - p * ht + titleSize, "anchor": ["left", "middle"]});
158
- texts.push(t);
159
- });
160
- } else {
161
- gradient = new LinearGradient({x1: 0, y1: 0, x2: 100, y2: 0});
162
- stops.forEach(d => {
163
- let p = (d - domain[0])/(domain[1] - domain[0]);
164
- gradient.addStop(p*100, this.encoding.scale.map(d), 1.0);
165
- let tk = scene.mark("line", {"x1": this._x + p * wd, "x2": this._x + p * wd, "y1": this._y + ht + titleSize, "y2": this._y + ht + tickSize + titleSize, "strokeColor": this._strokeColor});
166
- ticks.push(tk);
167
- let t = scene.mark("text", {fillColor: this._textColor, "text": ft === DataType.Date? dt.getRawValue(f, d) : d, x: this._x + p * wd, y: this._y + ht + offset + titleSize, "anchor": ["center", "top"]});
168
- texts.push(t);
169
- })
170
- }
171
- }
172
- rect.styles.fillColor = gradient;
173
-
174
- this.addChild(rect);
175
- for (let t of texts)
176
- this.addChild(t);
177
- for (let tk of ticks)
178
- this.addChild(tk);
179
- }
180
-
181
- get textColor() {
182
- return this._textColor;
183
- }
184
-
185
- set textColor(c) {
186
- this._textColor = c;
187
- this.setTextColor(this);
188
- }
189
-
190
- get orientation() {
191
- return this._orientation;
192
- }
193
-
194
- set orientation(o) {
195
- this._orientation = o;
196
- this.removeAll();
197
- this._initialize();
198
- }
199
-
200
- setTextColor(itm) {
201
- if (!itm.children || itm.children.length === 0) return;
202
- for (let i of itm.children) {
203
- if (i.type === ItemType.PointText)
204
- i.fillColor = this._textColor;
205
- else if (i.children && i.children.length > 0) {
206
- this.setTextColor(i);
207
- }
208
- }
209
- }
210
-
211
- _createCategoricalColorLegend(scene, f) {
212
- let scale = this.encoding.scale;
213
- let dt = new DataTable(scale.domain.map(d => ({"category": d, "value": scale.map(d)})));
214
- let longestText = dt.getUniqueFieldValues("category").sort((a,b) => b.length - a.length)[0];
215
- let mark = this.encoding.anyItem;
216
- let sw = isPath(mark) && mark.closed ? mark.strokeWidth : 0;
217
- if (this._orientation === Orientation.Vertical) {
218
- let titleSize = 0;
219
- if (this._showTitle) {
220
- this.addChild(new PointText({fillColor: this._textColor, "fontSize": this._fontSize, "text": f, x: this._x, y: this._y, "anchor": ["left", "top"]}));
221
- titleSize = parseFloat(this._fontSize) + 5;
222
- }
223
- let rect = scene.mark("rect", {"top": this._y + 2 + titleSize, "left": this._x, "width": 10, "height": 10, "strokeWidth": sw, "strokeColor": mark.strokeColor, "opacity": mark.opacity});
224
- let text = scene.mark("text", {text: longestText, fillColor: this._textColor, "fontSize": this._fontSize, x: this._x + 20, y: this._y + titleSize + 12 + sw, "anchor": ["left", "bottom"]});
225
- let glyph = scene.glyph(rect, text);
226
- let coll = scene.repeat(glyph, dt);
227
- scene.encode(text, {"channel": "text", "field": "category", "_remember": false});
228
- scene.encode(rect, {"channel": "fillColor", "field": "category", "_remember": false, scale: scale});
229
- coll.layout = new GridLayout({"numCols": this._numCols, "numRows": this._numRows});
230
- this.addChild(coll);
231
- } else {
232
- //do not show title for now
233
- let rect = scene.mark("rect", {"top": this._y, "left": this._x, "width": 10, "height": 10, "strokeWidth": sw, "strokeColor": mark.strokeColor, "opacity": this.encoding.anyItem.opacity});
234
- let text = scene.mark("text", {text: longestText, fillColor: this._textColor, "fontSize": this._fontSize, x: this._x + 15, y: this._y, "anchor": ["left", "top"]});
235
- let glyph = scene.glyph(rect, text);
236
- let coll = scene.repeat(glyph, dt);
237
- scene.encode(text, {"channel": "text", "field": "category", "_remember": false});
238
- scene.encode(rect, {"channel": "fillColor", "field": "category", "_remember": false, scale: scale});
239
- coll.layout = new GridLayout({"numCols": this._numCols, "numRows": this._numRows, "colGap": 15});
240
- this.addChild(coll);
241
- }
242
-
243
- }
244
-
245
- pathHitTest(x, y) {
246
- let items = getLeafItems(this);
247
- for (let i = items.length - 1; i >= 0; i--) {
248
- let c = items[i];
249
- if (isPath(c) && c.contains(x, y))
250
- return c;
251
- }
252
- return null;
253
- }
254
-
255
- //item is a group or a mark or a vertex or segment
256
- matches(item) {
257
- let k = getEncodingKey(item).split("_")[0],
258
- encodings = this.encoding.scale.encodings;
259
- for (let enc of encodings) {
260
- let classId = getEncodingKey(enc.anyItem).split("_")[0];
261
- if (classId === k)
262
- return true;
263
- }
264
- return false;
265
- }
266
-
267
- _doTranslate(dx, dy) {
268
- super._doTranslate(dx, dy);
269
- this._x += dx;
270
- this._y += dy;
271
- }
272
-
273
- }
@@ -1,95 +0,0 @@
1
- import {Direction, Alignment} from "../util/Constants";
2
- import Matrix from "../basic/Matrix";
3
- import Rectangle from "../basic/Rectangle";
4
-
5
- /**
6
- ** Circular layout can not be applied to nested collections
7
- ** Primary use case: people garden
8
- ** For pie charts, use Partition
9
- ** For polar line graphs, area charts, weather radial etc. use Polar Transformation on a scene
10
- **/
11
-
12
- class CircularLayout {
13
-
14
- constructor(args) {
15
- this.type = "circular";
16
- this.center = args.hasOwnProperty("center") ? args["center"] : {x: 500, y:400};
17
- this.radius = args.hasOwnProperty("radius") ? args["radius"] : 200;
18
- this.startAngle = args.hasOwnProperty("startAngle") ? args["startAngle"] : 90;
19
- this.endAngle = args.hasOwnProperty("endAngle") ? args["endAngle"] : 450;
20
- this.direction = args.hasOwnProperty("direction") ? args["direction"] : Direction.Anticlockwise;
21
- }
22
-
23
- clone() {
24
- return new CircularLayout({
25
- center: {x: this.center.x, y: this.center.y},
26
- radius: this.radius,
27
- startAngle: this.startAngle,
28
- endAngle: this.endAngle,
29
- direction: this.direction
30
- });
31
- }
32
-
33
- run() {
34
- if (this.collection == undefined)
35
- return;
36
-
37
- let collection = this.collection;
38
- let scene = this.collection.getScene();
39
-
40
- let bounds = collection.children.map(d => d.unRotatedBounds);
41
- let wds = bounds.map(d => d.width),
42
- hts = bounds.map(d => d.height);
43
- let cellWidth = Math.max(...wds),
44
- cellHeight = Math.max(...hts);
45
-
46
- for (let i = 0; i < collection.children.length; i++) {
47
- let item = collection.children[i];
48
- let cellBounds = this._getCellBounds(item, scene, cellWidth, cellHeight);
49
-
50
- let cellCenter = cellBounds.center;
51
-
52
- let dx = this.center.x - cellCenter.x, dy = this.center.y - this.radius - cellCenter.y;
53
- let mx = new Matrix();
54
- mx._doTranslate(dx, dy);
55
-
56
- let angle = (this.endAngle - this.startAngle)/(collection.children.length+1);
57
-
58
- let mx1 = new Matrix();
59
- mx1.rotate(90 - (this.startAngle + angle * i), this.center);
60
-
61
- mx.prepend(mx1);
62
- item._matrix = mx;
63
- }
64
- this.collection._updateBounds();
65
- }
66
-
67
- //TODO: handle collections
68
- _getCellBounds(item, scene, cellWidth, cellHeight) {
69
- let left, top;
70
- let bounds = item.unRotatedBounds;
71
- switch (scene._cellAlign[item.classId].x) {
72
- case Alignment.Left:
73
- left = bounds.left;
74
- break;
75
- case Alignment.Center:
76
- left = bounds.center.x - cellWidth/2;
77
- break;
78
- case Alignment.Right:
79
- left = bounds.right - cellWidth;
80
- break;
81
- }
82
- switch(scene._cellAlign[item.classId].y) {
83
- case Alignment.Top:
84
- top = bounds.top;
85
- break;
86
- case Alignment.Middle:
87
- top = bounds.center.y - cellHeight/2;
88
- break;
89
- case Alignment.Bottom:
90
- top = bounds.bottom - cellHeight;
91
- break;
92
- }
93
- return new Rectangle(left, top, cellWidth, cellHeight);
94
- }
95
- }