mascot-vis 2.0.0 → 3.0.0

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 (157) hide show
  1. package/README.md +4 -3
  2. package/dist/mascot-es.js +27745 -0
  3. package/dist/mascot-min.js +186 -199
  4. package/dist/mascot-umd.js +27781 -0
  5. package/js/depGraphVis.js +66 -0
  6. package/package.json +23 -15
  7. package/src-new-ts/action/createElement.ts +91 -0
  8. package/src-new-ts/action/encode.js +20 -0
  9. package/src-new-ts/action/repeat.js +128 -0
  10. package/src-new-ts/action/traverseScene.js +41 -0
  11. package/src-new-ts/data/Network.js +2 -0
  12. package/src-new-ts/data/Scope.js +135 -0
  13. package/src-new-ts/data/Table.js +263 -0
  14. package/src-new-ts/data/Tree.js +3 -0
  15. package/src-new-ts/data/field.ts +115 -0
  16. package/src-new-ts/data/import.ts +96 -0
  17. package/src-new-ts/data/predicate.ts +82 -0
  18. package/src-new-ts/depgraph/DepGraph.js +178 -0
  19. package/src-new-ts/depgraph/Edge.js +9 -0
  20. package/src-new-ts/depgraph/SceneGraph2DepGraph.js +110 -0
  21. package/src-new-ts/depgraph/Signal.js +12 -0
  22. package/src-new-ts/depgraph/operator/BoundsEvaluator.js +30 -0
  23. package/src-new-ts/depgraph/operator/Dataflow.js +41 -0
  24. package/src-new-ts/depgraph/operator/DomainBuilder.js +50 -0
  25. package/src-new-ts/depgraph/updateDepGraph.js +45 -0
  26. package/src-new-ts/depgraph/variable/BoundsVar.js +81 -0
  27. package/src-new-ts/depgraph/variable/ChannelVar.js +17 -0
  28. package/src-new-ts/depgraph/variable/DataScopeVar.js +12 -0
  29. package/src-new-ts/depgraph/variable/DomainVar.js +15 -0
  30. package/src-new-ts/depgraph/variable/FieldVar.js +17 -0
  31. package/src-new-ts/depgraph/variable/LayoutParameter.js +8 -0
  32. package/src-new-ts/depgraph/variable/ScaleVar.js +13 -0
  33. package/src-new-ts/depgraph/variable/Variable.js +39 -0
  34. package/src-new-ts/element/gradient/LinearGradient.js +37 -0
  35. package/src-new-ts/element/group/Collection.js +109 -0
  36. package/src-new-ts/element/group/Group.js +307 -0
  37. package/src-new-ts/element/group/Scene.js +98 -0
  38. package/src-new-ts/element/mark/CircleMark.ts +85 -0
  39. package/src-new-ts/element/mark/Mark.ts +233 -0
  40. package/src-new-ts/element/mark/PathMark.js +483 -0
  41. package/src-new-ts/element/mark/Segment.js +29 -0
  42. package/src-new-ts/element/mark/Vertex.js +118 -0
  43. package/src-new-ts/encode/Scale.ts +115 -0
  44. package/src-new-ts/index.ts +19 -0
  45. package/src-new-ts/layout/Layout.ts +3 -0
  46. package/src-new-ts/render/CanvasRenderer.ts +24 -0
  47. package/src-new-ts/render/SVGRenderer.js +316 -0
  48. package/src-new-ts/util.ts +3 -0
  49. package/src-old/action/Classify.js +53 -0
  50. package/src-old/action/Densify.js +199 -0
  51. package/src-old/action/Partition.js +531 -0
  52. package/src-old/action/Repeat.js +106 -0
  53. package/src-old/action/Repopulate.js +44 -0
  54. package/src-old/action/Stratify.js +156 -0
  55. package/src-old/basic/Gradient.js +37 -0
  56. package/src-old/basic/Point.js +51 -0
  57. package/src-old/basic/Rectangle.js +63 -0
  58. package/src-old/bind/bindToAngle.js +56 -0
  59. package/src-old/bind/bindToAreaMark.js +360 -0
  60. package/src-old/bind/bindToColor.js +114 -0
  61. package/src-old/bind/bindToLink.js +81 -0
  62. package/src-old/bind/bindToPosition.js +283 -0
  63. package/src-old/bind/bindToRadialDistance.js +62 -0
  64. package/src-old/bind/bindToSize.js +235 -0
  65. package/src-old/bind/bindToText.js +60 -0
  66. package/src-old/bind/bindToThickness.js +100 -0
  67. package/src-old/constraint/AffixConstraint.js +129 -0
  68. package/src-old/constraint/AlignConstraint.js +58 -0
  69. package/src-old/core/Encoding.js +336 -0
  70. package/src-old/core/Scale.js +322 -0
  71. package/src-old/core/SceneLoader.js +290 -0
  72. package/src-old/core/SceneValidator.js +232 -0
  73. package/src-old/core/SpecExecutor.js +113 -0
  74. package/src-old/core/SpecGenerator.js +350 -0
  75. package/src-old/data/DataImporter.js +64 -0
  76. package/src-old/data/DataScope.js +124 -0
  77. package/src-old/data/DataTable.js +338 -0
  78. package/src-old/data/Network.js +106 -0
  79. package/src-old/data/Tree.js +251 -0
  80. package/src-old/data/transform/Bin.js +46 -0
  81. package/src-old/data/transform/Filter.js +48 -0
  82. package/src-old/data/transform/Groupby.js +18 -0
  83. package/src-old/data/transform/KDE.js +58 -0
  84. package/src-old/data/transform/Sort.js +14 -0
  85. package/src-old/data/transform/Split.js +5 -0
  86. package/src-old/data/transform/partition.js +46 -0
  87. package/src-old/history/UndoRedoStack +0 -0
  88. package/src-old/index.js +271 -0
  89. package/src-old/indexSVG.js +259 -0
  90. package/src-old/interaction/Interaction.js +91 -0
  91. package/src-old/interaction/MouseEvent.js +8 -0
  92. package/src-old/interaction/Selection.js +9 -0
  93. package/src-old/interaction/brush.js +362 -0
  94. package/src-old/item/Segment.js +29 -0
  95. package/src-old/item/Vertex.js +118 -0
  96. package/src-old/item/composite/Collection.js +106 -0
  97. package/src-old/item/composite/Glyph.js +19 -0
  98. package/src-old/item/composite/Group.js +310 -0
  99. package/src-old/item/composite/Scene.js +1251 -0
  100. package/src-old/item/mark/ArcPath.js +181 -0
  101. package/src-old/item/mark/AreaPath.js +78 -0
  102. package/src-old/item/mark/CirclePath.js +102 -0
  103. package/src-old/item/mark/EllipsePath.js +5 -0
  104. package/src-old/item/mark/Image.js +101 -0
  105. package/src-old/item/mark/LinkPath.js +118 -0
  106. package/src-old/item/mark/Mark.js +163 -0
  107. package/src-old/item/mark/Path.js +494 -0
  108. package/src-old/item/mark/PointText.js +201 -0
  109. package/src-old/item/mark/PolygonPath.js +64 -0
  110. package/src-old/item/mark/RectPath.js +88 -0
  111. package/src-old/item/mark/RingPath.js +92 -0
  112. package/src-old/item/refs/Axis.js +362 -0
  113. package/src-old/item/refs/EncodingAxis.js +515 -0
  114. package/src-old/item/refs/Gridlines.js +144 -0
  115. package/src-old/item/refs/LayoutAxis.js +316 -0
  116. package/src-old/item/refs/Legend.js +273 -0
  117. package/src-old/layout/Circular.js +95 -0
  118. package/src-old/layout/Force.js +52 -0
  119. package/src-old/layout/Grid.js +423 -0
  120. package/src-old/layout/Layout.js +13 -0
  121. package/src-old/layout/Packing.js +56 -0
  122. package/src-old/layout/Stack.js +264 -0
  123. package/src-old/layout/Strata.js +88 -0
  124. package/src-old/layout/Sugiyama.js +59 -0
  125. package/src-old/layout/TidyTree.js +105 -0
  126. package/src-old/layout/Treemap.js +87 -0
  127. package/src-old/renderer/SVGInteractionHandler.js +241 -0
  128. package/src-old/renderer/SVGRenderer.js +325 -0
  129. package/src-old/renderer/WebGLRenderer.js +1097 -0
  130. package/src-old/renderer/WebGLRenderer2.js +249 -0
  131. package/src-old/renderer/threejs/Line2.js +18 -0
  132. package/src-old/renderer/threejs/LineGeometry.js +77 -0
  133. package/src-old/renderer/threejs/LineMaterial.js +605 -0
  134. package/src-old/renderer/threejs/LineSegments2.js +281 -0
  135. package/src-old/renderer/threejs/LineSegmentsGeometry.js +226 -0
  136. package/src-old/renderer/threejs/Wireframe.js +51 -0
  137. package/src-old/renderer/threejs/WireframeGeometry2.js +16 -0
  138. package/src-old/scale/areaSize.js +0 -0
  139. package/src-old/scale/domain.js +38 -0
  140. package/src-old/util/Constants.js +180 -0
  141. package/src-old/util/DataUtil.js +35 -0
  142. package/src-old/util/ItemUtil.js +586 -0
  143. package/src-old/util/Numerical.js +33 -0
  144. package/tests/demo-tests/README.md +80 -0
  145. package/tests/demo-tests/SVG2PNG.js +56 -0
  146. package/tests/demo-tests/demos2CanvasPNGs.js +69 -0
  147. package/tests/demo-tests/demos2ScenesSVGs.js +100 -0
  148. package/tests/demo-tests/pathElementWorker.js +91 -0
  149. package/tests/demo-tests/pixelTest.js +62 -0
  150. package/tests/demo-tests/renderDemos.html +132 -0
  151. package/tests/demo-tests/serializationTest.js +36 -0
  152. package/tests/demo-tests/serializeDemos.html +134 -0
  153. package/tests/unit-tests/README.md +4 -0
  154. package/tests/unit-tests/jasmine-browser.json +21 -0
  155. package/tests/unit-tests/jasmine.json +14 -0
  156. package/tests/unit-tests/testSpec.js +274 -0
  157. package/dist/mascot.js +0 -24446
