plotboilerplate 1.20.1 → 1.21.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 (141) hide show
  1. package/README.md +17 -1
  2. package/dist/index.esm.js +2065 -1397
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.esm.min.js +1 -1
  5. package/dist/index.esm.min.js.map +1 -1
  6. package/dist/plotboilerplate.browser.min.js +1 -1
  7. package/dist/plotboilerplate.browser.min.js.map +1 -1
  8. package/dist/plotboilerplate.js +1265 -584
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +2 -1
  11. package/src/cjs/BezierPath.d.ts +27 -49
  12. package/src/cjs/BezierPath.js +69 -237
  13. package/src/cjs/BezierPath.js.map +1 -1
  14. package/src/cjs/Bounds.d.ts +14 -1
  15. package/src/cjs/Bounds.js +21 -1
  16. package/src/cjs/Bounds.js.map +1 -1
  17. package/src/cjs/CubicBezierCurve.d.ts +70 -1
  18. package/src/cjs/CubicBezierCurve.js +130 -12
  19. package/src/cjs/CubicBezierCurve.js.map +1 -1
  20. package/src/cjs/Line.d.ts +2 -1
  21. package/src/cjs/Line.js +1 -0
  22. package/src/cjs/Line.js.map +1 -1
  23. package/src/cjs/PBText.d.ts +2 -1
  24. package/src/cjs/PBText.js +10 -9
  25. package/src/cjs/PBText.js.map +1 -1
  26. package/src/cjs/PlotBoilerplate.d.ts +10 -13
  27. package/src/cjs/PlotBoilerplate.js +136 -47
  28. package/src/cjs/PlotBoilerplate.js.map +1 -1
  29. package/src/cjs/Polygon.d.ts +35 -1
  30. package/src/cjs/Polygon.js +87 -1
  31. package/src/cjs/Polygon.js.map +1 -1
  32. package/src/cjs/Triangle.js +1 -0
  33. package/src/cjs/Triangle.js.map +1 -1
  34. package/src/cjs/VEllipse.js +1 -1
  35. package/src/cjs/VEllipse.js.map +1 -1
  36. package/src/cjs/Vector.d.ts +4 -4
  37. package/src/cjs/Vector.js +2 -2
  38. package/src/cjs/Vector.js.map +1 -1
  39. package/src/cjs/VertTuple.d.ts +2 -1
  40. package/src/cjs/VertTuple.js +4 -3
  41. package/src/cjs/VertTuple.js.map +1 -1
  42. package/src/cjs/Vertex.d.ts +14 -3
  43. package/src/cjs/Vertex.js +18 -3
  44. package/src/cjs/Vertex.js.map +1 -1
  45. package/src/cjs/draw.d.ts +159 -79
  46. package/src/cjs/draw.js +311 -139
  47. package/src/cjs/draw.js.map +1 -1
  48. package/src/cjs/drawgl.d.ts +93 -55
  49. package/src/cjs/drawgl.js +90 -34
  50. package/src/cjs/drawgl.js.map +1 -1
  51. package/src/cjs/drawutilssvg.d.ts +233 -58
  52. package/src/cjs/drawutilssvg.js +384 -95
  53. package/src/cjs/drawutilssvg.js.map +1 -1
  54. package/src/cjs/interfaces/DrawLib.d.ts +161 -82
  55. package/src/cjs/interfaces/DrawLib.js +7 -0
  56. package/src/cjs/interfaces/DrawLib.js.map +1 -1
  57. package/src/cjs/interfaces/core.d.ts +46 -32
  58. package/src/cjs/interfaces/core.js +2 -0
  59. package/src/cjs/interfaces/core.js.map +1 -1
  60. package/src/cjs/utils/creategui.js +16 -10
  61. package/src/cjs/utils/datastructures/Color.d.ts +3 -1
  62. package/src/cjs/utils/datastructures/Color.js +12 -1
  63. package/src/cjs/utils/datastructures/Color.js.map +1 -1
  64. package/src/cjs/utils/detectDarkMode.d.ts +10 -0
  65. package/src/cjs/utils/detectDarkMode.js +32 -0
  66. package/src/cjs/utils/detectDarkMode.js.map +1 -0
  67. package/src/cjs/utils/module.js +4 -2
  68. package/src/esm/BezierPath.d.ts +27 -49
  69. package/src/esm/BezierPath.js +69 -237
  70. package/src/esm/BezierPath.js.map +1 -1
  71. package/src/esm/Bounds.d.ts +14 -1
  72. package/src/esm/Bounds.js +19 -1
  73. package/src/esm/Bounds.js.map +1 -1
  74. package/src/esm/CubicBezierCurve.d.ts +70 -1
  75. package/src/esm/CubicBezierCurve.js +130 -12
  76. package/src/esm/CubicBezierCurve.js.map +1 -1
  77. package/src/esm/Line.d.ts +2 -1
  78. package/src/esm/Line.js +1 -0
  79. package/src/esm/Line.js.map +1 -1
  80. package/src/esm/PBText.d.ts +2 -1
  81. package/src/esm/PBText.js +10 -9
  82. package/src/esm/PBText.js.map +1 -1
  83. package/src/esm/PlotBoilerplate.d.ts +10 -13
  84. package/src/esm/PlotBoilerplate.js +136 -48
  85. package/src/esm/PlotBoilerplate.js.map +1 -1
  86. package/src/esm/Polygon.d.ts +35 -1
  87. package/src/esm/Polygon.js +85 -1
  88. package/src/esm/Polygon.js.map +1 -1
  89. package/src/esm/Triangle.js +1 -0
  90. package/src/esm/Triangle.js.map +1 -1
  91. package/src/esm/VEllipse.js +1 -1
  92. package/src/esm/VEllipse.js.map +1 -1
  93. package/src/esm/Vector.d.ts +4 -4
  94. package/src/esm/Vector.js +2 -2
  95. package/src/esm/Vector.js.map +1 -1
  96. package/src/esm/VertTuple.d.ts +2 -1
  97. package/src/esm/VertTuple.js +4 -3
  98. package/src/esm/VertTuple.js.map +1 -1
  99. package/src/esm/Vertex.d.ts +14 -3
  100. package/src/esm/Vertex.js +18 -3
  101. package/src/esm/Vertex.js.map +1 -1
  102. package/src/esm/draw.d.ts +159 -79
  103. package/src/esm/draw.js +307 -137
  104. package/src/esm/draw.js.map +1 -1
  105. package/src/esm/drawgl.d.ts +93 -55
  106. package/src/esm/drawgl.js +90 -34
  107. package/src/esm/drawgl.js.map +1 -1
  108. package/src/esm/drawutilssvg.d.ts +233 -58
  109. package/src/esm/drawutilssvg.js +379 -95
  110. package/src/esm/drawutilssvg.js.map +1 -1
  111. package/src/esm/interfaces/DrawLib.d.ts +161 -82
  112. package/src/esm/interfaces/DrawLib.js +7 -0
  113. package/src/esm/interfaces/DrawLib.js.map +1 -1
  114. package/src/esm/interfaces/core.d.ts +46 -32
  115. package/src/esm/interfaces/core.js +2 -0
  116. package/src/esm/interfaces/core.js.map +1 -1
  117. package/src/esm/utils/datastructures/Color.d.ts +3 -1
  118. package/src/esm/utils/datastructures/Color.js +12 -1
  119. package/src/esm/utils/datastructures/Color.js.map +1 -1
  120. package/src/esm/utils/detectDarkMode.d.ts +10 -0
  121. package/src/esm/utils/detectDarkMode.js +28 -0
  122. package/src/esm/utils/detectDarkMode.js.map +1 -0
  123. package/src/ts/BezierPath.ts +74 -244
  124. package/src/ts/Bounds.ts +25 -1
  125. package/src/ts/CubicBezierCurve.ts +139 -12
  126. package/src/ts/Line.ts +2 -1
  127. package/src/ts/PBText.ts +10 -9
  128. package/src/ts/PlotBoilerplate.ts +130 -50
  129. package/src/ts/Polygon.ts +91 -1
  130. package/src/ts/Triangle.ts +2 -1
  131. package/src/ts/VEllipse.ts +2 -2
  132. package/src/ts/Vector.ts +4 -4
  133. package/src/ts/VertTuple.ts +4 -3
  134. package/src/ts/Vertex.ts +20 -4
  135. package/src/ts/draw.ts +316 -119
  136. package/src/ts/drawgl.ts +141 -78
  137. package/src/ts/drawutilssvg.ts +562 -133
  138. package/src/ts/interfaces/DrawLib.ts +223 -86
  139. package/src/ts/interfaces/core.ts +47 -32
  140. package/src/ts/utils/datastructures/Color.ts +13 -1
  141. package/src/ts/utils/detectDarkMode.ts +30 -0
