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,1097 +0,0 @@
1
- import * as PIXI from "pixi.js";
2
- import { Container, Graphics, TextStyle } from "pixi.js";
3
- import { ItemType, Errors } from "../util/Constants";
4
- import * as D3 from "d3";
5
-
6
-
7
- let DEG2RAD = Math.PI / 180;
8
- export default class WebGLRenderer {
9
-
10
- constructor(canvasId) {
11
- this._canvasId = canvasId;
12
- this._doesCollectionHaveBounds = false;
13
- this._app = new PIXI.Application({
14
- antialias: true, // default: false
15
- width: 1600,
16
- height: 1000,
17
- view: document.getElementById(this._canvasId)
18
- });
19
- this._app.renderer.autoResize = true;
20
- }
21
-
22
- /**
23
- * @param {Scene} scene
24
- * @param {string} id
25
- * @param {*} args
26
- */
27
- render(scene, params) {
28
- let args = params ? params : {};
29
- this._app.renderer.backgroundColor = toHexColor(scene.fillColor ? scene.fillColor : "#fff");
30
- this._doesCollectionHaveBounds = !!args.collectionBounds;
31
- this._app.stage.removeChildren();
32
- this._app.renderer.clear();
33
- let final = this._renderItem(scene);
34
- this._app.stage.addChild(final);
35
- }
36
-
37
- // VM2356:14 Uncaught (in promise) TypeError: renderer.clear is not a function at eval (eval at loadScript (demoLoader.js:25:15), <anonymous>:14:32)
38
- clear() {
39
- }
40
-
41
- _renderItem(item) {
42
- switch (item.type) {
43
- case ItemType.Ellipse:
44
- case ItemType.LinearGradient:
45
- throwError("mark", item, Errors.FEATURE_NOT_IMPLEMENTED);
46
- break;
47
-
48
- case ItemType.Circle:
49
- return this._renderCircle(item);
50
-
51
- case ItemType.Pie:
52
- return this._renderArc(item);
53
-
54
- case ItemType.Area:
55
- return this._renderArea(item);
56
-
57
- case ItemType.Polygon:
58
- return this._renderPolygon(item);
59
-
60
- case ItemType.Axis:
61
- return this._renderAxis(item);
62
-
63
- case ItemType.Collection:
64
- return this._renderCollection(item);
65
-
66
- case ItemType.Glyph:
67
- case ItemType.Group:
68
- case ItemType.Gridlines:
69
- case ItemType.Legend:
70
- case ItemType.Scene:
71
- return this._renderGroup(item);
72
-
73
- case ItemType.Path:
74
- return this._renderPath(item);
75
-
76
- case ItemType.Line:
77
- return this._renderLinearPath(item);
78
-
79
- case ItemType.Rect:
80
- return this._renderRectangle(item);
81
-
82
- case ItemType.PointText:
83
- return this._renderText(item);
84
-
85
- case ItemType.Arc:
86
- return this._renderArc(item);
87
-
88
- case ItemType.Image:
89
- return this._renderImage(item);
90
-
91
- case ItemType.Link:
92
- return this._renderLink(item);
93
-
94
- case ItemType.Ring:
95
- return this._renderRing(item);
96
-
97
- default:
98
- console.log(item.type);
99
- throw new Error(`Expect: itemType, Actual: ${item}\nWait that's illegal`)
100
- }
101
- }
102
-
103
- /**
104
- * @param {RectPath} rect
105
- * @returns {PIXI.Rectangle}
106
- */
107
- _renderRectangle(rect) {
108
- let rectangle = new Graphics();
109
- decorate(rectangle, rect.styles);
110
- rectangle.lineStyle(
111
- rect.styles["strokeWidth"],
112
- toHexColor(rect.styles["strokeColor"])
113
- );
114
- beginGradientOrColorFill(rect.styles, rectangle, rect.height);
115
- rectangle.drawRect(0, 0, rect.width, rect.height);
116
- rectangle.x = rect.left;
117
- rectangle.y = rect.top;
118
- rectangle.endFill();
119
- return rectangle;
120
- }
121
-
122
- /**
123
- * @param {PointText} pointText
124
- * @returns {PIXI.Text}
125
- */
126
- _renderText(pointText) {
127
- let style = new TextStyle({
128
- fontSize: pointText.styles["fontSize"],
129
- fontFamily: pointText.styles["fontFamily"],
130
- fontWeight: styleFontWeight2PixiFontWeight(pointText.styles["fontWeight"]),
131
- fill: toHexColor(pointText.styles["fillColor"]),
132
- })
133
-
134
- //// PIXI.Text converts each 1em into 12px, which is not what we want.
135
- // Therefore, here, we convert each 1em into 16px:
136
- let fontSize = style.fontSize;
137
- if (typeof fontSize === 'string' || fontSize instanceof String) {
138
- if ((/^\d+em$/).test(fontSize)) {
139
- let number = parseInt(style.fontSize.substring(0, style.fontSize.length - 2));
140
- number *= 16 ; // 1em = 16px
141
- fontSize = number.toString().concat("px");
142
- }
143
- }
144
- style.fontSize = fontSize;
145
- /////
146
-
147
- let pixiText = new PIXI.Text(pointText.text, style);
148
- let container = new Container();
149
- decorate(pixiText, pointText.styles);
150
-
151
- pixiText.x = pointText.x;
152
- pixiText.y = pointText.y;
153
-
154
- pixiText.anchor.set(... styleAnchor2PixiAnchor(pointText.anchor));
155
- container.addChild(pixiText);
156
-
157
- let pivot = rotation2PixiPivot(pointText._rotate);
158
- container.pivot.set(pivot[0], pivot[1]);
159
- container.angle = rotation2PixiAngle(pointText._rotate);
160
- container.position.set(pivot[0], pivot[1]);
161
-
162
- return container;
163
- }
164
-
165
- /**
166
- * @param {Group} group
167
- * @returns {Container}
168
- */
169
- _renderGroup(group) {
170
- let container = new Container();
171
- for (const item of group.children) {
172
- let t = this._renderItem(item);
173
- if (t == undefined) throw new Error();
174
- container.addChild(t);
175
- }
176
-
177
- return container;
178
- }
179
-
180
- /**
181
- *
182
- * @param {Group} axis
183
- * @returns
184
- */
185
- _renderAxis(axis) {
186
- let container = this._renderGroup(axis);
187
- let pivot = rotation2PixiPivot(axis._rotate);
188
- container.pivot.set(pivot[0], pivot[1]);
189
- container.angle = rotation2PixiAngle(axis._rotate);
190
- container.position.set(pivot[0], pivot[1]);
191
- return container;
192
- }
193
-
194
- /**
195
- * @param {Collection} collection
196
- * @returns {Container}
197
- */
198
- _renderCollection(collection) {
199
- let container = new Container();
200
- let group = this._renderGroup(collection);
201
- container.addChild(group);
202
-
203
- // ------------------ Render Bounds -----------------------------------
204
-
205
- if (!this._doesCollectionHaveBounds) return container;
206
-
207
- let contour = new Graphics();
208
- // short for leading dash relative start position
209
- let leadDashRelStrtPos = 0;
210
- let bounds = collection.bounds;
211
- let l = bounds.left;
212
- let r = bounds.right;
213
- let t = bounds.top;
214
- let b = bounds.bottom;
215
- let style = {
216
- strokeWidth: 1,
217
- color: 0x1ecb40,
218
- dashLength: 5,
219
- dashSpacing: 5
220
- }
221
-
222
- leadDashRelStrtPos = drawDash(l, r, t, leadDashRelStrtPos, style, contour);
223
- leadDashRelStrtPos = drawDash(t, b, -r, leadDashRelStrtPos, style, contour);
224
- leadDashRelStrtPos = drawDash(r, l, b, leadDashRelStrtPos, style, contour);
225
- drawDash(b, t, -l, leadDashRelStrtPos, style, contour);
226
-
227
- container.addChild(contour);
228
- return container;
229
-
230
- // ------------------ End ---------------------------------------------
231
-
232
- /**
233
- * @param {Graphics} graphics
234
- * @param {Number} leadDashRelStrtPos the projected start position of a leading dash.
235
- * for example, if a dash is broken by the end of last edge,
236
- * the leading dash of next edge is incomplete and thus, the projected start point would be beyond
237
- * the start point. Therefore, it is marked with a negative value, RELATIVE to the starting point
238
- * V the starting point of this dash is thus -1
239
- * |---- -|--- ----
240
- * @param {Number} dimensionalConstrain it can be x or y, depends on which dimension remains unchanged
241
- * positive values indicate an horizontal edge
242
- * negative values indicate a vertical edge
243
- * @returns {Number} leading dash start position for next edge
244
- */
245
- function drawDash(start, end, dimensionalConstrain, leadDashRelStrtPos, style, graphics) {
246
- // if the dash line is going left -> right, then direction = +1. v.v.
247
- let dir = start <= end ? 1 : -1;
248
-
249
- // if the dash is a remain of last cut-off dash, it actually starts at the starting point
250
- // otherwise just use the start position
251
- // note here next.point is a reference,
252
- // it is a hack so that changes to next.point can be reflected to p as well
253
- let next = leadDashRelStrtPos >= 0 ?
254
- {point: start + leadDashRelStrtPos * dir} :
255
- {point: start};
256
-
257
- // p stands for pointer. It's used as an abstraction
258
- // so that this function can be applied to both horizontal and vertical scenarios
259
- let p = dimensionalConstrain > 0 ?
260
- [next, { point: dimensionalConstrain }] :
261
- [{ point: -dimensionalConstrain }, next];
262
-
263
- graphics.lineStyle({
264
- width: style.strokeWidth,
265
- color: style.color
266
- })
267
- // move to the actual start
268
- graphics.moveTo(p[0].point, p[1].point);
269
- // set the next point to the end of first dash (regardless of whether it's complete)
270
- next.point = leadDashRelStrtPos * dir + start + style.dashLength * dir;
271
- graphics.lineTo(p[0].point, p[1].point);
272
-
273
- let isDrawing = false;
274
- // move next point to (the start position)of the second dash
275
- next.point += style.dashLength * dir;
276
- // if the next point is with the range from start to end
277
- while (next.point * dir <= end * dir) {
278
- if (isDrawing) {
279
- graphics.lineTo(p[0].point, p[1].point);
280
- isDrawing = false;
281
- next.point += style.dashSpacing * dir;
282
- } else {
283
- graphics.moveTo(p[0].point, p[1].point);
284
- isDrawing = true;
285
- next.point += style.dashLength * dir;
286
- }
287
- }
288
-
289
- // finish the last dash
290
- // if it's still drawing, cut it off (and continue it in the next edge)
291
- if (isDrawing) {
292
- // handle the horizontal and vertical cases
293
- if (dimensionalConstrain > 0) graphics.lineTo(end, dimensionalConstrain);
294
- else graphics.lineTo(-dimensionalConstrain, end);
295
- return (end - next.point) * dir;
296
- // otherwise it's fine, let the math handle it automagically
297
- } else {
298
- return (next.point - end) * dir;
299
- }
300
- }
301
- }
302
-
303
- /**
304
- * @param {AreaPath} areaPath
305
- */
306
- _renderArea(areaPath) {
307
- switch (areaPath.curveMode) {
308
- case "linear":
309
- return this._renderPolygon(areaPath);
310
-
311
- case "basis":
312
- return this._renderBezierArea(areaPath);
313
-
314
- default:
315
- return throwError("areaPath", areaPath, Errors.FEATURE_NOT_IMPLEMENTED);
316
- }
317
- }
318
-
319
- _renderBezierArea(areaPath) {
320
- let area = new Graphics();
321
- decorate(area, areaPath.styles);
322
- area.lineStyle({
323
- width: areaPath.styles["strokeWidth"],
324
- color: toHexColor(areaPath.styles["strokeColor"])
325
- })
326
- let pathData = areaPath.getSVGPathData();
327
- let pathJSON = parseDPath(pathData);
328
-
329
- beginGradientOrColorFill(areaPath.styles, area, areaPath.bounds.height);
330
- drawOnGraphicsFromJSONData(area, pathJSON);
331
- area.endFill();
332
-
333
- return area;
334
- }
335
-
336
- /**
337
- * @param {PolygonPath} polygonPath
338
- */
339
- _renderPolygon(polygonPath) {
340
- let container = new PIXI.Container();
341
-
342
- // ------------------ Contour -----------------------------------------
343
-
344
- let contour = this._renderLinearPath(polygonPath);
345
- contour.getChildAt(0).lineTo(
346
- polygonPath.vertices[0].x,
347
- polygonPath.vertices[0].y
348
- );
349
-
350
- // ------------------ Fill --------------------------------------------
351
-
352
- let polygonFill = new PIXI.Graphics();
353
- decorate(polygonFill, polygonPath.styles);
354
- let path = [];
355
- for (const vertex of polygonPath.vertices) {
356
- path.push(vertex.x - polygonPath.bounds.left);
357
- path.push(vertex.y - polygonPath.bounds.top);
358
- }
359
- //polygonFill.beginFill(toHexColor(polygonPath.styles["fillColor"]));
360
- beginGradientOrColorFill(polygonPath.styles, polygonFill, polygonPath.bounds.height);
361
- polygonFill.drawPolygon(path);
362
- polygonFill.x += polygonPath.bounds.left;
363
- polygonFill.y += polygonPath.bounds.top;
364
- polygonFill.endFill();
365
-
366
- // ------------------ Finalize ----------------------------------------
367
-
368
- container.addChild(polygonFill);
369
- container.addChild(contour);
370
- return container;
371
- }
372
-
373
- /**
374
- * @param {Path} path
375
- * @returns {Container}
376
- */
377
- _renderPath(path) {
378
-
379
- switch (path.curveMode) {
380
- case "linear":
381
- return this._renderLinearPath(path);
382
-
383
- case "bumpX":
384
- case "natural":
385
- return this._renderBezierPath(path);
386
-
387
- default:
388
- throwError("path", path, Errors.FEATURE_NOT_IMPLEMENTED);
389
- break;
390
- }
391
-
392
- // ------------------ End ---------------------------------------------
393
-
394
- }
395
-
396
- /**
397
- *
398
- * @param {Path} path
399
- * @returns
400
- */
401
- _renderLinearPath(path) {
402
- let container = new Container();
403
- let line = new Graphics();
404
- let isContinuous = path.styles["strokeDash"] == "none";
405
- decorate(line, path.styles);
406
- let vertex0 = path.vertices[0];
407
- line.lineStyle({
408
- width: path.styles["strokeWidth"],
409
- color: toHexColor(path.styles["strokeColor"])
410
- })
411
-
412
- line.moveTo(vertex0.x, vertex0.y);
413
- if (isContinuous) {
414
- for (let i = 1; i < path.vertices.length; i++) {
415
- const vertex = path.vertices[i];
416
- line.lineTo(vertex.x, vertex.y);
417
- }
418
- } else {
419
- drawDashLine(path.vertices, path.styles["strokeDash"], line);
420
- }
421
-
422
- container.addChild(line);
423
-
424
- // ------------------ Render vertices ---------------------------------
425
-
426
- for (let i = 0; i < path.vertices.length; i++) {
427
- let vertex = path.vertices[i];
428
- let renderedVertex = this._renderVertex(vertex);
429
- if (renderedVertex != null) container.addChild(renderedVertex);
430
- }
431
-
432
- return container;
433
- }
434
-
435
- /**
436
- * @param {Path} path
437
- */
438
- _renderBezierPath(path) {
439
- let container = new Container();
440
- let graphics = new Graphics();
441
- decorate(graphics, path.styles);
442
- graphics.lineStyle({
443
- width: path.styles["strokeWidth"],
444
- color: toHexColor(path.styles["strokeColor"])
445
- })
446
- let pathData = path.getSVGPathData();
447
- let pathJSON = parseDPath(pathData);
448
- drawOnGraphicsFromJSONData(graphics, pathJSON);
449
- container.addChild(graphics);
450
-
451
- // ------------------ Render vertices ---------------------------------
452
-
453
- for (let i = 0; i < path.vertices.length; i++) {
454
- let vertex = path.vertices[i];
455
- let renderedVertex = this._renderVertex(vertex);
456
- if (renderedVertex != null) container.addChild(renderedVertex);
457
- }
458
-
459
- return container;
460
- }
461
-
462
- /**
463
- * NULLABLE!!!
464
- * @param {Vertex} vertex
465
- * @returns {Container} null if vertex shape is undefined
466
- */
467
- _renderVertex(vertex) {
468
- switch (vertex.shape) {
469
- case "rect":
470
- return renderRectVertex(vertex);
471
-
472
- case "circle":
473
- return renderCircleVertex(vertex);
474
-
475
- case undefined:
476
- return null;
477
-
478
- default:
479
- throwError("vertex shape", vertex.shape, Errors.FEATURE_NOT_IMPLEMENTED);
480
- }
481
-
482
- function renderRectVertex(vertex) {
483
- let rectVertex = new PIXI.Graphics();
484
- rectVertex.lineStyle({
485
- width: vertex.strokeWidth,
486
- color: toHexColor(vertex.strokeColor)
487
- })
488
- rectVertex.beginFill(toHexColor(vertex.fillColor))
489
- rectVertex.drawRect(
490
- vertex.x - vertex.width / 2,
491
- vertex.y - vertex.height / 2,
492
- vertex.width,
493
- vertex.height);
494
- rectVertex.endFill();
495
-
496
- return rectVertex;
497
- }
498
-
499
- function renderCircleVertex(vertex) {
500
- let circle = new PIXI.Graphics();
501
- circle.lineStyle({
502
- width: vertex.strokeWidth,
503
- color: toHexColor(vertex.strokeColor)
504
- })
505
- circle.alpha = vertex.opacity;
506
- circle.beginFill(toHexColor(vertex.fillColor));
507
- circle.drawCircle(vertex.x, vertex.y, vertex.radius);
508
- circle.endFill();
509
-
510
- return circle;
511
- }
512
- }
513
-
514
- /**
515
- * @param {CirclePath} circPath
516
- * @returns {PIXI.Rectangle}
517
- */
518
- _renderCircle(circPath) {
519
- let circle = new Graphics();
520
- decorate(circle, circPath.styles);
521
- circle.lineStyle(
522
- circPath.styles["strokeWidth"],
523
- toHexColor(circPath.styles["strokeColor"])
524
- );
525
- beginGradientOrColorFill(circPath.styles, circle, circPath.height);
526
- circle.drawCircle(
527
- circPath.x,
528
- circPath.y,
529
- circPath.radius
530
- );
531
- circle.endFill();
532
- return circle;
533
- }
534
-
535
- /**
536
- * @param {RingPath} ringPath
537
- * @returns {PIXI.Rectangle}
538
- */
539
- _renderRing(ringPath) {
540
- let ring = new Graphics();
541
- //decorate(ring, ringPath.styles);
542
- ring.lineStyle(
543
- (ringPath.outerRadius - ringPath.innerRadius),
544
- toHexColor(ringPath.styles["fillColor"])
545
- );
546
- //beginGradientOrColorFill(ringPath.styles, ring, ringPath.height);
547
- ring.drawCircle(
548
- ringPath.x,
549
- ringPath.y,
550
- (ringPath.innerRadius + ringPath.outerRadius)/2
551
- );
552
- ring.endFill();
553
- return ring;
554
- }
555
-
556
- // /**
557
- // * @param {PiePath} piePath
558
- // */
559
- // _renderPiePath(piePath) {
560
- // let arc = new PIXI.Graphics();
561
- // arc.lineStyle({
562
- // color: toHexColor(piePath.styles["strokeColor"]),
563
- // width: piePath.styles["strokeWidth"]
564
- // })
565
- // arc.beginFill(toHexColor(piePath.styles["fillColor"]))
566
- // arc.moveTo(piePath.x, piePath.y);
567
- // arc.arc(
568
- // piePath.x,
569
- // piePath.y,
570
- // piePath.radius,
571
- // -piePath.endAngleRad,
572
- // -piePath.startAngleRad,
573
- // );
574
-
575
- // arc.lineTo(piePath.x, piePath.y);
576
- // arc.endFill();
577
-
578
- // return arc;
579
- // }
580
-
581
- /**
582
- * @param {ArcPath} arcPath
583
- */
584
- _renderArc(arcPath) {
585
- let arc = new Graphics();
586
- arc.lineStyle({
587
- color: toHexColor(arcPath.styles["strokeColor"]),
588
- width: arcPath.styles["strokeWidth"]
589
- })
590
- arc.beginFill(toHexColor(arcPath.styles["fillColor"]));
591
- //arc.moveTo(arcPath.x, arcPath.y);
592
- arc.arc(
593
- arcPath.x,
594
- arcPath.y,
595
- arcPath.outerRadius,
596
- -arcPath.endAngle * DEG2RAD,
597
- -arcPath.startAngle * DEG2RAD,
598
- );
599
-
600
- arc.arc(
601
- arcPath.x,
602
- arcPath.y,
603
- arcPath.innerRadius,
604
- -arcPath.startAngle * DEG2RAD,
605
- -arcPath.endAngle * DEG2RAD,
606
- true
607
- );
608
-
609
- //arc.lineTo(arcPath.x, arcPath.y);
610
- arc.endFill();
611
-
612
- return arc;
613
- }
614
-
615
- /**
616
- * @param {Image} image
617
- */
618
- _renderImage(image) {
619
- let sprite = PIXI.Sprite.from(image.src);
620
- sprite.x = image.x;
621
- sprite.y = image.y;
622
- sprite.width = image.width;
623
- sprite.height = image.height;
624
-
625
- return sprite;
626
- }
627
-
628
- /**
629
- * @param {Link} link
630
- */
631
- _renderLink(link) {
632
- switch (link.linkMode) {
633
- case "arcClockwise":
634
- case "curveVertical":
635
- case "arcAntiClockwise":
636
- case "linear":
637
- return renderLinearLink(link);
638
-
639
- default:
640
- throwError("link", link.curveMode, "unexpected curvemode")
641
- }
642
-
643
- /**
644
- * @param {Link} link
645
- */
646
- function renderLinearLink(link) {
647
- let graphics = new Graphics();
648
- decorate(graphics, link.styles);
649
- graphics.lineStyle({
650
- color: toHexColor(link.styles["strokeColor"]),
651
- width: link.styles["strokeWidth"]
652
- })
653
- drawOnGraphicsFromJSONData(graphics, parseDPath(link.getSVGPathData()));
654
-
655
- return graphics;
656
- }
657
- }
658
- }
659
-
660
- /**
661
- * Set visibility and alpha
662
- * @param {DisplayObject} displayObject
663
- * @param {*} styles
664
- */
665
- function decorate(displayObject, styles) {
666
- displayObject.visible = styleVisiblity2PixiVisible(styles["visibility"]);
667
- displayObject.alpha = styleOpacity2PixiAlpha(styles["opacity"]);
668
- }
669
-
670
- function styleFontWeight2PixiFontWeight(fontWeight) {
671
- switch (fontWeight) {
672
- case "regular":
673
- case "normal":
674
- return "normal";
675
-
676
- case "bold":
677
- return "bold";
678
-
679
- default:
680
- console.log(fontWeight);
681
- throwError("font weight", fontWeight, Errors.FEATURE_NOT_IMPLEMENTED);
682
- }
683
- }
684
-
685
- function styleAnchor2PixiAnchor(anchor) {
686
- let horizontal, vertical;
687
-
688
- switch (anchor[0]) {
689
- case "left":
690
- horizontal = 0.0;
691
- break;
692
-
693
- case "center":
694
- horizontal = 0.5;
695
- break;
696
-
697
- case "right":
698
- horizontal = 1.0;
699
- break;
700
-
701
- default:
702
- throwError("x anchor", anchor[0], Errors.UNKNOWN_ANCHOR);
703
- }
704
-
705
- switch (anchor[1]) {
706
- // TODO: hanging is actually not quite the same as top
707
- case "hanging":
708
- case "top":
709
- vertical = 0.0;
710
- break;
711
- // TODO: central is not quite the same as middle
712
- case "central":
713
- case "middle":
714
- vertical = 0.5;
715
- break;
716
- case "bottom":
717
- vertical = 1.0;
718
- break;
719
- default:
720
- throwError("y anchor", anchor[1], Errors.UNKNOWN_ANCHOR);
721
- }
722
-
723
- return [horizontal, vertical];
724
- }
725
-
726
- /**
727
- * @param {string} cssColor
728
- * @returns {number}
729
- */
730
- function toHexColor(cssColor) {
731
- let d3Color = D3.color(cssColor);
732
- if (d3Color == null) {
733
- return null;
734
- } else {
735
- let hexString = d3Color.formatHex();
736
- return PIXI.utils.string2hex(hexString);
737
- }
738
- }
739
-
740
- function styleVisiblity2PixiVisible(visibility) {
741
- switch (visibility) {
742
- case "hidden":
743
- return false;
744
- case null:
745
- case undefined:
746
- case "visible":
747
- default:
748
- return true;
749
- }
750
- }
751
-
752
- function rotation2PixiAngle(rotation) {
753
- if (rotation === undefined || typeof rotation[0] != "number") {
754
- return 0
755
- } else {
756
- return rotation[0];
757
- }
758
- }
759
-
760
- function rotation2PixiPivot(rotation) {
761
- if (rotation === undefined || typeof rotation[0] != "number") {
762
- return [0, 0];
763
- } else {
764
- return rotation.slice(1);
765
- }
766
- }
767
-
768
- function styleOpacity2PixiAlpha(opacity) {
769
- switch (opacity) {
770
- case undefined:
771
- case null:
772
- return 1;
773
-
774
- default:
775
- return opacity;
776
- }
777
- }
778
-
779
- function throwError(name, value, err) {
780
- console.log(value);
781
- throw new Error(`${err}. Source: ${name}, Actual: `);
782
- }
783
-
784
- /**
785
- * Can fill graphic with color or linear gradient accordingly.
786
- * Can also handle transparency
787
- * @param {Graphics} graphics
788
- */
789
- function beginGradientOrColorFill(styles, graphics, height) {
790
- let fillColor = styles["fillColor"];
791
-
792
- // if no fill color
793
- if (fillColor == "none") return;
794
-
795
- let hexColor = toHexColor(fillColor);
796
- // if valid color
797
- if (hexColor != null) {
798
- graphics.beginFill(hexColor);
799
- // then it must be texture
800
- } else {
801
- graphics.beginTextureFill({
802
- color: 0xffffff,
803
- texture: createLinearGradientTexture(height, fillColor.stops, fillColor.y1 > fillColor.y2)
804
- });
805
- }
806
- }
807
-
808
- function createLinearGradientTexture(height, stops, isReversed) {
809
-
810
- const canvas = document.createElement("canvas");
811
- canvas.height = height;
812
- canvas.width = 1;
813
- const ctx = canvas.getContext("2d");
814
-
815
- const grd = ctx.createLinearGradient(0, 0, 0, height);
816
- for (let i = 0; i < stops.length; i++) {
817
- if (isReversed) {
818
- grd.addColorStop(1 - stops[i].offset / 100, stops[i].color);
819
- } else {
820
- grd.addColorStop(stops[i].offset / 100, stops[i].color);
821
- }
822
- }
823
-
824
- ctx.fillStyle = grd;
825
- ctx.fillRect(0, 0, 1, height);
826
-
827
- return PIXI.Texture.from(canvas);
828
- }
829
-
830
- /**
831
- * @param {Graphics} graphics
832
- * @param {Array} json
833
- */
834
- function drawOnGraphicsFromJSONData(graphics, json) {
835
-
836
- // Draw a closed shape accordingly
837
- let last = json.pop();
838
- let callBack = () => {};
839
- if (last.code.toUpperCase() == "Z") {
840
- callBack = () => graphics.lineTo(json[0].end.x, json[0].end.y);
841
- } else {
842
- json.push(last);
843
- }
844
-
845
- // Actual drawing
846
- for (const data of json) {
847
- draw(data, graphics);
848
- }
849
-
850
- callBack();
851
- }
852
-
853
- /**
854
- * @param {Graphics} graphics
855
- * @returns {Graphics}
856
- */
857
- function draw(data, graphics) {
858
- switch (data.code.toUpperCase()) {
859
- case "M":
860
- graphics.moveTo(data.end.x, data.end.y);
861
- break;
862
-
863
- case "L":
864
- graphics.lineTo(data.end.x, data.end.y);
865
- break;
866
-
867
- case "Q":
868
- graphics.bezierCurveTo(
869
- data.cp1.x,
870
- data.cp1.y,
871
- data.cp1.x,
872
- data.cp1.y,
873
- data.end.x,
874
- data.end.y
875
- );
876
- break;
877
-
878
- case "C":
879
- graphics.bezierCurveTo(
880
- data.cp1.x,
881
- data.cp1.y,
882
- data.cp2.x,
883
- data.cp2.y,
884
- data.end.x,
885
- data.end.y
886
- );
887
- break;
888
-
889
- case "Z":
890
- throw new Error("Unexpected \"z\" marker. There's something wrong, I can feel it");
891
- case "A":
892
-
893
- graphics.endFill(); // to undo moveTo(), to avoid straight lines between vertices
894
-
895
- // the SVG command , like M 250 460 A 7.5 7.5 0 0 1 265 460, has rotation in degrees.
896
- // ...converting rotation to radians
897
- const degrees = data.rotation;
898
- const radians = degrees * (Math.PI / 180);
899
-
900
- graphics.arc(data.end.x - data.radii.x, data.end.y, data.radii.y, 0 + radians, Math.PI + radians, data.clockwise);
901
- break;
902
- default:
903
- return throwError("data", data, Errors.FEATURE_NOT_IMPLEMENTED);
904
- }
905
- }
906
-
907
- // Adapted from https://codepen.io/unrealnl/pen/aYaxBW
908
- function drawDashLine(vertices, strokeDash, graphics) {
909
- let i;
910
- let p1;
911
- let p2;
912
- let dashLeft = 0;
913
- let gapLeft = 0;
914
- let dashAndGap = strokeDash.split(" ");
915
- let dash = Number(dashAndGap[0]);
916
- let gap = Number(dashAndGap[1]);
917
-
918
- for (i = 0; i < vertices.length; i++) {
919
- p1 = vertices[i];
920
- if (i == vertices.length - 1) break;
921
- else p2 = vertices[i + 1];
922
-
923
- let dx = p2.x - p1.x;
924
- let dy = p2.y - p1.y;
925
- let len = Math.sqrt(dx * dx + dy * dy);
926
- let normal = { x: dx / len, y: dy / len };
927
- let progressOnLine = 0;
928
- graphics.moveTo(p1.x + gapLeft * normal.x, p1.y + gapLeft * normal.y);
929
-
930
- while (progressOnLine <= len) {
931
- progressOnLine += gapLeft;
932
- if (dashLeft > 0) progressOnLine += dashLeft;
933
- else progressOnLine += dash;
934
- if (progressOnLine > len) {
935
- dashLeft = progressOnLine - len;
936
- progressOnLine = len;
937
- } else {
938
- dashLeft = 0;
939
- }
940
- graphics.lineTo(p1.x + progressOnLine * normal.x, p1.y + progressOnLine * normal.y);
941
- progressOnLine += gap;
942
- if (progressOnLine > len && dashLeft == 0) {
943
- gapLeft = progressOnLine - len;
944
- } else {
945
- gapLeft = 0;
946
- graphics.moveTo(p1.x + progressOnLine * normal.x, p1.y + progressOnLine * normal.y);
947
- }
948
- }
949
- }
950
- }
951
-
952
- // Adapted from d-path-parser under MIT license
953
- // GitHub Repository: https://github.com/MaxArt2501/d-path-parser
954
- function parseDPath(d) {
955
- let re = {
956
- command: /\s*([achlmqstvz])/gi,
957
- number: /\s*([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/gi,
958
- comma: /\s*(?:(,)|\s)/g,
959
- flag: /\s*([01])/g
960
- };
961
- let matchers = {
962
- "number": function(must) {
963
- return +get("number", must);
964
- },
965
- "coordinate pair": function(must) {
966
- let x = get("number", must);
967
- if (x === null && !must) return null;
968
- get("comma");
969
- let y = get("number", true);
970
- return { x: +x, y: +y };
971
- },
972
- "arc definition": function(must) {
973
- let radii = matchers["coordinate pair"](must);
974
- if (!radii && !must) return null;
975
- get("comma");
976
- let rotation = +get("number", true);
977
- get("comma", true);
978
- let large = !!+get("flag", true);
979
- get("comma");
980
- let clockwise = !!+get("flag", true);
981
- get("comma");
982
- let end = matchers["coordinate pair"](true);
983
- return {
984
- radii: radii,
985
- rotation: rotation,
986
- large: large,
987
- clockwise: clockwise,
988
- end: end
989
- };
990
- }
991
- }
992
- let index = 0;
993
- let commands = [];
994
-
995
- while (index < d.length) {
996
- let cmd = get("command");
997
- let upcmd = cmd.toUpperCase();
998
- let relative = cmd !== upcmd;
999
- let sequence;
1000
- switch (upcmd) {
1001
- case "M":
1002
- sequence = getSequence("coordinate pair").map(function(coords, i) {
1003
- if (i === 1) cmd = relative ? "l" : "L";
1004
- return makeCommand({ end: coords }, cmd, relative);
1005
- });
1006
- break;
1007
- case "L":
1008
- case "T":
1009
- sequence = getSequence("coordinate pair").map(function(coords) {
1010
- return makeCommand({ end: coords }, cmd, relative);
1011
- });
1012
- break;
1013
- case "C":
1014
- sequence = getSequence("coordinate pair");
1015
- if (sequence.length % 3)
1016
- throw Error("Expected coordinate pair triplet at position " + index);
1017
-
1018
- sequence = sequence.reduce(function(seq, coords, i) {
1019
- let rest = i % 3;
1020
- if (!rest) {
1021
- seq.push(makeCommand({ cp1: coords }, cmd, relative));
1022
- } else {
1023
- let last = seq[seq.length - 1];
1024
- last[rest === 1 ? "cp2" : "end"] = coords;
1025
- }
1026
- return seq;
1027
- }, []);
1028
-
1029
- break;
1030
- case "Q":
1031
- case "S":
1032
- sequence = getSequence("coordinate pair");
1033
- if (sequence.length & 1)
1034
- throw Error("Expected coordinate pair couple at position " + index);
1035
-
1036
- sequence = sequence.reduce(function(seq, coords, i) {
1037
- let odd = i & 1;
1038
- if (!odd) {
1039
- seq.push(makeCommand({ cp: coords }, cmd, relative));
1040
- } else {
1041
- let last = seq[seq.length - 1];
1042
- last.end = coords;
1043
- }
1044
- return seq;
1045
- }, []);
1046
-
1047
- break;
1048
- case "H":
1049
- case "V":
1050
- sequence = getSequence("number").map(function(value) {
1051
- return makeCommand({ value: value }, cmd, relative);
1052
- });
1053
- break;
1054
- case "A":
1055
- sequence = getSequence("arc definition");
1056
- sequence = sequence.map(obj => makeCommand(obj, cmd, relative))
1057
- break;
1058
- case "Z":
1059
- sequence = [ { code: "Z" } ];
1060
- break;
1061
- }
1062
- commands.push.apply(commands, sequence);
1063
- }
1064
-
1065
- return commands;
1066
-
1067
- function makeCommand(obj, cmd, relative) {
1068
- obj.code = cmd;
1069
- obj.relative = relative;
1070
-
1071
- return obj;
1072
- }
1073
- function get(what, must) {
1074
- re[what].lastIndex = index;
1075
- let res = re[what].exec(d);
1076
- if (!res || res.index !== index) {
1077
- if (!must) return null;
1078
- throw Error("Expected " + what + " at position " + index);
1079
- }
1080
-
1081
- index = re[what].lastIndex;
1082
-
1083
- return res[1];
1084
- }
1085
-
1086
- function getSequence(what) {
1087
- let sequence = [];
1088
- let matched;
1089
- let must = true;
1090
- while ((matched = matchers[what](must)) !== null) {
1091
- sequence.push(matched);
1092
- must = !!get("comma");
1093
- }
1094
-
1095
- return sequence;
1096
- }
1097
- }