@@ -0,0 +1,515 @@
1
+ import { DataType, ItemType, LayoutType, Alignment } from "../../util/Constants";
2
+ import { getClosestLayout, getCellBoundsInGridLayout, getEncodingKey, getTopLevelCollection, getTopLevelGroup, getPeers } from "../../util/ItemUtil";
3
+ import Path from "../mark/Path";
4
+ import PointText from "../mark/PointText";
5
+ import Group from "../composite/Group";
6
+ import * as d3 from 'd3';
7
+ import Axis from "./Axis";
8
+ import { uniqueNumbers } from "../../util/DataUtil";
9
+
10
+ export default class EncodingAxis extends Axis {
11
+
12
+ //glyph is optional
13
+ constructor(encoding, item, args) {
14
+ super(args);
15
+
16
+ this.encoding = encoding;
17
+ this._field = this.encoding.field;
18
+ this._channel = this.encoding.channel;
19
+ this._orientation = "orientation" in args ? args["orientation"] :
20
+ this._channel === "x" || this._channel == "width" ? "bottom" : "left";
21
+
22
+ this._posArg = this._channel == "x" || this._channel == "width"? args["pathY"] : args["pathX"];
23
+ this._position = this._posArg;
24
+ this._titleText = "title" in args ? args["title"] : this.encoding.field;
25
+
26
+ this._item = item;
27
+
28
+ this._ticks = new Group();
29
+ this._ticks.id = this.id + "ticks";
30
+ this.addChild(this._ticks);
31
+
32
+ this._labels = new Group();
33
+ this._labels.id = this.id + "labels";
34
+ this.addChild(this._labels);
35
+
36
+ if (this._channel === "radialDistance"){
37
+ //this._position = this._item.parent.y;
38
+ if("rotation" in args){
39
+ this._rotate = [-args["rotation"], this._item.parent.x, this._item.parent.y];
40
+ }
41
+ }
42
+
43
+ this._showTitle = "showTitle" in args ? args.showTitle : true;
44
+
45
+ this._determineAxisFlip();
46
+ this._generatePath();
47
+ this._positionPath();
48
+ if (this._showTitle) {
49
+ this._generateTitle();
50
+ }
51
+
52
+ //ticks and labels are created and positioned when the values are set in scene.axis()
53
+
54
+ if (this._showTitle) {
55
+ this._positionTitle();
56
+ }
57
+ }
58
+
59
+ autoUpdateTicks() {
60
+ let vals = this.encoding._inferTickValues();
61
+ this.tickValues = vals;
62
+ this.labelValues = vals;
63
+ }
64
+
65
+ _updateBounds() {
66
+ this._bounds = this._path.bounds;
67
+ if (this._ticks.children.length > 0)
68
+ this._bounds = this._bounds.union(this._ticks.bounds);
69
+ if (this._labels.children.length > 0)
70
+ this._bounds = this._bounds.union(this._labels.bounds);
71
+ if (this._title)
72
+ this._bounds = this._bounds.union(this._title.bounds);
73
+ }
74
+
75
+ toJSON() {
76
+ let json = super.toJSON();
77
+ json.args.item = this._item.id;
78
+ if (this.encoding.scale.type === "time") {
79
+ json.args.isDate = true;
80
+ }
81
+ if (this._rotate) {
82
+ json.args.rotation = this._rotate[0];
83
+ }
84
+ if (this._channel == "x" || this._channel == "width")
85
+ json.args.pathY = this._posArg;
86
+ else
87
+ json.args.pathX = this._posArg;
88
+ return json;
89
+ }
90
+
91
+ get ticks() {
92
+ return this._ticks;
93
+ }
94
+
95
+ get labels() {
96
+ return this._labels;
97
+ }
98
+
99
+ get path() {
100
+ return this._path;
101
+ }
102
+
103
+ set strokeColor(c) {
104
+ this._strokeColor = c;
105
+ for (let t of this._ticks.children)
106
+ t.strokeColor = c;
107
+ this._path.strokeColor = c;
108
+ }
109
+
110
+ get strokeColor() {
111
+ return this._strokeColor;
112
+ }
113
+
114
+ set textColor(c) {
115
+ this._textColor = c;
116
+ for (let l of this._labels.children)
117
+ l.fillColor = c;
118
+ if (this._title)
119
+ this._title.fillColor = c;
120
+ }
121
+
122
+ get textColor() {
123
+ return this._textColor;
124
+ }
125
+
126
+ _generatePath(){
127
+ this._path = new Path({"strokeColor": this._strokeColor});
128
+ if (!this._pathVisible)
129
+ this._path.visibility = "hidden";
130
+ this._path.type = ItemType.Line;
131
+ this._path.id = this.id + "path";
132
+ this.addChild(this._path);
133
+ }
134
+
135
+ _generateTicks(){
136
+ this._ticks.removeAll();
137
+ for (let i = 0; i < this._tickValues.length; i++) {
138
+ let t = new Path({"strokeColor": this._strokeColor});
139
+ if (!this._tickVisible)
140
+ t.visibility = "hidden";
141
+ t.type = ItemType.Line;
142
+ t.id = this.id + "tick" + i;
143
+ this._ticks.addChild(t);
144
+ }
145
+ }
146
+
147
+ _generateLabels(){
148
+ this._labels.removeAll();
149
+ let formatter, fieldType = this.encoding.datatable.getFieldType(this.encoding.field);
150
+
151
+ switch (fieldType) {
152
+ case DataType.Date:
153
+ formatter = d3.timeFormat(this._labelFormat);
154
+ break;
155
+ case DataType.String:
156
+ formatter = function(d) {return d;};
157
+ break;
158
+ default:
159
+ formatter = d3.format(this._labelFormat);
160
+ break;
161
+ }
162
+
163
+ for (let [i, v] of this._labelValues.entries()) {
164
+ let t = new PointText({"text": formatter(v), fontSize: this._fontSize, fillColor: this._textColor});
165
+ t.id = this.id + "label" + i;
166
+ this._labels.addChild(t);
167
+ }
168
+ }
169
+
170
+ _positionPath(){
171
+ this._range = this.encoding.getScaleRange(this._item);
172
+ if (this._posArg === undefined)
173
+ this._position = this._computePosition();
174
+ else
175
+ this._position = this._posArg;
176
+
177
+ let vertices = [];
178
+ if (this._channel == "x" || this._channel == "radialDistance" || this._channel == "width") {
179
+ let tickX = this._ticks.children.map(d => d.vertices[0].x);
180
+ vertices.push([
181
+ Math.min(...tickX.concat(this._range)),
182
+ this._position
183
+ ]);
184
+ vertices.push([
185
+ Math.max(...tickX.concat(this._range)),
186
+ this._position
187
+ ]);
188
+ } else if (this._channel == "y" || this._channel == "height") {
189
+ let tickY = this._ticks.children.map(d => d.vertices[0].y);
190
+ vertices.push([
191
+ this._position,
192
+ Math.min(...tickY.concat(this._range))
193
+ ]);
194
+ vertices.push([
195
+ this._position,
196
+ Math.max(...tickY.concat(this._range))
197
+ ]);
198
+ }
199
+ this._path._setVertices(vertices);
200
+ this._path._updateBounds();
201
+
202
+ if (this._showTitle && this._title) {
203
+ this._positionTitle();
204
+ }
205
+
206
+ this._updateBounds();
207
+ }
208
+
209
+ _isAlignedLeft(layout) {
210
+ switch (layout.type) {
211
+ case LayoutType.Stack:
212
+ case LayoutType.Grid:
213
+ return layout.horzCellAlignment === Alignment.Left;
214
+ default:
215
+ return true;
216
+ }
217
+ }
218
+
219
+ _isAlignedBottom(layout) {
220
+ switch (layout.type) {
221
+ case LayoutType.Stack:
222
+ case LayoutType.Grid:
223
+ return layout.vertCellAlignment === Alignment.Bottom;
224
+ default:
225
+ return true;
226
+ }
227
+ }
228
+
229
+ _determineAxisFlip() {
230
+ if (this._channel == "x" || this._channel == "radialDistance" || this._channel == "width") {
231
+ if (this._channel == "width") {
232
+ let layout = getTopLevelCollection(this._item) ? getTopLevelCollection(this._item).layout : getClosestLayout(this._item);
233
+ if (layout) {
234
+ //let alignment = layout.type == LayoutType.Stack ? layout._horzCellAlignment == Alignment.Left : layout._cellHorzAlignment == Alignment.Left;
235
+ //this._flip = alignment? false : true;
236
+ this._flip = !this._isAlignedLeft(layout);
237
+ }
238
+ else if (this._item.type == "area"){
239
+ let alignment = this._item.baseline == Alignment.Left || this._item.baseline == Alignment.Center || this._item.baseline == Alignment.Middle || this._item.baseline == undefined;
240
+ this._flip = alignment? false : true;
241
+ }
242
+ }
243
+ } else if (this._channel == "y" || this._channel == "height") {
244
+ if (this._channel == "height") {
245
+ let layout = getTopLevelCollection(this._item) ? getTopLevelCollection(this._item).layout : getClosestLayout(this._item);
246
+ //TODO: bug here, example: Mystique D3-12. http://bl.ocks.org/peterbsmyth/raw/005ed081c4b654ad04ce/?raw=true
247
+ if (layout) {
248
+ this._flip = !this._isAlignedBottom(layout);
249
+ //this._flip = layout.vertCellAlignment !== Alignment.Bottom;
250
+ } else if (this._item.type == "area") {
251
+ let alignment = this._item.baseline == Alignment.Bottom || this._item.baseline == Alignment.Center || this._item.baseline == Alignment.Middle || this._item.baseline == undefined;
252
+ this._flip = alignment? false : true;
253
+ }
254
+ }
255
+ }
256
+ }
257
+
258
+
259
+ _positionLabels(){
260
+ if (this._posArg === undefined)
261
+ this._position = this._computePosition();
262
+ else
263
+ this._position = this._posArg;
264
+ if (this._channel == "x" || this._channel == "radialDistance" || this._channel == "width") {
265
+ let offset = this._orientation == "bottom" ? this._tickSize : - this._tickSize ;
266
+ let anchor = this._orientation == "bottom" ? ["center", "top"] : ["center", "bottom"];
267
+ // if (this._item.type == "area" && this._channel == "width") {
268
+ // let layout = getClosestLayout(this._item);
269
+ // if (layout) {
270
+ // //let alignment = layout.type == LayoutType.Stack ? layout._horzCellAlignment == Alignment.Left : layout._cellHorzAlignment == Alignment.Left;
271
+ // this._flip = !this._isAlignedLeft(layout);
272
+ // }
273
+ // else {
274
+ // let alignment = this._item.baseline == Alignment.Left || this._item.baseline == Alignment.Center || this._item.baseline == Alignment.Middle || this._item.baseline == undefined;
275
+ // this._flip = alignment? false : true;
276
+ // }
277
+ // }
278
+ if (this._flip) {
279
+ for (let [i, l] of this._labels.children.entries()) {
280
+ l.x = this._range[1] - this.encoding.scale.map(this._labelValues[i]);
281
+ l.y = this._position + offset;
282
+ l.anchor = anchor;
283
+ if (this._labelRotation){
284
+ l._rotate = [this._labelRotation, l.x, l.y];
285
+ l.anchor = ["right", anchor[1]];
286
+ }
287
+ }
288
+ } else if (this.encoding.scale.isFlipped) {
289
+ for (let [i, l] of this._labels.children.entries()) {
290
+ l.x = this._range[0] + this.encoding.scale.map(this._labelValues[i]);
291
+ l.y = this._position + offset;
292
+ l.anchor = anchor;
293
+ if (this._labelRotation){
294
+ l._rotate = [this._labelRotation, l.x, l.y];
295
+ l.anchor = ["right", anchor[1]];
296
+ }
297
+ }
298
+ } else {
299
+ for (let [i, l] of this._labels.children.entries()) {
300
+ l.x = this._range[0] + this.encoding.scale.map(this._labelValues[i]) - this.encoding.scale.range[0];
301
+ l.y = this._position + offset;
302
+ l.anchor = anchor;
303
+ if (this._labelRotation){
304
+ l._rotate = [this._labelRotation, l.x, l.y];
305
+ l.anchor = ["right", anchor[1]];
306
+ }
307
+ }
308
+ }
309
+ } else if (this._channel == "y" || this._channel == "height") {
310
+ let offset = this._orientation == "left" ? -this._tickSize : this._tickSize;
311
+ let anchor = this._orientation == "left" ? ["right", "middle"] : ["left", "middle"];
312
+ // if (this._item.type == "area" && this._channel == "height") {
313
+ // let layout = getClosestLayout(this._item);
314
+ // if (this._channel == "height" && layout) {
315
+ // // let alignment = layout.type == LayoutType.Stack ? layout._vertCellAlignment == Alignment.Bottom : layout._cellVertAlignment == Alignment.Bottom;
316
+ // // this._flip = alignment? false : true;
317
+ // this._flip = !this._isAlignedBottom(layout);
318
+ // }
319
+ // else {
320
+ // let alignment = this._item.baseline == Alignment.Bottom || this._item.baseline == Alignment.Center || this._item.baseline == Alignment.Middle || this._item.baseline == undefined;
321
+ // this._flip = alignment? false : true;
322
+ // }
323
+ // }
324
+ if (this._flip) {
325
+ for (let [i, l] of this._labels.children.entries()) {
326
+ l.x = this._position + offset;
327
+ l.y = this._range[1] + this.encoding.scale.map(this._labelValues[i]);
328
+ l.anchor = anchor;
329
+ }
330
+ } else if (this.encoding.scale.isFlipped) {
331
+ for (let [i, l] of this._labels.children.entries()) {
332
+ l.x = this._position + offset;
333
+ l.y = this._range[1] - this.encoding.scale.map(this._labelValues[i]) + this.encoding.scale.range[1];
334
+ l.anchor = anchor;
335
+ }
336
+ } else {
337
+ for (let [i, l] of this._labels.children.entries()) {
338
+ l.x = this._position + offset;
339
+ l.y = this._range[0] - this.encoding.scale.map(this._labelValues[i]) + this.encoding.scale.range[0];
340
+ l.anchor = anchor;
341
+ }
342
+ }
343
+ }
344
+ this._labels._updateBounds();
345
+ this._updateBounds();
346
+ }
347
+
348
+ _computePosition() {
349
+ let c;
350
+ if (this._item.type === "vertex" && !this._item.parent.closed) {
351
+ //only for vertices that share the same x or y positions
352
+ let peers = getPeers(this._item, this._item.parent.getScene());
353
+ if (this._channel === "x" && uniqueNumbers(peers.map(d => d.bounds.middle)).length == 1) {
354
+ return this._item.bounds.middle;
355
+ } else if (this._channel === "y" && uniqueNumbers(peers.map(d => d.bounds.center)).length == 1) {
356
+ return this._item.bounds.center;
357
+ } else if (this._channel === "radialDistance"){
358
+ return this._item.parent.y;
359
+ }
360
+ }
361
+
362
+ if (this._item.type === ItemType.Area || this._item.parent.type === ItemType.Area)
363
+ c = getCellBoundsInGridLayout(this._item);
364
+
365
+ if (c === undefined) {
366
+ let container = getTopLevelCollection(this._item);
367
+ if (container === undefined)
368
+ container = getTopLevelGroup(this._item);
369
+ c = container.bounds;
370
+ }
371
+ if (this._channel === "x" || this._channel === "width") {
372
+ return this._orientation == "top" ? c.top - this._tickSize : c.bottom + this._tickSize;
373
+ } else if (this._channel === "y" || this._channel === "height") {
374
+ return this._orientation == "left" ? c.left - this._tickSize : c.right + this._tickSize;
375
+ } else if (this._channel === "radialDistance"){
376
+ return this._item.parent.y;
377
+ }
378
+ }
379
+
380
+ _positionTicks() {
381
+ if (this._posArg === undefined)
382
+ this._position = this._computePosition();
383
+ else
384
+ this._position = this._posArg;
385
+ this._range = this.encoding.getScaleRange(this._item);
386
+ if (this._channel == "x" || this._channel == "radialDistance" || this._channel == "width") {
387
+ let offset = this._orientation == "bottom" ? this._tickSize : -this._tickSize;
388
+ // if (this._channel == "width") {
389
+ // let layout = getClosestLayout(this._item);
390
+ // if (layout) {
391
+ // //let alignment = layout.type == LayoutType.Stack ? layout._horzCellAlignment == Alignment.Left : layout._cellHorzAlignment == Alignment.Left;
392
+ // //this._flip = alignment? false : true;
393
+ // this._flip = !this._isAlignedLeft;
394
+ // }
395
+ // else if (this._item.type == "area"){
396
+ // let alignment = this._item.baseline == Alignment.Left || this._item.baseline == Alignment.Center || this._item.baseline == Alignment.Middle || this._item.baseline == undefined;
397
+ // this._flip = alignment? false : true;
398
+ // }
399
+ // }
400
+ if (this._flip) {
401
+ for (let [i, t] of this._ticks.children.entries()) {
402
+ t._setVertices([
403
+ [this._range[1] - this.encoding.scale.map(this._tickValues[i]), this._position],
404
+ [this._range[1] - this.encoding.scale.map(this._tickValues[i]), this._position + offset]
405
+ ]);
406
+ t._updateBounds();
407
+ }
408
+ } else if (this.encoding.scale.isFlipped) {
409
+ for (let [i, t] of this._ticks.children.entries()) {
410
+ t._setVertices([
411
+ [this._range[0] + this.encoding.scale.map(this._tickValues[i]), this._position],
412
+ [this._range[0] + this.encoding.scale.map(this._tickValues[i]), this._position + offset]
413
+ ]);
414
+ t._updateBounds();
415
+ }
416
+ } else {
417
+ for (let [i, t] of this._ticks.children.entries()) {
418
+ t._setVertices([
419
+ [this._range[0] + this.encoding.scale.map(this._tickValues[i]) - this.encoding.scale.range[0], this._position],
420
+ [this._range[0] + this.encoding.scale.map(this._tickValues[i]) - this.encoding.scale.range[0], this._position + offset]
421
+ ]);
422
+ t._updateBounds();
423
+ }
424
+ }
425
+ } else if (this._channel == "y" || this._channel == "height") {
426
+ let offset = this._orientation == "left" ? -this._tickSize : this._tickSize;
427
+ // if (this._channel == "height") {
428
+ // let layout = getClosestLayout(this._item);
429
+ // //TODO: bug here, example: Mystique D3-12. http://bl.ocks.org/peterbsmyth/raw/005ed081c4b654ad04ce/?raw=true
430
+ // if (layout) {
431
+ // this._flip = !this._isAlignedBottom(layout);
432
+ // //this._flip = layout.vertCellAlignment !== Alignment.Bottom;
433
+ // } else if (this._item.type == "area") {
434
+ // let alignment = this._item.baseline == Alignment.Bottom || this._item.baseline == Alignment.Center || this._item.baseline == Alignment.Middle || this._item.baseline == undefined;
435
+ // this._flip = alignment? false : true;
436
+ // }
437
+ // }
438
+ if (this._flip) {
439
+ for (let [i, t] of this._ticks.children.entries()) {
440
+ t._setVertices([
441
+ [this._position + offset, this._range[1] + this.encoding.scale.map(this._tickValues[i])],
442
+ [this._position, this._range[1] + this.encoding.scale.map(this._tickValues[i])]
443
+ ]);
444
+ t._updateBounds();
445
+ }
446
+ } else if (this.encoding.scale.isFlipped) {
447
+ for (let [i, t] of this._ticks.children.entries()) {
448
+ let y = this._range[1] - this.encoding.scale.map(this._tickValues[i]) + this.encoding.scale.range[1];
449
+ //this._range[1] + this.encoding.scale.map(this._tickValues[i])
450
+ t._setVertices([
451
+ [this._position + offset, y],
452
+ [this._position, y]
453
+ ]);
454
+ t._updateBounds();
455
+ }
456
+ } else {
457
+ for (let [i, t] of this._ticks.children.entries()) {
458
+ t._setVertices([
459
+ [this._position + offset, this._range[0] - this.encoding.scale.map(this._tickValues[i]) + this.encoding.scale.range[0]],
460
+ [this._position, this._range[0] - this.encoding.scale.map(this._tickValues[i]) + this.encoding.scale.range[0]]
461
+ ]);
462
+ t._updateBounds();
463
+ }
464
+ }
465
+ }
466
+ this._positionPath();
467
+ this._ticks._updateBounds();
468
+ this._updateBounds();
469
+ }
470
+
471
+ _positionTitle(){
472
+ let pb = this._path.bounds;
473
+ this._title.achor = this._titleAnchor;
474
+ if (!this._titlePosition) {
475
+ if (this._channel == "x" || this._channel == "width") {
476
+ this._title.x = pb.x;
477
+ this._title.y = this._orientation == "top" ? pb.top - this._titleOffset : pb.bottom + this._titleOffset;
478
+ } else {
479
+ this._title.x = this._orientation == "left" ? pb.left - this._titleOffset : pb.right + this._titleOffset;
480
+ this._title.y = pb.y;
481
+ if (this._rotateYTitle)
482
+ this._title._rotate = this._orientation == "left" ? [-90, this._title.bounds.x, this._title.bounds.y] : [90, this._title.bounds.x, this._title.bounds.y];
483
+ }
484
+ } else {
485
+ this._title.x = this._titlePosition[0];
486
+ this._title.y = this._titlePosition[1];
487
+ if (this._channel == "y" || this._channel == "height") {
488
+ if (this._rotateYTitle)
489
+ this._title._rotate = this._orientation == "left" ? [-90, this._title.bounds.x, this._title.bounds.y] : [90, this._title.bounds.x, this._title.bounds.y];
490
+ }
491
+ }
492
+ this._title._updateBounds();
493
+ this._updateBounds();
494
+ }
495
+
496
+ //item is a group or a mark or a vertex or segment
497
+ matches(item) {
498
+ let k = getEncodingKey(item).split("_")[0],
499
+ encodings = this.encoding.scale.encodings;
500
+ for (let enc of encodings) {
501
+ let classId = getEncodingKey(enc.anyItem).split("_")[0];
502
+ if (classId === k)
503
+ return true;
504
+ }
505
+ return false;
506
+ }
507
+
508
+ get isFlipped() {
509
+ if (this._flip)
510
+ return true;
511
+ if (this.encoding.scale.isFlipped)
512
+ return true;
513
+ return false;
514
+ }
515
+ }
@@ -0,0 +1,144 @@
1
+ import { ItemType } from "../../util/Constants";
2
+ import { getEncodingKey, getTopLevelCollection, getTopLevelGroup, ItemCounter } from "../../util/ItemUtil";
3
+ import Path from "../mark/Path";
4
+ import Group from "../composite/Group";
5
+ import CirclePath from "../mark/CirclePath";
6
+
7
+ export default class Gridlines extends Group {
8
+
9
+ constructor(encoding, item, args) {
10
+ super();
11
+ this.type = ItemType.Gridlines;
12
+ this.id = this.type + ItemCounter[this.type]++;
13
+
14
+ this.encoding = encoding;
15
+ this.channel = this.encoding.channel;
16
+ this._item = item;
17
+
18
+ this._strokeColor = ("strokeColor" in args) ? args["strokeColor"] : "#ddd";
19
+ this._strokeWidth = ("strokeWidth" in args) ? args["strokeWidth"] : 1;
20
+
21
+ if (this.channel == "radialDistance"){
22
+ if("angle" in args){
23
+ this._rotate = [-args["angle"], this.encoding.x, this.encoding.y];
24
+ }
25
+ }
26
+ }
27
+
28
+ toJSON(){
29
+ // let json = {args: {}};
30
+ let json = super.toJSON();
31
+ json.type = this.type;
32
+ json.id = this.id;
33
+ if (!("args" in json))
34
+ json.args = {};
35
+ json.args.item = this._item.id;
36
+ json.args.strokeColor = this._strokeColor;
37
+ json.args.strokeWidth = this._strokeWidth;
38
+ json.args.values = this._values;
39
+ if (this.encoding.scale.type === "time") {
40
+ json.args.isDate = true;
41
+ }
42
+ json.channel = this.encoding.channel;
43
+ json.field = this.encoding.field;
44
+ if (this._rotate)
45
+ json.args.angle = this._rotate[0];
46
+ return json;
47
+ }
48
+
49
+ get values() {
50
+ return this._values;
51
+ }
52
+
53
+ set values(values) {
54
+ this._values = values;
55
+ this.updateLines();
56
+ this.updateLinePositions();
57
+ }
58
+
59
+ get strokeColor() {
60
+ return this._strokeColor;
61
+ }
62
+
63
+ set strokeColor(c) {
64
+ this._strokeColor = c;
65
+ for (let p of this.children)
66
+ p.strokeColor = c;
67
+ }
68
+
69
+ get strokeWidth() {
70
+ return this._strokeWidth;
71
+ }
72
+
73
+ set strokeWidth(w) {
74
+ this._strokeWidth = w;
75
+ for (let p of this.children)
76
+ p.strokeWidth = w;
77
+ }
78
+
79
+ matches(item) {
80
+ let k = getEncodingKey(item).split("_")[0],
81
+ encodings = this.encoding.scale.encodings;
82
+ for (let enc of encodings) {
83
+ let classId = getEncodingKey(enc.anyItem).split("_")[0];
84
+ if (classId === k)
85
+ return true;
86
+ }
87
+ return false;
88
+ }
89
+
90
+ updateLinePositions() {
91
+ let container = getTopLevelCollection(this._item) ? getTopLevelCollection(this._item) : getTopLevelGroup(this._item);
92
+ if (this.channel == "x" || this.channel == "width") {
93
+ let bounds = container.bounds,
94
+ range = this.encoding.getScaleRange(this._item);
95
+ for (let [i, l] of this.children.entries()) {
96
+ let x = range[0] + this.encoding.scale.map(this._values[i]) - this.encoding.scale.range[0];
97
+ l._setVertices([[x, bounds.top], [x, bounds.bottom]]);
98
+ }
99
+ } else if (this.channel == "y" || this.channel == "height") {
100
+ let bounds = container.bounds,
101
+ range = this.encoding.getScaleRange(this._item);
102
+ if (this.encoding.flip) {
103
+ for (let [i, l] of this.children.entries()) {
104
+ let y = range[1] - this.encoding.scale.map(this._values[i]) + this.encoding.scale.range[0];
105
+ l._setVertices([[bounds.left, y], [bounds.right, y]]);
106
+ }
107
+ } else {
108
+ for (let [i, l] of this.children.entries()) {
109
+ let y = range[0] - this.encoding.scale.map(this._values[i]) + this.encoding.scale.range[0];
110
+ l._setVertices([[bounds.left, y], [bounds.right, y]]);
111
+ }
112
+ }
113
+ } else if (this.channel == "radialDistance") {
114
+ for (let [i, c] of this.children.entries()) {
115
+ c.x = this._item.parent.x;
116
+ c.y = this._item.parent.y;
117
+ c.radius = this.encoding.scale.map(this._values[i]);
118
+ }
119
+ }
120
+ for (let c of this.children)
121
+ c._updateBounds();
122
+ this._updateBounds();
123
+ }
124
+
125
+ updateLines() {
126
+ this.children = [];
127
+ if (this.channel == "x" || this.channel == "y" || this.channel == "width" || this.channel == "height") {
128
+ for (let i = 0; i < this._values.length; i++) {
129
+ let t = new Path ({"strokeColor": this._strokeColor, "fillColor": "none", "strokeWidth": this._strokeWidth});
130
+ t.type = ItemType.Line;
131
+ t.id = this.id + "line" + i;
132
+ this.addChild(t);
133
+ }
134
+ } else if (this.channel == "radialDistance") {
135
+ for (let i = 0; i < this._values.length; i++) {
136
+ let t = new CirclePath({"strokeColor": this._strokeColor, "fillColor": "none", "strokeWidth": this._strokeWidth});
137
+ t.type = ItemType.Circle;
138
+ t.id = this.id + "line" + i;
139
+ this.addChild(t);
140
+ }
141
+ }
142
+ }
143
+
144
+ }