@@ -35,7 +35,17 @@
35
35
  * @modified 2022-03-26 Added the `texturedPoly` function to draw textures polygons.
36
36
  * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.
37
37
  * @modified 2022-11-10 Tweaking some type issues.
38
- * @version 1.6.2
38
+ * @modified 2023-02-04 Fixed a typo in the CSS classname for cubic Bézier paths: cubicBezier (was cubierBezier).
39
+ * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.
40
+ * @modified 2023-09-29 Added initialization checks for null parameters.
41
+ * @modified 2023-09-29 Added a missing implementation to the `drawurilssvg.do(XYCoords,string)` function. Didn't draw anything.
42
+ * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.
43
+ * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.
44
+ * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.
45
+ * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.
46
+ * @modified 2023-10-04 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.
47
+ *
48
+ * @version 1.6.7
39
49
  **/
40
50
 
41
51
  import { CircleSector } from "./CircleSector";
@@ -52,10 +62,12 @@ import {
52
62
  UID,
53
63
  DrawLibConfiguration,
54
64
  FontStyle,
55
- FontWeight
65
+ FontWeight,
66
+ StrokeOptions
56
67
  } from "./interfaces";
57
68
  import { Bounds } from "./Bounds";
58
69
  import { UIDGenerator } from "./UIDGenerator";
70
+ import { Vector } from "./Vector";
59
71
 
60
72
  const RAD_TO_DEG = 180 / Math.PI;
61
73
 
@@ -163,16 +175,16 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
163
175
  /**
164
176
  * The current drawable-ID. This can be any unique ID identifying the following drawn element.
165
177
  *
166
- * @member {UID|undefined}
178
+ * @member {UID|null}
167
179
  * @memberof drawutilssvg
168
180
  * @instance
169
181
  */
170
- private curId: UID | undefined;
182
+ private curId: UID | null;
171
183
 
172
184
  /**
173
185
  * The current drawable-classname.
174
186
  */
175
- private curClassName: string | undefined;
187
+ private curClassName: string | null;
176
188
 
177
189
  /**
178
190
  * The SVG element cache. On clear() all elements are kept for possible re-use on next draw cycle.
@@ -215,12 +227,15 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
215
227
  this.offset = new Vertex(0, 0).set(offset);
216
228
  this.scale = new Vertex(1, 1).set(scale);
217
229
  this.fillShapes = fillShapes;
218
- this.isSecondary = isSecondary;
230
+ this.isSecondary = Boolean(isSecondary);
219
231
 
220
232
  this.drawlibConfiguration = {} as DrawLibConfiguration;
221
233
  this.cache = new Map<UID, SVGElement>();
222
234
  this.setSize(canvasSize);
223
235
  if (isSecondary) {
236
+ if (!gNode || !bufferGNode || !nodeDefs || !bufferNodeDefs) {
237
+ throw "Cannot create secondary svg draw lib with undefinde gNode|bufferGNode|nodeDefs|bufferNodeDefs.";
238
+ }
224
239
  this.gNode = gNode;
225
240
  this.bufferGNode = bufferGNode;
226
241
  this.nodeDefs = nodeDefs;
@@ -247,6 +262,8 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
247
262
  // Which default styles to add? -> All from the DrawConfig.
248
263
  // Compare with DrawConfig interface
249
264
  const keys = {
265
+ // "bezier": "CubicBezierCurve", // TODO: is this correct?
266
+ "bezierPath": "BezierPath",
250
267
  "polygon": "Polygon",
251
268
  "triangle": "Triangle",
252
269
  "ellipse": "Ellipse",
@@ -313,8 +330,11 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
313
330
  * @param {UID} key - The key of the desired element (used when re-drawing).
314
331
  * @param {string} nodeName - The expected node name.
315
332
  */
