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.
- package/dist/mascot-esm.js +186 -0
- package/package.json +3 -6
- package/dist/mascot-es.js +0 -27745
- package/dist/mascot-min.js +0 -186
- package/dist/mascot-umd.js +0 -27781
- package/js/depGraphVis.js +0 -66
- package/src-new-ts/action/createElement.ts +0 -91
- package/src-new-ts/action/encode.js +0 -20
- package/src-new-ts/action/repeat.js +0 -128
- package/src-new-ts/action/traverseScene.js +0 -41
- package/src-new-ts/data/Network.js +0 -2
- package/src-new-ts/data/Scope.js +0 -135
- package/src-new-ts/data/Table.js +0 -263
- package/src-new-ts/data/Tree.js +0 -3
- package/src-new-ts/data/field.ts +0 -115
- package/src-new-ts/data/import.ts +0 -96
- package/src-new-ts/data/predicate.ts +0 -82
- package/src-new-ts/depgraph/DepGraph.js +0 -178
- package/src-new-ts/depgraph/Edge.js +0 -9
- package/src-new-ts/depgraph/SceneGraph2DepGraph.js +0 -110
- package/src-new-ts/depgraph/Signal.js +0 -12
- package/src-new-ts/depgraph/operator/BoundsEvaluator.js +0 -30
- package/src-new-ts/depgraph/operator/Dataflow.js +0 -41
- package/src-new-ts/depgraph/operator/DomainBuilder.js +0 -50
- package/src-new-ts/depgraph/updateDepGraph.js +0 -45
- package/src-new-ts/depgraph/variable/BoundsVar.js +0 -81
- package/src-new-ts/depgraph/variable/ChannelVar.js +0 -17
- package/src-new-ts/depgraph/variable/DataScopeVar.js +0 -12
- package/src-new-ts/depgraph/variable/DomainVar.js +0 -15
- package/src-new-ts/depgraph/variable/FieldVar.js +0 -17
- package/src-new-ts/depgraph/variable/LayoutParameter.js +0 -8
- package/src-new-ts/depgraph/variable/ScaleVar.js +0 -13
- package/src-new-ts/depgraph/variable/Variable.js +0 -39
- package/src-new-ts/element/gradient/LinearGradient.js +0 -37
- package/src-new-ts/element/group/Collection.js +0 -109
- package/src-new-ts/element/group/Group.js +0 -307
- package/src-new-ts/element/group/Scene.js +0 -98
- package/src-new-ts/element/mark/CircleMark.ts +0 -85
- package/src-new-ts/element/mark/Mark.ts +0 -233
- package/src-new-ts/element/mark/PathMark.js +0 -483
- package/src-new-ts/element/mark/Segment.js +0 -29
- package/src-new-ts/element/mark/Vertex.js +0 -118
- package/src-new-ts/encode/Scale.ts +0 -115
- package/src-new-ts/index.ts +0 -19
- package/src-new-ts/layout/Layout.ts +0 -3
- package/src-new-ts/render/CanvasRenderer.ts +0 -24
- package/src-new-ts/render/SVGRenderer.js +0 -316
- package/src-new-ts/util.ts +0 -3
- package/src-old/action/Classify.js +0 -53
- package/src-old/action/Densify.js +0 -199
- package/src-old/action/Partition.js +0 -531
- package/src-old/action/Repeat.js +0 -106
- package/src-old/action/Repopulate.js +0 -44
- package/src-old/action/Stratify.js +0 -156
- package/src-old/basic/Gradient.js +0 -37
- package/src-old/basic/Point.js +0 -51
- package/src-old/basic/Rectangle.js +0 -63
- package/src-old/bind/bindToAngle.js +0 -56
- package/src-old/bind/bindToAreaMark.js +0 -360
- package/src-old/bind/bindToColor.js +0 -114
- package/src-old/bind/bindToLink.js +0 -81
- package/src-old/bind/bindToPosition.js +0 -283
- package/src-old/bind/bindToRadialDistance.js +0 -62
- package/src-old/bind/bindToSize.js +0 -235
- package/src-old/bind/bindToText.js +0 -60
- package/src-old/bind/bindToThickness.js +0 -100
- package/src-old/constraint/AffixConstraint.js +0 -129
- package/src-old/constraint/AlignConstraint.js +0 -58
- package/src-old/core/Encoding.js +0 -336
- package/src-old/core/Scale.js +0 -322
- package/src-old/core/SceneLoader.js +0 -290
- package/src-old/core/SceneValidator.js +0 -232
- package/src-old/core/SpecExecutor.js +0 -113
- package/src-old/core/SpecGenerator.js +0 -350
- package/src-old/data/DataImporter.js +0 -64
- package/src-old/data/DataScope.js +0 -124
- package/src-old/data/DataTable.js +0 -338
- package/src-old/data/Network.js +0 -106
- package/src-old/data/Tree.js +0 -251
- package/src-old/data/transform/Bin.js +0 -46
- package/src-old/data/transform/Filter.js +0 -48
- package/src-old/data/transform/Groupby.js +0 -18
- package/src-old/data/transform/KDE.js +0 -58
- package/src-old/data/transform/Sort.js +0 -14
- package/src-old/data/transform/Split.js +0 -5
- package/src-old/data/transform/partition.js +0 -46
- package/src-old/history/UndoRedoStack +0 -0
- package/src-old/index.js +0 -271
- package/src-old/indexSVG.js +0 -259
- package/src-old/interaction/Interaction.js +0 -91
- package/src-old/interaction/MouseEvent.js +0 -8
- package/src-old/interaction/Selection.js +0 -9
- package/src-old/interaction/brush.js +0 -362
- package/src-old/item/Segment.js +0 -29
- package/src-old/item/Vertex.js +0 -118
- package/src-old/item/composite/Collection.js +0 -106
- package/src-old/item/composite/Glyph.js +0 -19
- package/src-old/item/composite/Group.js +0 -310
- package/src-old/item/composite/Scene.js +0 -1251
- package/src-old/item/mark/ArcPath.js +0 -181
- package/src-old/item/mark/AreaPath.js +0 -78
- package/src-old/item/mark/CirclePath.js +0 -102
- package/src-old/item/mark/EllipsePath.js +0 -5
- package/src-old/item/mark/Image.js +0 -101
- package/src-old/item/mark/LinkPath.js +0 -118
- package/src-old/item/mark/Mark.js +0 -163
- package/src-old/item/mark/Path.js +0 -494
- package/src-old/item/mark/PointText.js +0 -201
- package/src-old/item/mark/PolygonPath.js +0 -64
- package/src-old/item/mark/RectPath.js +0 -88
- package/src-old/item/mark/RingPath.js +0 -92
- package/src-old/item/refs/Axis.js +0 -362
- package/src-old/item/refs/EncodingAxis.js +0 -515
- package/src-old/item/refs/Gridlines.js +0 -144
- package/src-old/item/refs/LayoutAxis.js +0 -316
- package/src-old/item/refs/Legend.js +0 -273
- package/src-old/layout/Circular.js +0 -95
- package/src-old/layout/Force.js +0 -52
- package/src-old/layout/Grid.js +0 -423
- package/src-old/layout/Layout.js +0 -13
- package/src-old/layout/Packing.js +0 -56
- package/src-old/layout/Stack.js +0 -264
- package/src-old/layout/Strata.js +0 -88
- package/src-old/layout/Sugiyama.js +0 -59
- package/src-old/layout/TidyTree.js +0 -105
- package/src-old/layout/Treemap.js +0 -87
- package/src-old/renderer/SVGInteractionHandler.js +0 -241
- package/src-old/renderer/SVGRenderer.js +0 -325
- package/src-old/renderer/WebGLRenderer.js +0 -1097
- package/src-old/renderer/WebGLRenderer2.js +0 -249
- package/src-old/renderer/threejs/Line2.js +0 -18
- package/src-old/renderer/threejs/LineGeometry.js +0 -77
- package/src-old/renderer/threejs/LineMaterial.js +0 -605
- package/src-old/renderer/threejs/LineSegments2.js +0 -281
- package/src-old/renderer/threejs/LineSegmentsGeometry.js +0 -226
- package/src-old/renderer/threejs/Wireframe.js +0 -51
- package/src-old/renderer/threejs/WireframeGeometry2.js +0 -16
- package/src-old/scale/areaSize.js +0 -0
- package/src-old/scale/domain.js +0 -38
- package/src-old/util/Constants.js +0 -180
- package/src-old/util/DataUtil.js +0 -35
- package/src-old/util/ItemUtil.js +0 -586
- package/src-old/util/Numerical.js +0 -33
- package/tests/demo-tests/README.md +0 -80
- package/tests/demo-tests/SVG2PNG.js +0 -56
- package/tests/demo-tests/demos2CanvasPNGs.js +0 -69
- package/tests/demo-tests/demos2ScenesSVGs.js +0 -100
- package/tests/demo-tests/pathElementWorker.js +0 -91
- package/tests/demo-tests/pixelTest.js +0 -62
- package/tests/demo-tests/renderDemos.html +0 -132
- package/tests/demo-tests/serializationTest.js +0 -36
- package/tests/demo-tests/serializeDemos.html +0 -134
- package/tests/unit-tests/README.md +0 -4
- package/tests/unit-tests/jasmine-browser.json +0 -21
- package/tests/unit-tests/jasmine.json +0 -14
- 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
|
-
}
|