plotboilerplate 1.17.1 → 1.18.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.
package/README.md CHANGED
@@ -47,12 +47,18 @@ often use for the visualization of 2D geometries. Basic features are
47
47
  - text
48
48
  ([docs](https://plotboilerplate.io/docs_typedoc/classes/pbtext.html "PBText class"),
49
49
  [example](https://plotboilerplate.io/repo/demos/basic-PBText "PBText example"))
50
- - configuration of the canvas behavior (fullsize, interaction, raster)
51
- - mouse interaction (zoom, pan, drag elements)
52
- - keyboard interaction
53
- - touch interaction for dragging vertices (mobile devices: zoom, pan, drag elements)
54
-
55
- The compressed library has 128kb.
50
+ - configuration of the canvas behavior
51
+ - fullsize and auto-resizing
52
+ - enable/disable mouse, touch or keyboard interaction
53
+ - draw rasters
54
+ - default colors and darkmode
55
+ - mouse and touch interaction
56
+ - zoom
57
+ - pan
58
+ - drag and select elements
59
+ - keyboard interaction customizable
60
+
61
+ The compressed library has 133kb.
56
62
 
57
63
  ## Install the package via npm
58
64
 
@@ -143,6 +149,8 @@ globalThis.addEventListener("load", () => {
143
149
  });
144
150
  ```
145
151
 
152
+ For a guide of how to [Getting Started click here](https://github.com/IkarosKappler/plotboilerplate/blob/master/Getting-Started.md "Getting Started click here.").
153
+
146
154
  A full working demo repository about the [Usage with Typescript is here](https://github.com/IkarosKappler/plotboilerplate-typescript-example "usage with Typescript is here").
147
155
 
148
156
  ### Screenshot
@@ -442,6 +450,55 @@ vert.listeners.addDragListener(function (e) {
442
450
  - Touch & move (2 fingers): Pan the area
443
451
  - Touch & pinch: Zoom in/out
444
452
 
453
+ ## Custom keyboard events
454
+
455
+ ```javascript
456
+ new KeyHandler({ trackAll: true })
457
+ .down("enter", function () {
458
+ console.log("ENTER was hit.");
459
+ })
460
+ .press("enter", function () {
461
+ console.log("ENTER was pressed.");
462
+ })
463
+ .up("enter", function () {
464
+ console.log("ENTER was released.");
465
+ })
466
+ .down("e", function () {
467
+ console.log("e was hit. shift is pressed?", keyHandler.isDown("shift"));
468
+ })
469
+ .up("spacebar", function () {
470
+ console.log("spacebar was released.");
471
+ });
472
+ ```
473
+
474
+ For a list of all supported key codes see [Full list of supported key codes](https://github.com/IkarosKappler/plotboilerplate/blob/master/keycodes.md "Full list of supported key codes").
475
+
476
+ ## Custom mouse event
477
+
478
+ ```javascript
479
+ new MouseHandler(document.getElementById("mycanvas"))
480
+ .drag(function (e) {
481
+ console.log("Mouse dragged: " + JSON.stringify(e));
482
+ if (e.params.leftMouse);
483
+ else if (e.params.rightMouse);
484
+ })
485
+ .move(function (e) {
486
+ console.log("Mouse moved: " + JSON.stringify(e.params));
487
+ })
488
+ .up(function (e) {
489
+ console.log("Mouse up. Was dragged?", e.params.wasDragged);
490
+ })
491
+ .down(function (e) {
492
+ console.log("Mouse down.");
493
+ })
494
+ .click(function (e) {
495
+ console.log("Click.");
496
+ })
497
+ .wheel(function (e) {
498
+ console.log("Wheel. delta=" + e.deltaY);
499
+ });
500
+ ```
501
+
445
502
  ## Build the package
446
503
 
447
504
  [Compile and build howto](https://github.com/IkarosKappler/plotboilerplate/blob/master/build.md "Compile and build howto")
package/changelog.md CHANGED
@@ -1,8 +1,17 @@
1
1
  # Changelog
2
2
 
3
- <!-- - 2022-06-21 (Midsommer)
4
- - Added `Bounds.clone()`. -->
5
-
3
+ - 2022-09-11
4
+ - Added the extended circle-line-intersection demo (because I am stupid and need visual confirmation).
5
+ - 2022-08-23
6
+ - Added the `Circle.lineIntersection(Vertex,Vertex)` function.
7
+ - Added the `Circle.closestPoint(XYCoords)` function.
8
+ - Fixed a type issue in the `draw.polyline` function.
9
+ - Fixed a type issue in the `draw.setConfiguration` function.
10
+ - Fixed a type issue in the `draw.path` function.
11
+ - 2022-08-16
12
+ - MouseHandler: Fixed a bug in the mouse button detection.
13
+ - 2022-08-15
14
+ - Added the `Circle.containsPoint(XYCoords)` function.
6
15
  - 2022-08-01
7
16
  - Added `title` param to the `PBParams` interface.
8
17
  - 2022-07-26
package/dist/index.esm.js CHANGED
@@ -3945,7 +3945,10 @@ class Line extends VertTuple {
3945
3945
  * @modified 2021-01-20 Added UID.
3946
3946
  * @modified 2022-02-02 Added the `destroy` method.
3947
3947
  * @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.
3948
- * @version 1.3.0
3948
+ * @modified 2022-08-15 Added the `containsPoint` function.
3949
+ * @modified 2022-08-23 Added the `lineIntersection` function.
3950
+ * @modified 2022-08-23 Added the `closestPoint` function.
3951
+ * @version 1.4.0
3949
3952
  **/
3950
3953
  /**
3951
3954
  * @classdesc A simple circle: center point and radius.
@@ -3976,6 +3979,18 @@ class Circle {
3976
3979
  this.center = center;
3977
3980
  this.radius = radius;
3978
3981
  }
3982
+ /**
3983
+ * Check if the given circle is fully contained inside this circle.
3984
+ *
3985
+ * @method containsPoint
3986
+ * @param {XYCoords} point - The point to check if it is contained in this circle.
3987
+ * @instance
3988
+ * @memberof Circle
3989
+ * @return {boolean} `true` if the given point is inside this circle.
3990
+ */
3991
+ containsPoint(point) {
3992
+ return this.center.distance(point) < this.radius;
3993
+ }
3979
3994
  /**
3980
3995
  * Check if the given circle is fully contained inside this circle.
3981
3996
  *
@@ -4087,6 +4102,71 @@ class Circle {
4087
4102
  var y4 = p2.y + (h * (p1.x - p0.x)) / d;
4088
4103
  return new Line(new Vertex(x3, y3), new Vertex(x4, y4));
4089
4104
  }
4105
+ /**
4106
+ * Calculate the intersection points (if exists) with the given infinite line (defined by two points).
4107
+ *
4108
+ * @method lineIntersection
4109
+ * @instance
4110
+ * @memberof Circle
4111
+ * @param {Vertex} a- The first of the two points defining the line.
4112
+ * @param {Vertex} b - The second of the two points defining the line.
4113
+ * @return {Line|null} The intersection points (as a line) or null if this circle does not intersect the line given.
4114
+ **/
4115
+ lineIntersection(a, b) {
4116
+ // Based on the math from
4117
+ // https://mathworld.wolfram.com/Circle-LineIntersection.html
4118
+ const interA = new Vertex();
4119
+ const interB = new Vertex();
4120
+ // First do a transformation, because the calculation is based on a cicle at (0,0)
4121
+ const transA = new Vertex(a).sub(this.center);
4122
+ const transB = new Vertex(b).sub(this.center);
4123
+ const diff = transA.difference(transB);
4124
+ // There is a special case if diff.y=0, where the intersection is not calcuatable.
4125
+ // Use an non-zero epsilon here to approximate this case.
4126
+ // TODO for the future: find a better solution
4127
+ if (Math.abs(diff.y) === 0) {
4128
+ diff.y = 0.000001;
4129
+ }
4130
+ const dist = transA.distance(transB);
4131
+ const det = transA.x * transB.y - transA.y * transB.x;
4132
+ const distSquared = dist * dist;
4133
+ const radiusSquared = this.radius * this.radius;
4134
+ // Check if circle and line have an intersection at all
4135
+ if (radiusSquared * distSquared - det * det < 0) {
4136
+ return null;
4137
+ }
4138
+ const belowSqrt = this.radius * this.radius * dist * dist - det * det;
4139
+ const sqrt = Math.sqrt(belowSqrt);
4140
+ interA.x = (det * diff.y + Math.sign(diff.y) * diff.x * sqrt) / distSquared;
4141
+ interB.x = (det * diff.y - Math.sign(diff.y) * diff.x * sqrt) / distSquared;
4142
+ interA.y = (-det * diff.x + Math.abs(diff.y) * sqrt) / distSquared;
4143
+ interB.y = (-det * diff.x - Math.abs(diff.y) * sqrt) / distSquared;
4144
+ return new Line(interA.add(this.center), interB.add(this.center));
4145
+ // return new Line(interA, interB);
4146
+ }
4147
+ /**
4148
+ * Calculate the closest point on the outline of this circle to the given point.
4149
+ *
4150
+ * @method closestPoint
4151
+ * @instance
4152
+ * @memberof Circle
4153
+ * @param {XYCoords} vert - The point to find the closest circle point for.
4154
+ * @return {Vertex} The closest point on this circle.
4155
+ **/
4156
+ closestPoint(vert) {
4157
+ const lineIntersection = this.lineIntersection(this.center, vert);
4158
+ if (!lineIntersection) {
4159
+ // Note: this case should not happen as a radial from the center always intersect this circle.
4160
+ return new Vertex();
4161
+ }
4162
+ // Return closed of both
4163
+ if (lineIntersection.a.distance(vert) < lineIntersection.b.distance(vert)) {
4164
+ return lineIntersection.a;
4165
+ }
4166
+ else {
4167
+ return lineIntersection.b;
4168
+ }
4169
+ }
4090
4170
  /**
4091
4171
  * This function should invalidate any installed listeners and invalidate this object.
4092
4172
  * After calling this function the object might not hold valid data any more and
@@ -5608,7 +5688,10 @@ drawutilssvg.HEAD_XML = [
5608
5688
  * @modified 2022-03-27 Added the `texturedPoly` function.
5609
5689
  * @modified 2022-06-01 Tweaked the `polyline` function; lineWidth now scales with scale.x.
5610
5690
  * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.
5611
- * @version 1.12.2
5691
+ * @modified 2022-08-23 Fixed a type issue in the `polyline` function.
5692
+ * @modified 2022-08-23 Fixed a type issue in the `setConfiguration` function.
5693
+ * @modified 2022-08-23 Fixed a type issue in the `path` function.
5694
+ * @version 1.12.3
5612
5695
  **/
5613
5696
  // Todo: rename this class to Drawutils?
5614
5697
  /**
@@ -5662,7 +5745,7 @@ class drawutils {
5662
5745
  * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.
5663
5746
  */
5664
5747
  setConfiguration(configuration) {
5665
- this.ctx.globalCompositeOperation = configuration.blendMode;
5748
+ this.ctx.globalCompositeOperation = configuration.blendMode || "source-over";
5666
5749
  }
5667
5750
  /**
5668
5751
  * This method shouled be called each time the currently drawn `Drawable` changes.
@@ -6371,7 +6454,7 @@ class drawutils {
6371
6454
  }
6372
6455
  this.ctx.save();
6373
6456
  this.ctx.beginPath();
6374
- this.ctx.lineWidth = lineWidth * this.scale.x || 1.0;
6457
+ this.ctx.lineWidth = (lineWidth || 1.0) * this.scale.x;
6375
6458
  this.ctx.moveTo(this.offset.x + vertices[0].x * this.scale.x, this.offset.y + vertices[0].y * this.scale.y);
6376
6459
  for (var i = 0; i < vertices.length; i++) {
6377
6460
  this.ctx.lineTo(this.offset.x + vertices[i].x * this.scale.x, this.offset.y + vertices[i].y * this.scale.y);
@@ -6488,14 +6571,20 @@ class drawutils {
6488
6571
  path(pathData, color, lineWidth, options) {
6489
6572
  const d = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);
6490
6573
  drawutilssvg.transformPathData(d, this.offset, this.scale);
6491
- this.ctx.strokeStyle = color;
6574
+ if (color) {
6575
+ this.ctx.strokeStyle = color;
6576
+ }
6492
6577
  this.ctx.lineWidth = lineWidth || 1;
6493
6578
  if (this.fillShapes) {
6494
- this.ctx.fillStyle = color;
6579
+ if (color) {
6580
+ this.ctx.fillStyle = color;
6581
+ }
6495
6582
  this.ctx.fill(new Path2D(d.join(" ")));
6496
6583
  }
6497
6584
  else {
6498
- this.ctx.strokeStyle = color;
6585
+ if (color) {
6586
+ this.ctx.strokeStyle = color;
6587
+ }
6499
6588
  this.ctx.stroke(new Path2D(d.join(" ")));
6500
6589
  }
6501
6590
  }
@@ -8280,7 +8369,8 @@ KeyHandler.KEY_CODES = {
8280
8369
  * @modified 2020-10-04 Added extended JSDoc comments.
8281
8370
  * @modified 2020-11-25 Added the `isTouchEvent` param.
8282
8371
  * @modified 2021-01-10 The mouse handler is now also working with SVGElements.
8283
- * @version 1.2.0
8372
+ * @modified 2022-08-16 Fixed a bug in the mouse button detection.
8373
+ * @version 1.2.1
8284
8374
  *
8285
8375
  * @file MouseHandler
8286
8376
  * @public
@@ -8370,8 +8460,8 @@ class MouseHandler {
8370
8460
  // +-------------------------------------------------
8371
8461
  this.name = name;
8372
8462
  this.element = element;
8373
- this.mouseDownPos = null;
8374
- this.mouseDragPos = null;
8463
+ this.mouseDownPos = undefined;
8464
+ this.mouseDragPos = undefined;
8375
8465
  // this.mousePos = null;
8376
8466
  this.mouseButton = -1;
8377
8467
  this.listeners = {};
@@ -8440,26 +8530,27 @@ class MouseHandler {
8440
8530
  * @memberof MouseHandler
8441
8531
  * @instance
8442
8532
  * @private
8443
- * @param {MouseEvent} e - The mouse event to get the relative position for.
8533
+ * @param {MouseEvent} event - The mouse event to get the relative position for.
8444
8534
  * @param {string} eventName - The name of the firing event.
8445
8535
  * @return {XMouseEvent}
8446
8536
  */
8447
- mkParams(e, eventName) {
8448
- const rel = this.relPos(e);
8449
- const xEvent = e;
8537
+ mkParams(event, eventName) {
8538
+ var _a, _b;
8539
+ const rel = this.relPos(event);
8540
+ const xEvent = event;
8450
8541
  xEvent.params = {
8451
8542
  element: this.element,
8452
8543
  name: eventName,
8453
8544
  isTouchEvent: false,
8454
8545
  pos: rel,
8455
- button: this.mouseButton,
8456
- leftButton: this.mouseButton == 0,
8457
- middleButton: this.mouseButton == 1,
8458
- rightButton: this.mouseButton == 2,
8459
- mouseDownPos: this.mouseDownPos,
8460
- draggedFrom: this.mouseDragPos,
8546
+ button: event.button,
8547
+ leftButton: event.button === 0,
8548
+ middleButton: event.button === 1,
8549
+ rightButton: event.button === 2,
8550
+ mouseDownPos: (_a = this.mouseDownPos) !== null && _a !== void 0 ? _a : { x: NaN, y: NaN },
8551
+ draggedFrom: (_b = this.mouseDragPos) !== null && _b !== void 0 ? _b : { x: NaN, y: NaN },
8461
8552
  wasDragged: this.mouseDownPos != null && (this.mouseDownPos.x != rel.x || this.mouseDownPos.y != rel.y),
8462
- dragAmount: this.mouseDownPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }
8553
+ dragAmount: this.mouseDragPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }
8463
8554
  };
8464
8555
  return xEvent;
8465
8556
  }