316
- private findElement(key: UID, nodeName: string): SVGElement | undefined {
317
- var node: SVGElement = this.cache.get(key);
333
+ private findElement(key: UID | null, nodeName: string): SVGElement | null {
334
+ if (!key) {
335
+ return null;
336
+ }
337
+ var node: SVGElement | undefined = this.cache.get(key);
318
338
  if (node && node.nodeName.toUpperCase() === nodeName.toUpperCase()) {
319
339
  this.cache.delete(key);
320
340
  return node;
@@ -353,7 +373,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
353
373
  // Unique node keys are strictly necessary.
354
374
 
355
375
  // Try to recycle an old element from cache.
356
- var node: SVGElement | undefined = this.findElement(this.curId, nodeName);
376
+ var node: SVGElement | null = this.findElement(this.curId, nodeName);
357
377
  if (!node) {
358
378
  // If no such old elements exists (key not found, tag name not matching),
359
379
  // then create a new one.
@@ -362,6 +382,9 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
362
382
  if (this.drawlibConfiguration.blendMode) {
363
383
  node.style["mix-blend-mode"] = this.drawlibConfiguration.blendMode;
364
384
  }
385
+ // if (this.lineDashEnabled && this.lineDash && this.lineDash.length > 0 && drawutilssvg.nodeSupportsLineDash(nodeName)) {
386
+ // node.setAttribute("stroke-dasharray", this.lineDash.join(" "));
387
+ // }
365
388
  return node;
366
389
  }
367
390
 
@@ -385,22 +408,73 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
385
408
  * @param {number=1} lineWidth - (optional) A line width to use for drawing (default is 1).
386
409
  * @return {SVGElement} The node itself (for chaining).
387
410
  */
388
- private _bindFillDraw(node: SVGElement, className: string, color?: string | null, lineWidth?: number | null): SVGElement {
411
+ private _bindFillDraw(
412
+ node: SVGElement,
413
+ className: string,
414
+ color?: string | null,
415
+ lineWidth?: number | null,
416
+ strokeOptions?: StrokeOptions
417
+ ): SVGElement {
418
+ this._configureNode(node, className, this.fillShapes, color, lineWidth, strokeOptions);
419
+ return this._bindNode(node, undefined);
420
+ }
421
+
422
+ /**
423
+ * Bind this given node to a parent. If no parent is passed then the global
424
+ * node buffer will be used.
425
+ *
426
+ * @method _bindNode
427
+ * @private
428
+ * @instance
429
+ * @memberof drawutilssvg
430
+ * @param {SVGElement} node - The SVG node to bind.
431
+ * @param {SVGElement=} bindingParent - (optional) You may pass node other than the glober buffer node.
432
+ * @returns {SVGElement} The passed node itself.
433
+ */
434
+ private _bindNode(node: SVGElement, bindingParent?: SVGElement): SVGElement {
435
+ if (!node.parentNode) {
436
+ // Attach to DOM only if not already attached
437
+ (bindingParent ?? this.bufferGNode).appendChild(node);
438
+ }
439
+ return node;
440
+ }
441
+
442
+ /**
443
+ * Add custom CSS class names and the globally defined CSS classname to the
444
+ * given node.
445
+ *
446
+ * @method addCSSClasses
447
+ * @private
448
+ * @instance
449
+ * @memberof drawutilssvg
450
+ * @param {SVGElement} node - The SVG node to bind.
451
+ * @param {string} className - The additional custom classname to add.
452
+ * @returns {void}
453
+ */
454
+ private _addCSSClasses(node: SVGElement, className: string) {
389
455
  if (this.curClassName) {
390
456
  node.setAttribute("class", `${className} ${this.curClassName}`);
391
457
  } else {
392
458
  node.setAttribute("class", className);
393
459
  }
394
- node.setAttribute("fill", this.fillShapes ? color : "none");
395
- node.setAttribute("stroke", this.fillShapes ? "none" : color);
460
+ }
461
+
462
+ private _configureNode(
463
+ node: SVGElement,
464
+ className: string,
465
+ fillMode: boolean,
466
+ color?: string | null,
467
+ lineWidth?: number | null,
468
+ strokeOptions?: StrokeOptions
469
+ ): SVGElement {
470
+ this._addCSSClasses(node, className);
471
+ node.setAttribute("fill", fillMode && color ? color : "none");
472
+ node.setAttribute("stroke", fillMode ? "none" : color || "none");
396
473
  node.setAttribute("stroke-width", `${lineWidth || 1}`);
397
474
  if (this.curId) {
398
475
  node.setAttribute("id", `${this.curId}`); // Maybe React-style 'key' would be better?
399
476
  }
400
- if (!node.parentNode) {
401
- // Attach to DOM only if not already attached
402
- this.bufferGNode.appendChild(node);
403
- }
477
+ this.applyStrokeOpts(node, strokeOptions);
404
478
  return node;
405
479
  }
406
480
 
@@ -430,7 +504,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
430
504
  this.scale,
431
505
  this.canvasSize,
432
506
  fillShapes,
433
- null, // no DrawConfig
507
+ null as any as DrawConfig, // no DrawConfig – this will work as long as `isSecondary===true`
434
508
  true, // isSecondary
435
509
  this.gNode,
436
510
  this.bufferGNode,
@@ -451,17 +525,32 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
451
525
  this.drawlibConfiguration = configuration;
452
526
  }
453
527
 
528
+ // /**
529
+ // * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.
530
+ // *
531
+ // * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
532
+ // * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
533
+ // * for how line dashes work.
534
+ // *
535
+ // * @method
536
+ // * @param {Array<number> lineDashes - The line-dash array configuration.
537
+ // * @returns {void}
538
+ // */
539
+ // setLineDash(lineDashes: Array<number>) {
540
+ // this.lineDash = lineDashes;
541
+ // }
542
+
454
543
  /**
455
544
  * This method shouled be called each time the currently drawn `Drawable` changes.
456
545
  * It is used by some libraries for identifying elemente on re-renders.
457
546
  *
458
547
  * @name setCurrentId
459
548
  * @method
460
- * @param {UID} uid - A UID identifying the currently drawn element(s).
549
+ * @param {UID|null} uid - A UID identifying the currently drawn element(s).
461
550
  * @instance
462
551
  * @memberof drawutilssvg
463
552
  **/
464
- setCurrentId(uid: UID | undefined): void {
553
+ setCurrentId(uid: UID | null): void {
465
554
  this.curId = uid;
466
555
  }
467
556
 
@@ -471,11 +560,11 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
471
560
  *
472
561
  * @name setCurrentClassName
473
562
  * @method
474
- * @param {string} className - A class name for further custom use cases.
563
+ * @param {string|null} className - A class name for further custom use cases.
475
564
  * @instance
476
565
  * @memberof drawutilssvg
477
566
  **/
478
- setCurrentClassName(className: string | undefined): void {
567
+ setCurrentClassName(className: string | null): void {
479
568
  this.curClassName = className;
480
569
  }
481
570
 
@@ -498,7 +587,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
498
587
  // Hide all nodes here. Don't throw them away.
499
588
  // We can probably re-use them in the next draw cycle.
500
589
  var child: SVGElement = this.bufferGNode.childNodes[i] as SVGElement;
501
- this.cache.set(child.getAttribute("id"), child);
590
+ this.cache.set(child.getAttribute("id") as string, child);
502
591
  }
503
592
  this.removeAllChildNodes();
504
593
  }
@@ -531,6 +620,32 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
531
620
  this.bufferedNodeDefs = tmpDefsNode;
532
621
  }
533
622
 
623
+ /**
624
+ * A private helper method to apply stroke options to the current
625
+ * context.
626
+ * @param {StrokeOptions=} strokeOptions -
627
+ */
628
+ private applyStrokeOpts(node: SVGElement, strokeOptions?: StrokeOptions) {
629
+ if (
630
+ strokeOptions &&
631
+ strokeOptions.dashArray &&
632
+ strokeOptions.dashArray.length > 0 &&
633
+ drawutilssvg.nodeSupportsLineDash(node.tagName)
634
+ ) {
635
+ node.setAttribute(
636
+ "stroke-dasharray",
637
+ strokeOptions.dashArray
638
+ .map((dashArayElem: number) => {
639
+ return dashArayElem * this.scale.x;
640
+ })
641
+ .join(" ")
642
+ );
643
+ if (strokeOptions.dashOffset) {
644
+ node.setAttribute("stroke-dashoffset", `${strokeOptions.dashOffset * this.scale.x}`);
645
+ }
646
+ }
647
+ }
648
+
534
649
  private _x(x: number): number {
535
650
  return this.offset.x + this.scale.x * x;
536
651
  }
@@ -542,49 +657,143 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
542
657
  * Draw the line between the given two points with the specified (CSS-) color.
543
658
  *
544
659
  * @method line
545
- * @param {Vertex} zA - The start point of the line.
546
- * @param {Vertex} zB - The end point of the line.
660
+ * @param {XYCoords} zA - The start point of the line.
661
+ * @param {XYCoords} zB - The end point of the line.
547
662
  * @param {string} color - Any valid CSS color string.
548
663
  * @param {number=1} lineWidth? - [optional] The line's width.
664
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
665
+ *
549
666
  * @return {void}
550
667
  * @instance
551
668
  * @memberof drawutilssvg
552
669
  **/
553
- line(zA: Vertex, zB: Vertex, color: string, lineWidth?: number): SVGElement {
554
- const line: SVGElement = this.makeNode("line");
555
- line.setAttribute("x1", `${this._x(zA.x)}`);
556
- line.setAttribute("y1", `${this._y(zA.y)}`);
557
- line.setAttribute("x2", `${this._x(zB.x)}`);
558
- line.setAttribute("y2", `${this._y(zB.y)}`);
559
-
560
- return this._bindFillDraw(line, "line", color, lineWidth || 1);
670
+ line(zA: XYCoords, zB: XYCoords, color: string, lineWidth?: number, strokeOptions?: StrokeOptions): SVGElement {
671
+ // const line: SVGElement = this.makeNode("line");
672
+ // this.applyStrokeOpts(line, strokeOptions);
673
+ // line.setAttribute("x1", `${this._x(zA.x)}`);
674
+ // line.setAttribute("y1", `${this._y(zA.y)}`);
675
+ // line.setAttribute("x2", `${this._x(zB.x)}`);
676
+ // line.setAttribute("y2", `${this._y(zB.y)}`);
677
+ const line = this.makeLineNode(zA, zB, color, lineWidth, strokeOptions);
678
+ return this._bindFillDraw(line, "line", color, lineWidth || 1, strokeOptions);
561
679
  }
562
680
 
563
681
  /**
564
682
  * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.
565
683
  *
566
684
  * @method arrow
567
- * @param {Vertex} zA - The start point of the arrow-line.
568
- * @param {Vertex} zB - The end point of the arrow-line.
685
+ * @param {XYCoords} zA - The start point of the arrow-line.
686
+ * @param {XYCoords} zB - The end point of the arrow-line.
569
687
  * @param {string} color - Any valid CSS color string.
570
688
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
689
+ * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).
690
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
691
+ *
571
692
  * @return {void}
572
693
  * @instance
573
694
  * @memberof drawutilssvg
574
695
  **/
575
- arrow(zA: Vertex, zB: Vertex, color: string, lineWidth?: number): SVGElement {
576
- const node: SVGElement = this.makeNode("path");
577
- var headlen: number = 8; // length of head in pixels
578
- var vertices: Array<Vertex> = Vertex.utils.buildArrowHead(zA, zB, headlen, this.scale.x, this.scale.y);
579
- const d: Array<string | number> = ["M", this._x(zA.x), this._y(zA.y)];
580
- for (var i = 0; i <= vertices.length; i++) {
581
- d.push("L");
582
- // Note: only use offset here (the vertices are already scaled)
583
- d.push(this.offset.x + vertices[i % vertices.length].x);
584
- d.push(this.offset.y + vertices[i % vertices.length].y);
585
- }
586
- node.setAttribute("d", d.join(" "));
587
- return this._bindFillDraw(node, "arrow", color, lineWidth || 1);
696
+ arrow(
697
+ zA: XYCoords,
698
+ zB: XYCoords,
699
+ color: string,
700
+ lineWidth?: number,
701
+ headLength: number = 8,
702
+ strokeOptions?: StrokeOptions
703
+ ): SVGElement {
704
+ const group: SVGElement = this.makeNode("g");
705
+ const arrowHeadBasePosition: XYCoords = { x: 0, y: 0 };
706
+ // Just create the child nodes, don't bind them to the root node.
707
+ const arrowHead: SVGElement = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition);
708
+ const line: SVGElement = this.makeLineNode(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions);
709
+ group.appendChild(line);
710
+ group.appendChild(arrowHead);
711
+ this._addCSSClasses(group, "linear-arrow");
712
+ this._bindNode(group, undefined);
713
+ return group;
714
+ }
715
+
716
+ /**
717
+ * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.
718
+ *
719
+ * @method cubicBezierArrow
720
+ * @param {XYCoords} startPoint - The start point of the cubic Bézier curve
721
+ * @param {XYCoords} endPoint - The end point the cubic Bézier curve.
722
+ * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
723
+ * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
724
+ * @param {string} color - The CSS color to draw the curve with.
725
+ * @param {number} lineWidth - (optional) The line width to use.
726
+ * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).
727
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
728
+ *
729
+ * @return {void}
730
+ * @instance
731
+ * @memberof DrawLib
732
+ */
733
+ cubicBezierArrow(
734
+ startPoint: XYCoords,
735
+ endPoint: XYCoords,
736
+ startControlPoint: XYCoords,
737
+ endControlPoint: XYCoords,
738
+ color: string,
739
+ lineWidth?: number,
740
+ headLength: number = 8,
741
+ strokeOptions?: StrokeOptions
742
+ ): SVGElement {
743
+ const group: SVGElement = this.makeNode("g");
744
+ // Just create the child nodes, don't bind them to the root node.
745
+ const arrowHeadBasePosition = new Vertex(0, 0);
746
+ const arrowHead: SVGElement = this.makeArrowHeadNode(
747
+ endControlPoint,
748
+ endPoint,
749
+ color,
750
+ lineWidth,
751
+ headLength,
752
+ undefined,
753
+ arrowHeadBasePosition
754
+ );
755
+ const diff = arrowHeadBasePosition.difference(endPoint);
756
+ const bezier: SVGElement = this.makeCubicBezierNode(
757
+ startPoint,
758
+ { x: endPoint.x - diff.x, y: endPoint.y - diff.y },
759
+ startControlPoint,
760
+ { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y },
761
+ color,
762
+ lineWidth,
763
+ strokeOptions
764
+ );
765
+ group.appendChild(bezier);
766
+ group.appendChild(arrowHead);
767
+ this._addCSSClasses(group, "cubicbezier-arrow");
768
+ this._bindNode(group, undefined);
769
+ return group;
770
+ }
771
+
772
+ /**
773
+ * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.
774
+ *
775
+ * @method arrow
776
+ * @param {XYCoords} zA - The start point of the arrow-line.
777
+ * @param {XYCoords} zB - The end point of the arrow-line.
778
+ * @param {string} color - Any valid CSS color string.
779
+ * @param {number=1} lineWidth - (optional) The line width to use; default is 1.
780
+ * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).
781
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
782
+ *
783
+ * @return {void}
784
+ * @instance
785
+ * @memberof DrawLib
786
+ **/
787
+ arrowHead(
788
+ zA: XYCoords,
789
+ zB: XYCoords,
790
+ color: string,
791
+ lineWidth?: number,
792
+ headLength: number = 8,
793
+ strokeOptions?: StrokeOptions
794
+ ): SVGElement {
795
+ const node: SVGElement = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, strokeOptions);
796
+ return this._bindFillDraw(node, "arrowhead", color, lineWidth || 1, strokeOptions);
588
797
  }
589
798
 
590
799
  /**
@@ -594,14 +803,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
594
803
  *
595
804
  * @method image
596
805
  * @param {Image} image - The image object to draw.
597
- * @param {Vertex} position - The position to draw the the upper left corner at.
598
- * @param {Vertex} size - The x/y-size to draw the image with.
806
+ * @param {XYCoords} position - The position to draw the the upper left corner at.
807
+ * @param {XYCoords} size - The x/y-size to draw the image with.
599
808
  * @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).
600
809
  * @return {void}
601
810
  * @instance
602
811
  * @memberof drawutilssvg
603
812
  **/
604
- image(image: HTMLImageElement, position: Vertex, size: Vertex, alpha: number = 1.0) {
813
+ image(image: HTMLImageElement, position: XYCoords, size: XYCoords, alpha: number = 1.0) {
605
814
  const node: SVGElement = this.makeNode("image");
606
815
 
607
816
  // We need to re-adjust the image if it was not yet fully loaded before.
@@ -611,7 +820,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
611
820
  const ratioY = size.y / image.naturalHeight;
612
821
  node.setAttribute("width", `${image.naturalWidth * this.scale.x}`);
613
822
  node.setAttribute("height", `${image.naturalHeight * this.scale.y}`);
614
- node.setAttribute("display", null); // Dislay when loaded
823
+ node.setAttribute("display", null as any as string); // Dislay when loaded
615
824
  // if (alpha) {
616
825
  node.setAttribute("opacity", `${alpha}`);
617
826
  // }
@@ -641,7 +850,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
641
850
  * @param {Image} textureImage - The image object to draw.
642
851
  * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.
643
852
  * @param {Polygon} polygon - The polygon to use as clip path.
644
- * @param {Vertex} polygonPosition - The polygon's position (relative), measured at the bounding box's center.
853
+ * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.
645
854
  * @param {number} rotation - The rotation to use for the polygon (and for the texture).
646
855
  * @return {void}
647
856
  * @instance
@@ -651,12 +860,12 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
651
860
  textureImage: HTMLImageElement,
652
861
  textureSize: Bounds,
653
862
  polygon: Polygon,
654
- polygonPosition: Vertex,
863
+ polygonPosition: XYCoords,
655
864
  rotation: number
656
865
  ): SVGElement {
657
- const basePolygonBounds: Bounds = polygon.getBounds();
866
+ // const basePolygonBounds: Bounds = polygon.getBounds();
658
867
  const rotatedScalingOrigin = new Vertex(textureSize.min).clone().rotate(rotation, polygonPosition);
659
- const rotationCenter = polygonPosition.clone().add(rotatedScalingOrigin.difference(textureSize.min).inv());
868
+ // const rotationCenter = polygonPosition.clone().add(rotatedScalingOrigin.difference(textureSize.min).inv());
660
869
  // Create something like this
661
870
  // ...
662
871
  // <defs>
@@ -720,50 +929,37 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
720
929
  * Draw the given (cubic) bézier curve.
721
930
  *
722
931
  * @method cubicBezier
723
- * @param {Vertex} startPoint - The start point of the cubic Bézier curve
724
- * @param {Vertex} endPoint - The end point the cubic Bézier curve.
725
- * @param {Vertex} startControlPoint - The start control point the cubic Bézier curve.
726
- * @param {Vertex} endControlPoint - The end control point the cubic Bézier curve.
932
+ * @param {XYCoords} startPoint - The start point of the cubic Bézier curve
933
+ * @param {XYCoords} endPoint - The end point the cubic Bézier curve.
934
+ * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
935
+ * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
727
936
  * @param {string} color - The CSS color to draw the curve with.
728
937
  * @param {number} lineWidth - (optional) The line width to use.
938
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
939
+ *
729
940
  * @return {void}
730
941
  * @instance
731
942
  * @memberof drawutilssvg
732
943
  */
733
944
  cubicBezier(
734
- startPoint: Vertex,
735
- endPoint: Vertex,
736
- startControlPoint: Vertex,
737
- endControlPoint: Vertex,
945
+ startPoint: XYCoords,
946
+ endPoint: XYCoords,
947
+ startControlPoint: XYCoords,
948
+ endControlPoint: XYCoords,
738
949
  color: string,
739
- lineWidth?: number
950
+ lineWidth?: number,
951
+ strokeOptions?: StrokeOptions
740
952
  ): SVGElement {
741
- if (startPoint instanceof CubicBezierCurve) {
742
- return this.cubicBezier(
743
- startPoint.startPoint,
744
- startPoint.endPoint,
745
- startPoint.startControlPoint,
746
- startPoint.endControlPoint,
747
- color,
748
- lineWidth
749
- );
750
- }
751
- const node: SVGElement = this.makeNode("path");
752
- // Draw curve
753
- const d: Array<string | number> = [
754
- "M",
755
- this._x(startPoint.x),
756
- this._y(startPoint.y),
757
- "C",
758
- this._x(startControlPoint.x),
759
- this._y(startControlPoint.y),
760
- this._x(endControlPoint.x),
761
- this._y(endControlPoint.y),
762
- this._x(endPoint.x),
763
- this._y(endPoint.y)
764
- ];
765
- node.setAttribute("d", d.join(" "));
766
- return this._bindFillDraw(node, "cubierBezier", color, lineWidth);
953
+ const node: SVGElement = this.makeCubicBezierNode(
954
+ startPoint,
955
+ endPoint,
956
+ startControlPoint,
957
+ endControlPoint,
958
+ color,
959
+ lineWidth,
960
+ strokeOptions
961
+ );
962
+ return this._bindNode(node, undefined);
767
963
  }
768
964
 
769
965
  /**
@@ -774,24 +970,29 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
774
970
  * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>
775
971
  *
776
972
  * @method cubicBezierPath
777
- * @param {Vertex[]} path - The cubic bezier path as described above.
973
+ * @param {XYCoords[]} path - The cubic bezier path as described above.
778
974
  * @param {string} color - The CSS colot to draw the path with.
779
975
  * @param {number=1} lineWidth - (optional) The line width to use.
976
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
977
+ *
780
978
  * @return {void}
781
979
  * @instance
782
980
  * @memberof drawutilssvg
783
981
  */
784
- cubicBezierPath(path: Array<Vertex>, color: string, lineWidth?: number): SVGElement {
982
+ cubicBezierPath(path: Array<XYCoords>, color: string, lineWidth?: number, strokeOptions?: StrokeOptions): SVGElement {
785
983
  const node: SVGElement = this.makeNode("path");
786
- if (!path || path.length == 0) return node;
984
+ this.applyStrokeOpts(node, strokeOptions);
985
+ if (!path || path.length == 0) {
986
+ return node;
987
+ }
787
988
 
788
989
  // Draw curve
789
990
  const d: Array<string | number> = ["M", this._x(path[0].x), this._y(path[0].y)];
790
991
 
791
992
  // Draw curve path
792
- var endPoint: Vertex;
793
- var startControlPoint: Vertex;
794
- var endControlPoint: Vertex;
993
+ var endPoint: XYCoords;
994
+ var startControlPoint: XYCoords;
995
+ var endControlPoint: XYCoords;
795
996
  for (var i = 1; i < path.length; i += 3) {
796
997
  startControlPoint = path[i];
797
998
  endControlPoint = path[i + 1];
@@ -822,7 +1023,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
822
1023
  * @instance
823
1024
  * @memberof drawutilssvg
824
1025
  */
825
- handle(startPoint: Vertex, endPoint: Vertex): void {
1026
+ handle(startPoint: XYCoords, endPoint: XYCoords): void {
826
1027
  // TODO: redefine methods like these into an abstract class?
827
1028
  this.point(startPoint, "rgb(0,32,192)");
828
1029
  this.square(endPoint, 5, "rgba(0,128,192,0.5)");
@@ -832,28 +1033,32 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
832
1033
  * Draw a handle line (with a light grey).
833
1034
  *
834
1035
  * @method handleLine
835
- * @param {Vertex} startPoint - The start point to draw the handle at.
836
- * @param {Vertex} endPoint - The end point to draw the handle at.
1036
+ * @param {XYCoords} startPoint - The start point to draw the handle at.
1037
+ * @param {XYCoords} endPoint - The end point to draw the handle at.
837
1038
  * @return {void}
838
1039
  * @instance
839
1040
  * @memberof drawutilssvg
840
1041
  */
841
- handleLine(startPoint: Vertex, endPoint: Vertex): void {
842
- this.line(startPoint, endPoint, "rgb(192,192,192)");
1042
+ handleLine(startPoint: XYCoords, endPoint: XYCoords): void {
1043
+ this.line(startPoint, endPoint, "rgb(128,128,128,0.5)");
843
1044
  }
844
1045
 
845
1046
  /**
846
1047
  * Draw a 1x1 dot with the specified (CSS-) color.
847
1048
  *
848
1049
  * @method dot
849
- * @param {Vertex} p - The position to draw the dot at.
1050
+ * @param {XYCoords} p - The position to draw the dot at.
850
1051
  * @param {string} color - The CSS color to draw the dot with.
851
1052
  * @return {void}
852
1053
  * @instance
853
1054
  * @memberof drawutilssvg
854
1055
  */
855
- dot(p: Vertex, color: string) {
1056
+ dot(p: XYCoords, color: string) {
856
1057
  const node: SVGElement = this.makeNode("line");
1058
+ node.setAttribute("x1", `${this._x(p.x)}`);
1059
+ node.setAttribute("y1", `${this._y(p.y)}`);
1060
+ node.setAttribute("x2", `${this._x(p.x)}`);
1061
+ node.setAttribute("y2", `${this._y(p.y)}`);
857
1062
  return this._bindFillDraw(node, "dot", color, 1);
858
1063
  }
859
1064
 
@@ -861,13 +1066,13 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
861
1066
  * Draw the given point with the specified (CSS-) color and radius 3.
862
1067
  *
863
1068
  * @method point
864
- * @param {Vertex} p - The position to draw the point at.
1069
+ * @param {XYCoords} p - The position to draw the point at.
865
1070
  * @param {string} color - The CSS color to draw the point with.
866
1071
  * @return {void}
867
1072
  * @instance
868
1073
  * @memberof drawutilssvg
869
1074
  */
870
- point(p: Vertex, color: string) {
1075
+ point(p: XYCoords, color: string) {
871
1076
  var radius: number = 3;
872
1077
  const node: SVGElement = this.makeNode("circle");
873
1078
  node.setAttribute("cx", `${this._x(p.x)}`);
@@ -882,17 +1087,21 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
882
1087
  * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.
883
1088
  *
884
1089
  * @method circle
885
- * @param {Vertex} center - The center of the circle.
1090
+ * @param {XYCoords} center - The center of the circle.
886
1091
  * @param {number} radius - The radius of the circle.
887
1092
  * @param {string} color - The CSS color to draw the circle with.
888
1093
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
1094
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1095
+ *
889
1096
  * @return {void}
890
1097
  * @instance
891
1098
  * @memberof drawutilssvg
892
1099
  */
893
- circle(center: Vertex, radius: number, color: string, lineWidth?: number) {
1100
+ circle(center: XYCoords, radius: number, color: string, lineWidth?: number, strokeOptions?: StrokeOptions) {
894
1101
  // Todo: draw ellipse when scalex!=scaley
895
1102
  const node: SVGElement = this.makeNode("circle");
1103
+ this.applyStrokeOpts(node, strokeOptions);
1104
+
896
1105
  node.setAttribute("cx", `${this._x(center.x)}`);
897
1106
  node.setAttribute("cy", `${this._y(center.y)}`);
898
1107
  node.setAttribute("r", `${radius * this.scale.x}`); // y?
@@ -904,17 +1113,29 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
904
1113
  * Draw a circular arc (section of a circle) with the given CSS color.
905
1114
  *
906
1115
  * @method circleArc
907
- * @param {Vertex} center - The center of the circle.
1116
+ * @param {XYCoords} center - The center of the circle.
908
1117
  * @param {number} radius - The radius of the circle.
909
1118
  * @param {number} startAngle - The angle to start at.
910
1119
  * @param {number} endAngle - The angle to end at.
911
1120
  * @param {string} color - The CSS color to draw the circle with.
1121
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1122
+ *
912
1123
  * @return {void}
913
1124
  * @instance
914
1125
  * @memberof drawutilssvg
915
1126
  */
916
- circleArc(center: Vertex, radius: number, startAngle: number, endAngle: number, color: string, lineWidth?: number) {
1127
+ circleArc(
1128
+ center: XYCoords,
1129
+ radius: number,
1130
+ startAngle: number,
1131
+ endAngle: number,
1132
+ color: string,
1133
+ lineWidth?: number,
1134
+ strokeOptions?: StrokeOptions
1135
+ ) {
917
1136
  const node: SVGElement = this.makeNode("path");
1137
+ this.applyStrokeOpts(node, strokeOptions);
1138
+
918
1139
  const arcData: SVGPathParams = CircleSector.circleSectorUtils.describeSVGArc(
919
1140
  this._x(center.x),
920
1141
  this._y(center.y),
@@ -930,21 +1151,33 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
930
1151
  * Draw an ellipse with the specified (CSS-) color and thw two radii.
931
1152
  *
932
1153
  * @method ellipse
933
- * @param {Vertex} center - The center of the ellipse.
1154
+ * @param {XYCoords} center - The center of the ellipse.
934
1155
  * @param {number} radiusX - The radius of the ellipse.
935
1156
  * @param {number} radiusY - The radius of the ellipse.
936
1157
  * @param {string} color - The CSS color to draw the ellipse with.
937
1158
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
938
1159
  * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.
1160
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1161
+ *
939
1162
  * @return {void}
940
1163
  * @instance
941
1164
  * @memberof drawutilssvg
942
1165
  */
943
- ellipse(center: Vertex, radiusX: number, radiusY: number, color: string, lineWidth?: number, rotation?: number) {
1166
+ ellipse(
1167
+ center: XYCoords,
1168
+ radiusX: number,
1169
+ radiusY: number,
1170
+ color: string,
1171
+ lineWidth?: number,
1172
+ rotation?: number,
1173
+ strokeOptions?: StrokeOptions
1174
+ ) {
944
1175
  if (typeof rotation === "undefined") {
945
1176
  rotation = 0.0;
946
1177
  }
947
1178
  const node: SVGElement = this.makeNode("ellipse");
1179
+ this.applyStrokeOpts(node, strokeOptions);
1180
+
948
1181
  node.setAttribute("cx", `${this._x(center.x)}`);
949
1182
  node.setAttribute("cy", `${this._y(center.y)}`);
950
1183
  node.setAttribute("rx", `${radiusX * this.scale.x}`);
@@ -962,15 +1195,19 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
962
1195
  *
963
1196
  * @method square
964
1197
  * @param {XYCoords} center - The center of the square.
965
- * @param {Vertex} size - The size of the square.
1198
+ * @param {number} size - The size of the square.
966
1199
  * @param {string} color - The CSS color to draw the square with.
967
1200
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
968
- * @return {void}
1201
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1202
+ *
1203
+ * @return {SVGElement}
969
1204
  * @instance
970
1205
  * @memberof drawutilssvg
971
1206
  */
972
- square(center: XYCoords, size: number, color: string, lineWidth?: number) {
1207
+ square(center: XYCoords, size: number, color: string, lineWidth?: number, strokeOptions?: StrokeOptions): SVGElement {
973
1208
  const node: SVGElement = this.makeNode("rectangle");
1209
+ this.applyStrokeOpts(node, strokeOptions);
1210
+
974
1211
  node.setAttribute("x", `${this._x(center.x - size / 2.0)}`);
975
1212
  node.setAttribute("y", `${this._y(center.y - size / 2.0)}`);
976
1213
  node.setAttribute("width", `${size * this.scale.x}`);
@@ -987,9 +1224,23 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
987
1224
  * @param {number} height - The height of the rectangle.
988
1225
  * @param {string} color - The color to use.
989
1226
  * @param {number=1} lineWidth - (optional) The line with to use (default is 1).
1227
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1228
+ *
1229
+ * @return {SVGElement}
1230
+ * @instance
1231
+ * @memberof drawutilssvg
990
1232
  **/
991
- rect(position: XYCoords, width: number, height: number, color: string, lineWidth?: number) {
1233
+ rect(
1234
+ position: XYCoords,
1235
+ width: number,
1236
+ height: number,
1237
+ color: string,
1238
+ lineWidth?: number,
1239
+ strokeOptions?: StrokeOptions
1240
+ ): SVGElement {
992
1241
  const node: SVGElement = this.makeNode("rect");
1242
+ this.applyStrokeOpts(node, strokeOptions);
1243
+
993
1244
  node.setAttribute("x", `${this._x(position.x)}`);
994
1245
  node.setAttribute("y", `${this._y(position.y)}`);
995
1246
  node.setAttribute("width", `${width * this.scale.x}`);
@@ -1002,7 +1253,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1002
1253
  * Draw a grid of horizontal and vertical lines with the given (CSS-) color.
1003
1254
  *
1004
1255
  * @method grid
1005
- * @param {Vertex} center - The center of the grid.
1256
+ * @param {XYCoords} center - The center of the grid.
1006
1257
  * @param {number} width - The total width of the grid (width/2 each to the left and to the right).
1007
1258
  * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).
1008
1259
  * @param {number} sizeX - The horizontal grid size.
@@ -1012,7 +1263,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1012
1263
  * @instance
1013
1264
  * @memberof drawutilssvg
1014
1265
  */
1015
- grid(center: Vertex, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1266
+ grid(center: XYCoords, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1016
1267
  const node: SVGElement = this.makeNode("path");
1017
1268
  const d: SVGPathParams = [];
1018
1269
 
@@ -1039,7 +1290,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1039
1290
  * This works analogue to the grid() function
1040
1291
  *
1041
1292
  * @method raster
1042
- * @param {Vertex} center - The center of the raster.
1293
+ * @param {XYCoords} center - The center of the raster.
1043
1294
  * @param {number} width - The total width of the raster (width/2 each to the left and to the right).
1044
1295
  * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).
1045
1296
  * @param {number} sizeX - The horizontal raster size.
@@ -1049,7 +1300,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1049
1300
  * @instance
1050
1301
  * @memberof drawutilssvg
1051
1302
  */
1052
- raster(center: Vertex, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1303
+ raster(center: XYCoords, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1053
1304
  const node: SVGElement = this.makeNode("path");
1054
1305
  const d: SVGPathParams = [];
1055
1306
 
@@ -1076,14 +1327,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1076
1327
  * as even shaped diamonds.
1077
1328
  *
1078
1329
  * @method diamondHandle
1079
- * @param {Vertex} center - The center of the diamond.
1080
- * @param {Vertex} size - The x/y-size of the diamond.
1330
+ * @param {XYCoords} center - The center of the diamond.
1331
+ * @param {number} size - The x/y-size of the diamond.
1081
1332
  * @param {string} color - The CSS color to draw the diamond with.
1082
1333
  * @return {void}
1083
1334
  * @instance
1084
1335
  * @memberof drawutilssvg
1085
1336
  */
1086
- diamondHandle(center: Vertex, size: number, color: string) {
1337
+ diamondHandle(center: XYCoords, size: number, color: string) {
1087
1338
  const node: SVGElement = this.makeNode("path");
1088
1339
  const d: SVGPathParams = [
1089
1340
  "M",
@@ -1112,14 +1363,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1112
1363
  * as even shaped squares.
1113
1364
  *
1114
1365
  * @method squareHandle
1115
- * @param {Vertex} center - The center of the square.
1116
- * @param {Vertex} size - The x/y-size of the square.
1366
+ * @param {XYCoords} center - The center of the square.
1367
+ * @param {XYCoords} size - The x/y-size of the square.
1117
1368
  * @param {string} color - The CSS color to draw the square with.
1118
1369
  * @return {void}
1119
1370
  * @instance
1120
1371
  * @memberof drawutilssvg
1121
1372
  */
1122
- squareHandle(center: Vertex, size: number, color: string) {
1373
+ squareHandle(center: XYCoords, size: number, color: string) {
1123
1374
  const node: SVGElement = this.makeNode("rect");
1124
1375
  node.setAttribute("x", `${this._x(center.x) - size / 2.0}`);
1125
1376
  node.setAttribute("y", `${this._y(center.y) - size / 2.0}`);
@@ -1136,14 +1387,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1136
1387
  * as even shaped circles.
1137
1388
  *
1138
1389
  * @method circleHandle
1139
- * @param {Vertex} center - The center of the circle.
1390
+ * @param {XYCoords} center - The center of the circle.
1140
1391
  * @param {number} radius - The radius of the circle.
1141
1392
  * @param {string} color - The CSS color to draw the circle with.
1142
1393
  * @return {void}
1143
1394
  * @instance
1144
1395
  * @memberof drawutilssvg
1145
1396
  */
1146
- circleHandle(center: Vertex, radius: number, color: string) {
1397
+ circleHandle(center: XYCoords, radius: number, color: string) {
1147
1398
  radius = radius || 3;
1148
1399
 
1149
1400
  const node: SVGElement = this.makeNode("circle");
@@ -1240,17 +1491,29 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1240
1491
  * Draw a polygon line (alternative function to the polygon).
1241
1492
  *
1242
1493
  * @method polyline
1243
- * @param {Vertex[]} vertices - The polygon vertices to draw.
1494
+ * @param {XYCoords[]} vertices - The polygon vertices to draw.
1244
1495
  * @param {boolan} isOpen - If true the polyline will not be closed at its end.
1245
1496
  * @param {string} color - The CSS color to draw the polygon with.
1246
1497
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
1498
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1499
+ *
1247
1500
  * @return {void}
1248
1501
  * @instance
1249
1502
  * @memberof drawutilssvg
1250
1503
  */
1251
- polyline(vertices: Array<Vertex>, isOpen: boolean, color: string, lineWidth?: number): SVGElement {
1504
+ polyline(
1505
+ vertices: Array<XYCoords>,
1506
+ isOpen: boolean,
1507
+ color: string,
1508
+ lineWidth?: number,
1509
+ strokeOptions?: StrokeOptions
1510
+ ): SVGElement {
1252
1511
  const node: SVGElement = this.makeNode("path");
1253
- if (vertices.length == 0) return node;
1512
+ this.applyStrokeOpts(node, strokeOptions);
1513
+
1514
+ if (vertices.length == 0) {
1515
+ return node;
1516
+ }
1254
1517
  // Draw curve
1255
1518
  const d: Array<string | number> = ["M", this._x(vertices[0].x), this._y(vertices[0].y)];
1256
1519
  var n = vertices.length;
@@ -1373,12 +1636,17 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1373
1636
  * @param {string=null} color - (optional) The color to draw this path with (default is null).
1374
1637
  * @param {number=1} lineWidth - (optional) the line width to use (default is 1).
1375
1638
  * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.
1639
+ * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.
1640
+ * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.
1641
+ *
1376
1642
  * @instance
1377
1643
  * @memberof drawutils
1378
1644
  * @return {R} An instance representing the drawn path.
1379
1645
  */
1380
- path(pathData: SVGPathParams, color?: string, lineWidth?: number, options?: { inplace?: boolean }): SVGElement {
1646
+ path(pathData: SVGPathParams, color?: string, lineWidth?: number, options?: { inplace?: boolean } & StrokeOptions): SVGElement {
1381
1647
  const node: SVGElement = this.makeNode("path");
1648
+ this.applyStrokeOpts(node, options);
1649
+
1382
1650
  // Transform the path: in-place (fast) or copy (slower)
1383
1651
  const d: SVGPathParams = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);
1384
1652
  drawutilssvg.transformPathData(d, this.offset, this.scale);
@@ -1406,7 +1674,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1406
1674
 
1407
1675
  // Add a covering rect with the given background color
1408
1676
  this.curId = "background";
1409
- this.curClassName = undefined;
1677
+ this.curClassName = null; // undefined;
1410
1678
  const node: SVGElement = this.makeNode("rect");
1411
1679
  // For some strange reason SVG rotation transforms use degrees instead of radians
1412
1680
  // Note that the background does not scale with the zoom level (always covers full element)
@@ -1419,7 +1687,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1419
1687
  this._bindFillDraw(node, this.curId, null, null);
1420
1688
  node.setAttribute("fill", typeof color === "undefined" ? "none" : color);
1421
1689
  // Clear the current ID again
1422
- this.curId = undefined;
1690
+ this.curId = null; // undefined;
1423
1691
  }
1424
1692
 
1425
1693
  /**
@@ -1630,4 +1898,165 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1630
1898
  }
1631
1899
  } // END while
1632
1900
  } // END transformPathData
1901
+
1902
+ private static nodeSupportsLineDash(nodeName: string) {
1903
+ return ["line", "path", "circle", "ellipse", "rectangle", "rect"].includes(nodeName);
1904
+ }
1905
+
1906
+ /**
1907
+ * Creates a basic <line> node with start and end coordinates. The created node will not
1908
+ * be bound to any root node.
1909
+ *
1910
+ * @private
1911
+ * @method makeLineNode
1912
+ * @param {XYCoords} zA - The line's start position.
1913
+ * @param {XYCoords} zB - The line's start position.
1914
+ * @param {string} color - The CSS color to draw the point with.
1915
+ * @param {number=1} lineWidth - (optional) The line width to use.
1916
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
1917
+ * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.
1918
+ * @return {SVGLineElement}
1919
+ * @instance
1920
+ * @memberof drawutilssvg
1921
+ */
1922
+ private makeLineNode(
1923
+ zA: XYCoords,
1924
+ zB: XYCoords,
1925
+ color: string,
1926
+ lineWidth?: number,
1927
+ strokeOptions?: StrokeOptions,
1928
+ classNameOverride?: string
1929
+ ): SVGLineElement {
1930
+ const line: SVGLineElement = this.makeNode("line") as SVGLineElement;
1931
+ line.setAttribute("x1", `${this._x(zA.x)}`);
1932
+ line.setAttribute("y1", `${this._y(zA.y)}`);
1933
+ line.setAttribute("x2", `${this._x(zB.x)}`);
1934
+ line.setAttribute("y2", `${this._y(zB.y)}`);
1935
+ this._configureNode(line, classNameOverride ?? "line", this.fillShapes, color, lineWidth || 1, strokeOptions);
1936
+ return line;
1937
+ }
1938
+
1939
+ /**
1940
+ * Creates a basic <path> node with given path string data. The created node will not
1941
+ * be bound to any root node.
1942
+ *
1943
+ * @private
1944
+ * @method makePathNode
1945
+ * @param {string} pathString - The path data (must be a valid path data string).
1946
+ * @param {string} color - The CSS color to draw the point with.
1947
+ * @param {number=1} lineWidth - (optional) The line width to use.
1948
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
1949
+ * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.
1950
+ * @return {SVGPathElement}
1951
+ * @instance
1952
+ * @memberof drawutilssvg
1953
+ */
1954
+ private makePathNode(
1955
+ pathString: string,
1956
+ color: string,
1957
+ lineWidth?: number,
1958
+ strokeOptions?: StrokeOptions,
1959
+ classNameOverride?: string
1960
+ ): SVGPathElement {
1961
+ const path: SVGPathElement = this.makeNode("path") as SVGPathElement;
1962
+ path.setAttribute("d", pathString);
1963
+ this._configureNode(path, classNameOverride ?? "path", this.fillShapes, color, lineWidth || 1, strokeOptions);
1964
+ return path;
1965
+ }
1966
+
1967
+ /**
1968
+ * Creates a basic arrow head node (<path> node) at the end of the given line coordinates. The created node will not
1969
+ * be bound to any root node.
1970
+ *
1971
+ * @private
1972
+ * @method makeArrowHeadNode
1973
+ * @param {string} pathString - The path data (must be a valid path data string).
1974
+ * @param {string} color - The CSS color to draw the point with.
1975
+ * @param {number=1} lineWidth - (optional) The line width to use.
1976
+ * @param {number=8} headLength - (optional) The length of the arrow head; if none is specified then the head will be 8 absolute units long.
1977
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
1978
+ * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.
1979
+ * @return {SVGPathElement}
1980
+ * @instance
1981
+ * @memberof drawutilssvg
1982
+ */
1983
+ private makeArrowHeadNode(
1984
+ zA: XYCoords,
1985
+ zB: XYCoords,
1986
+ color: string,
1987
+ lineWidth?: number,
1988
+ headLength: number = 8,
1989
+ strokeOptions?: StrokeOptions,
1990
+ arrowHeadBasePositionBuffer?: XYCoords
1991
+ ): SVGPathElement {
1992
+ var vertices: Array<Vertex> = Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);
1993
+ const d: Array<string | number> = ["M", this.offset.x + vertices[0].x, this.offset.y + vertices[0].y];
1994
+ if (arrowHeadBasePositionBuffer) {
1995
+ arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;
1996
+ arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;
1997
+ }
1998
+ for (var i = 1; i <= vertices.length; i++) {
1999
+ d.push("L");
2000
+ // Note: only use offset here (the vertices are already scaled)
2001
+ d.push(this.offset.x + vertices[i % vertices.length].x);
2002
+ d.push(this.offset.y + vertices[i % vertices.length].y);
2003
+ }
2004
+ const node: SVGPathElement = this.makePathNode(d.join(" "), color, lineWidth, strokeOptions, "arrowhead");
2005
+ return node;
2006
+ }
2007
+
2008
+ /**
2009
+ * Creates a basic cubic Bézier path node (<path> node) with the given cubic Bézier data. The created node will not
2010
+ * be bound to any root node.
2011
+ *
2012
+ * @private
2013
+ * @method makeCubicBezierNode
2014
+ * @param {XYCoords} startPoint - The start point of the cubic Bézier curve
2015
+ * @param {XYCoords} endPoint - The end point the cubic Bézier curve.
2016
+ * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
2017
+ * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
2018
+ * @param {string} color - The CSS color to draw the point with.
2019
+ * @param {number=1} lineWidth - (optional) The line width to use.
2020
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
2021
+ * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.
2022
+ * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.
2023
+ * @return {SVGPathElement}
2024
+ * @instance
2025
+ * @memberof drawutilssvg
2026
+ */
2027
+ private makeCubicBezierNode(
2028
+ startPoint: XYCoords,
2029
+ endPoint: XYCoords,
2030
+ startControlPoint: XYCoords,
2031
+ endControlPoint: XYCoords,
2032
+ color: string,
2033
+ lineWidth?: number,
2034
+ strokeOptions?: StrokeOptions
2035
+ ): SVGElement {
2036
+ if (startPoint instanceof CubicBezierCurve) {
2037
+ return this.cubicBezier(
2038
+ startPoint.startPoint,
2039
+ startPoint.endPoint,
2040
+ startPoint.startControlPoint,
2041
+ startPoint.endControlPoint,
2042
+ color,
2043
+ lineWidth
2044
+ );
2045
+ }
2046
+ // Draw curve
2047
+ const d: Array<string | number> = [
2048
+ "M",
2049
+ this._x(startPoint.x),
2050
+ this._y(startPoint.y),
2051
+ "C",
2052
+ this._x(startControlPoint.x),
2053
+ this._y(startControlPoint.y),
2054
+ this._x(endControlPoint.x),
2055
+ this._y(endControlPoint.y),
2056
+ this._x(endPoint.x),
2057
+ this._y(endPoint.y)
2058
+ ];
2059
+ const node: SVGElement = this.makePathNode(d.join(" "), color, lineWidth, strokeOptions, "cubicBezier");
2060
+ return node;
2061
+ }
1633
2062
  }