microboard-temp 0.4.40 → 0.4.42

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/cjs/node.js CHANGED
@@ -22182,433 +22182,6 @@ class NoOpCommand {
22182
22182
  }
22183
22183
  }
22184
22184
 
22185
- // src/isSafari.ts
22186
- function isSafari() {
22187
- if (typeof navigator === "undefined") {
22188
- return false;
22189
- }
22190
- const agent = navigator.userAgent;
22191
- const vendor = navigator.vendor;
22192
- const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
22193
- return is;
22194
- }
22195
-
22196
- // src/Items/Drawing/Drawing.ts
22197
- class Drawing extends BaseItem {
22198
- points;
22199
- events;
22200
- itemType = "Drawing";
22201
- parent = "Board";
22202
- transformation;
22203
- path2d = new conf.path2DFactory;
22204
- subject = new Subject;
22205
- untransformedMbr = new Mbr;
22206
- lines = [];
22207
- linkTo;
22208
- strokeWidth = 1;
22209
- borderStyle = "solid";
22210
- linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22211
- borderOpacity = 1;
22212
- transformationRenderBlock = undefined;
22213
- constructor(board, points, events, id = "") {
22214
- super(board, id);
22215
- this.points = points;
22216
- this.events = events;
22217
- this.transformation = new Transformation(id, events);
22218
- this.linkTo = new LinkTo(this.id, this.events);
22219
- this.transformation.subject.subscribe(() => {
22220
- this.updateMbr();
22221
- this.updateLines();
22222
- this.subject.publish(this);
22223
- });
22224
- this.linkTo.subject.subscribe(() => {
22225
- this.updateMbr();
22226
- this.updateLines();
22227
- this.subject.publish(this);
22228
- });
22229
- this.updateLines();
22230
- }
22231
- serialize() {
22232
- this.optimizePoints();
22233
- const points = [];
22234
- for (const point3 of this.points) {
22235
- points.push({ x: point3.x, y: point3.y });
22236
- }
22237
- return {
22238
- itemType: "Drawing",
22239
- points,
22240
- transformation: this.transformation.serialize(),
22241
- strokeStyle: this.borderColor,
22242
- strokeWidth: this.strokeWidth,
22243
- linkTo: this.linkTo.serialize()
22244
- };
22245
- }
22246
- deserialize(data) {
22247
- this.points = [];
22248
- for (const point3 of data.points) {
22249
- this.points.push(new Point(point3.x, point3.y));
22250
- }
22251
- this.linkTo.deserialize(data.linkTo);
22252
- this.optimizePoints();
22253
- this.transformation.deserialize(data.transformation);
22254
- this.borderColor = data.strokeStyle;
22255
- this.strokeWidth = data.strokeWidth;
22256
- this.updateGeometry();
22257
- return this;
22258
- }
22259
- updateGeometry() {
22260
- this.updatePath2d();
22261
- this.updateLines();
22262
- this.updateMbr();
22263
- }
22264
- updateMbr() {
22265
- const offset = this.getStrokeWidth() / 2;
22266
- const untransformedMbr = this.untransformedMbr.copy();
22267
- untransformedMbr.left -= offset;
22268
- untransformedMbr.top -= offset;
22269
- untransformedMbr.right += offset;
22270
- untransformedMbr.bottom += offset;
22271
- const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
22272
- this.left = mbr.left;
22273
- this.top = mbr.top;
22274
- this.right = mbr.right;
22275
- this.bottom = mbr.bottom;
22276
- }
22277
- updatePath2d() {
22278
- this.path2d = new conf.path2DFactory;
22279
- const context = this.path2d;
22280
- const points = this.points;
22281
- if (points.length < 3) {
22282
- context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
22283
- context.closePath();
22284
- } else {
22285
- context.moveTo(points[0].x, points[0].y);
22286
- let j = 1;
22287
- for (;j < points.length - 2; j++) {
22288
- const cx = (points[j].x + points[j + 1].x) / 2;
22289
- const cy = (points[j].y + points[j + 1].y) / 2;
22290
- context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
22291
- }
22292
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
22293
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
22294
- context.quadraticCurveTo(points[j].x, points[j].y, x, y);
22295
- }
22296
- let left = Number.MAX_SAFE_INTEGER;
22297
- let right = Number.MIN_SAFE_INTEGER;
22298
- let top = Number.MAX_SAFE_INTEGER;
22299
- let bottom = Number.MIN_SAFE_INTEGER;
22300
- for (const { x, y } of this.points) {
22301
- if (x < left) {
22302
- left = x;
22303
- }
22304
- if (x > right) {
22305
- right = x;
22306
- }
22307
- if (y < top) {
22308
- top = y;
22309
- }
22310
- if (y > bottom) {
22311
- bottom = y;
22312
- }
22313
- }
22314
- this.untransformedMbr = new Mbr(left, top, right, bottom);
22315
- }
22316
- updateLines() {
22317
- this.lines = [];
22318
- const matrix = this.transformation.matrix;
22319
- if (this.points.length < 2) {
22320
- return;
22321
- }
22322
- for (let i = 0;i < this.points.length - 2; i++) {
22323
- const p1 = this.points[i];
22324
- const p2 = this.points[i + 1];
22325
- const line = new Line(p1.copy(), p2.copy());
22326
- line.transform(matrix);
22327
- this.lines.push(line);
22328
- }
22329
- }
22330
- optimizePoints() {
22331
- const dp = douglasPeucker(this.points, 1);
22332
- dp.push(this.points[this.points.length - 1]);
22333
- this.points = dp;
22334
- }
22335
- addPoint(point3) {
22336
- const previous2 = this.points[this.points.length - 1];
22337
- if (previous2) {
22338
- const distance = point3.getDistance(previous2);
22339
- if (distance >= 2) {
22340
- this.points.push(point3);
22341
- }
22342
- } else {
22343
- this.points.push(point3);
22344
- }
22345
- this.updateGeometry();
22346
- }
22347
- setId(id) {
22348
- this.id = id;
22349
- this.transformation.setId(id);
22350
- this.linkTo.setId(id);
22351
- return this;
22352
- }
22353
- getId() {
22354
- return this.id;
22355
- }
22356
- render(context) {
22357
- if (this.transformationRenderBlock) {
22358
- return;
22359
- }
22360
- const ctx = context.ctx;
22361
- ctx.save();
22362
- ctx.strokeStyle = this.borderColor;
22363
- ctx.lineWidth = this.strokeWidth;
22364
- ctx.lineCap = "round";
22365
- ctx.setLineDash(this.linePattern);
22366
- this.transformation.matrix.applyToContext(ctx);
22367
- ctx.stroke(this.path2d.nativePath);
22368
- ctx.restore();
22369
- if (this.getLinkTo()) {
22370
- const { top, right } = this.getMbr();
22371
- this.linkTo.render(context, top, right, this.board.camera.getScale());
22372
- }
22373
- }
22374
- renderHTML(documentFactory) {
22375
- const div = documentFactory.createElement("drawing-item");
22376
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
22377
- const mbr = this.getMbr();
22378
- const width = mbr.getWidth();
22379
- const height = mbr.getHeight();
22380
- const unscaledWidth = width / scaleX;
22381
- const unscaledHeight = height / scaleY;
22382
- const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
22383
- svg.setAttribute("width", `${unscaledWidth}px`);
22384
- svg.setAttribute("height", `${unscaledHeight}px`);
22385
- svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
22386
- svg.setAttribute("style", "position: absolute; overflow: visible;");
22387
- const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
22388
- pathElement.setAttribute("d", this.getPathData());
22389
- pathElement.setAttribute("stroke", this.borderColor);
22390
- pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
22391
- pathElement.setAttribute("fill", "none");
22392
- svg.appendChild(pathElement);
22393
- div.appendChild(svg);
22394
- div.id = this.getId();
22395
- div.style.width = unscaledWidth + "px";
22396
- div.style.height = unscaledHeight + "px";
22397
- div.style.transformOrigin = "left top";
22398
- div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
22399
- div.style.position = "absolute";
22400
- div.setAttribute("data-link-to", this.linkTo.serialize() || "");
22401
- if (this.getLinkTo()) {
22402
- const linkElement = this.linkTo.renderHTML(documentFactory);
22403
- scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
22404
- translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
22405
- div.appendChild(linkElement);
22406
- }
22407
- return div;
22408
- }
22409
- getPathData() {
22410
- const points = this.points;
22411
- if (points.length < 2) {
22412
- return "";
22413
- }
22414
- let pathData = `M ${points[0].x} ${points[0].y}`;
22415
- if (points.length < 3) {
22416
- pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
22417
- } else {
22418
- let j = 1;
22419
- for (;j < points.length - 2; j++) {
22420
- const cx = (points[j].x + points[j + 1].x) / 2;
22421
- const cy = (points[j].y + points[j + 1].y) / 2;
22422
- pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
22423
- }
22424
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
22425
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
22426
- pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
22427
- }
22428
- return pathData;
22429
- }
22430
- getPath() {
22431
- const { left, top, right, bottom } = this.getMbr();
22432
- const leftTop = new Point(left, top);
22433
- const rightTop = new Point(right, top);
22434
- const rightBottom = new Point(right, bottom);
22435
- const leftBottom = new Point(left, bottom);
22436
- return new Path([
22437
- new Line(leftTop, rightTop),
22438
- new Line(rightTop, rightBottom),
22439
- new Line(rightBottom, leftBottom),
22440
- new Line(leftBottom, leftTop)
22441
- ], true);
22442
- }
22443
- getSnapAnchorPoints() {
22444
- const mbr = this.getMbr();
22445
- const width = mbr.getWidth();
22446
- const height = mbr.getHeight();
22447
- return [
22448
- new Point(mbr.left + width / 2, mbr.top),
22449
- new Point(mbr.left + width / 2, mbr.bottom),
22450
- new Point(mbr.left, mbr.top + height / 2),
22451
- new Point(mbr.right, mbr.top + height / 2)
22452
- ];
22453
- }
22454
- getLines() {
22455
- return this.lines;
22456
- }
22457
- isClosed() {
22458
- return true;
22459
- }
22460
- isEnclosedOrCrossedBy(rect) {
22461
- for (const line of this.lines) {
22462
- if (line.isEnclosedOrCrossedBy(rect)) {
22463
- return true;
22464
- }
22465
- }
22466
- return false;
22467
- }
22468
- emit(operation) {
22469
- if (this.events) {
22470
- const command = new DrawingCommand([this], operation);
22471
- command.apply();
22472
- this.events.emit(operation, command);
22473
- } else {
22474
- this.apply(operation);
22475
- }
22476
- }
22477
- apply(op) {
22478
- switch (op.class) {
22479
- case "Drawing":
22480
- switch (op.method) {
22481
- case "setStrokeColor":
22482
- this.borderColor = op.color;
22483
- break;
22484
- case "setStrokeWidth":
22485
- this.strokeWidth = op.width;
22486
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22487
- break;
22488
- case "setStrokeOpacity":
22489
- this.borderOpacity = op.opacity;
22490
- break;
22491
- case "setStrokeStyle":
22492
- this.borderStyle = op.style;
22493
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22494
- break;
22495
- }
22496
- this.updateMbr();
22497
- break;
22498
- case "Transformation":
22499
- this.transformation.apply(op);
22500
- break;
22501
- case "LinkTo":
22502
- this.linkTo.apply(op);
22503
- break;
22504
- default:
22505
- return;
22506
- }
22507
- this.subject.publish(this);
22508
- }
22509
- setStrokeOpacity(opacity) {
22510
- this.emit({
22511
- class: "Drawing",
22512
- method: "setStrokeOpacity",
22513
- item: [this.id],
22514
- opacity
22515
- });
22516
- return this;
22517
- }
22518
- getStrokeOpacity() {
22519
- return this.borderOpacity;
22520
- }
22521
- setBorderStyle(style) {
22522
- this.emit({
22523
- class: "Drawing",
22524
- method: "setStrokeStyle",
22525
- item: [this.id],
22526
- style
22527
- });
22528
- return this;
22529
- }
22530
- getBorderStyle() {
22531
- return this.borderStyle;
22532
- }
22533
- setStrokeColor(color) {
22534
- this.emit({
22535
- class: "Drawing",
22536
- method: "setStrokeColor",
22537
- item: [this.id],
22538
- color
22539
- });
22540
- return this;
22541
- }
22542
- getStrokeColor() {
22543
- return this.borderColor;
22544
- }
22545
- setStrokeWidth(width) {
22546
- this.emit({
22547
- class: "Drawing",
22548
- method: "setStrokeWidth",
22549
- item: [this.id],
22550
- width,
22551
- prevWidth: this.strokeWidth
22552
- });
22553
- return this;
22554
- }
22555
- getLinkTo() {
22556
- return this.linkTo.link;
22557
- }
22558
- getStrokeWidth() {
22559
- return this.strokeWidth;
22560
- }
22561
- getRichText() {
22562
- return null;
22563
- }
22564
- isPointNearLine(point3, threshold = 10) {
22565
- const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
22566
- const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
22567
- const transformedMouse = new Point(transformedMouseX, transformedMouseY);
22568
- for (let i = 0;i < this.points.length - 1; i++) {
22569
- const p1 = this.points[i];
22570
- const p2 = this.points[i + 1];
22571
- const distance = getPerpendicularDistance(transformedMouse, p1, p2);
22572
- if (distance < threshold) {
22573
- return true;
22574
- }
22575
- }
22576
- return false;
22577
- }
22578
- }
22579
- function getPerpendicularDistance(point3, lineStart, lineEnd) {
22580
- const { x: px, y: py } = point3;
22581
- const { x: sx, y: sy } = lineStart;
22582
- const { x: ex, y: ey } = lineEnd;
22583
- const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
22584
- const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
22585
- return numerator / denominator;
22586
- }
22587
- function douglasPeucker(points, epsilon2) {
22588
- if (points.length < 3) {
22589
- return points;
22590
- }
22591
- const start = points[0];
22592
- const end = points[points.length - 1];
22593
- let maxDistance = 0;
22594
- let maxIndex = 0;
22595
- for (let i = 1;i < points.length - 1; i++) {
22596
- const distance = getPerpendicularDistance(points[i], start, end);
22597
- if (distance > maxDistance) {
22598
- maxDistance = distance;
22599
- maxIndex = i;
22600
- }
22601
- }
22602
- if (maxDistance > epsilon2) {
22603
- const leftSubPoints = points.slice(0, maxIndex + 1);
22604
- const rightSubPoints = points.slice(maxIndex);
22605
- const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
22606
- const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
22607
- return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
22608
- } else {
22609
- return [start, end];
22610
- }
22611
- }
22612
22185
  // src/SpatialIndex/LayeredIndex/Layers.ts
22613
22186
  class Layers {
22614
22187
  getNewLayer;
@@ -23931,12 +23504,12 @@ class Items {
23931
23504
  if (enclosed.length === 0) {
23932
23505
  enclosed = underPointer;
23933
23506
  }
23934
- if (underPointer.some((item) => item instanceof Drawing)) {
23507
+ if (underPointer.some((item) => item.itemType === "Drawing")) {
23935
23508
  enclosed = [...underPointer, ...enclosed];
23936
23509
  }
23937
23510
  const { nearest } = enclosed.reduce((acc, item) => {
23938
23511
  const area = item.getMbr().getHeight() * item.getMbr().getWidth();
23939
- if (item instanceof Drawing && !item.isPointNearLine(this.pointer.point)) {
23512
+ if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
23940
23513
  return acc;
23941
23514
  }
23942
23515
  const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
@@ -24071,6 +23644,7 @@ class Items {
24071
23644
  }
24072
23645
  }
24073
23646
 
23647
+ // src/SpatialIndex/SimpleSpatialIndex.ts
24074
23648
  class SimpleSpatialIndex {
24075
23649
  subject = new Subject;
24076
23650
  itemsArray = [];
@@ -44821,202 +44395,455 @@ class Placeholder extends BaseItem {
44821
44395
  renderHTML(documentFactory) {
44822
44396
  return documentFactory.createElement("div");
44823
44397
  }
44824
- getLinkTo() {
44825
- return;
44398
+ getLinkTo() {
44399
+ return;
44400
+ }
44401
+ getRichText() {
44402
+ return null;
44403
+ }
44404
+ }
44405
+ // src/Items/Image/Image.ts
44406
+ function getPlaceholderImage(board, imageDimension) {
44407
+ const placeholderCanvas = conf.documentFactory.createElement("canvas");
44408
+ const placeholderContext = placeholderCanvas.getContext("2d");
44409
+ const context = new DrawingContext(board.camera, placeholderContext);
44410
+ const placeholder = new Placeholder(board);
44411
+ if (imageDimension) {
44412
+ placeholderCanvas.width = imageDimension.width;
44413
+ placeholderCanvas.height = imageDimension.height;
44414
+ placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
44415
+ } else {
44416
+ placeholderCanvas.width = 250;
44417
+ placeholderCanvas.height = 50;
44418
+ placeholder.transformation.scaleTo(250 / 100, 50 / 100);
44419
+ }
44420
+ const placeholderImage = new Image;
44421
+ placeholderImage.src = placeholderCanvas.toDataURL();
44422
+ return placeholderImage;
44423
+ }
44424
+
44425
+ class ImageItem extends BaseItem {
44426
+ events;
44427
+ itemType = "Image";
44428
+ parent = "Board";
44429
+ image;
44430
+ transformation;
44431
+ linkTo;
44432
+ subject = new Subject;
44433
+ loadCallbacks = [];
44434
+ beforeLoadCallbacks = [];
44435
+ transformationRenderBlock = undefined;
44436
+ storageLink;
44437
+ imageDimension;
44438
+ board;
44439
+ constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
44440
+ super(board, id);
44441
+ this.events = events;
44442
+ this.linkTo = new LinkTo(this.id, events);
44443
+ this.board = board;
44444
+ this.setStorageLink(storageLink);
44445
+ this.imageDimension = imageDimension;
44446
+ this.transformation = new Transformation(id, events);
44447
+ this.image = new Image;
44448
+ this.image.crossOrigin = "anonymous";
44449
+ this.image.onload = this.onLoad;
44450
+ this.image.onerror = this.onError;
44451
+ if (typeof base64 === "string") {
44452
+ this.image.src = base64;
44453
+ }
44454
+ this.linkTo.subject.subscribe(() => {
44455
+ this.updateMbr();
44456
+ this.subject.publish(this);
44457
+ });
44458
+ this.transformation.subject.subscribe(this.onTransform);
44459
+ }
44460
+ setStorageLink(link2) {
44461
+ try {
44462
+ const url = new URL(link2);
44463
+ this.storageLink = `${window?.location.origin}${url.pathname}`;
44464
+ } catch (_) {}
44465
+ }
44466
+ getStorageId() {
44467
+ return this.storageLink.split("/").pop();
44468
+ }
44469
+ handleError = () => {
44470
+ console.error("Invalid dataUrl or image failed to load.");
44471
+ this.image = getPlaceholderImage(this.board);
44472
+ this.updateMbr();
44473
+ this.subject.publish(this);
44474
+ this.shootLoadCallbacks();
44475
+ };
44476
+ onLoad = async () => {
44477
+ this.shootBeforeLoadCallbacks();
44478
+ this.updateMbr();
44479
+ this.subject.publish(this);
44480
+ this.shootLoadCallbacks();
44481
+ };
44482
+ onError = (_error) => {
44483
+ this.image = getPlaceholderImage(this.board);
44484
+ this.updateMbr();
44485
+ this.subject.publish(this);
44486
+ this.shootLoadCallbacks();
44487
+ };
44488
+ onTransform = () => {
44489
+ this.updateMbr();
44490
+ this.subject.publish(this);
44491
+ };
44492
+ updateMbr() {
44493
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44494
+ this.left = translateX;
44495
+ this.top = translateY;
44496
+ this.right = this.left + this.image.width * scaleX;
44497
+ this.bottom = this.top + this.image.height * scaleY;
44498
+ }
44499
+ doOnceBeforeOnLoad = (callback) => {
44500
+ this.loadCallbacks.push(callback);
44501
+ };
44502
+ doOnceOnLoad = (callback) => {
44503
+ this.loadCallbacks.push(callback);
44504
+ };
44505
+ setId(id) {
44506
+ this.id = id;
44507
+ this.transformation.setId(id);
44508
+ this.linkTo.setId(id);
44509
+ return this;
44510
+ }
44511
+ getId() {
44512
+ return this.id;
44513
+ }
44514
+ serialize() {
44515
+ return {
44516
+ itemType: "Image",
44517
+ storageLink: this.storageLink,
44518
+ imageDimension: this.imageDimension,
44519
+ transformation: this.transformation.serialize(),
44520
+ linkTo: this.linkTo.serialize()
44521
+ };
44522
+ }
44523
+ setCoordinates() {
44524
+ this.left = this.transformation.matrix.translateX;
44525
+ this.top = this.transformation.matrix.translateY;
44526
+ this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
44527
+ this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
44528
+ this.subject.publish(this);
44529
+ }
44530
+ shootBeforeLoadCallbacks() {
44531
+ while (this.beforeLoadCallbacks.length > 0) {
44532
+ this.beforeLoadCallbacks.shift()(this);
44533
+ }
44534
+ }
44535
+ shootLoadCallbacks() {
44536
+ while (this.loadCallbacks.length > 0) {
44537
+ this.loadCallbacks.shift()(this);
44538
+ }
44539
+ }
44540
+ deserialize(data) {
44541
+ if (data.transformation) {
44542
+ this.transformation.deserialize(data.transformation);
44543
+ }
44544
+ this.linkTo.deserialize(data.linkTo);
44545
+ this.image.onload = () => {
44546
+ this.setCoordinates();
44547
+ this.shootLoadCallbacks();
44548
+ };
44549
+ if (data.storageLink) {
44550
+ this.setStorageLink(data.storageLink);
44551
+ }
44552
+ if (this.image.src) {
44553
+ return this;
44554
+ }
44555
+ this.image = getPlaceholderImage(this.board, data.imageDimension);
44556
+ const storageImage = new Image;
44557
+ storageImage.onload = () => {
44558
+ this.image = storageImage;
44559
+ this.onLoad();
44560
+ };
44561
+ storageImage.onerror = this.onError;
44562
+ storageImage.src = this.storageLink;
44563
+ return this;
44564
+ }
44565
+ emit(operation) {
44566
+ if (this.events) {
44567
+ const command = new ImageCommand([this], operation);
44568
+ command.apply();
44569
+ this.events.emit(operation, command);
44570
+ } else {
44571
+ this.apply(operation);
44572
+ }
44573
+ }
44574
+ setDimensions(dim) {
44575
+ this.imageDimension = dim;
44576
+ }
44577
+ apply(op) {
44578
+ switch (op.class) {
44579
+ case "Transformation":
44580
+ this.transformation.apply(op);
44581
+ break;
44582
+ case "LinkTo":
44583
+ this.linkTo.apply(op);
44584
+ break;
44585
+ case "Image":
44586
+ if (op.data.base64) {
44587
+ this.image.src = op.data.base64;
44588
+ }
44589
+ this.setStorageLink(op.data.storageLink);
44590
+ this.setDimensions(op.data.imageDimension);
44591
+ this.subject.publish(this);
44592
+ break;
44593
+ }
44594
+ }
44595
+ render(context) {
44596
+ if (this.transformationRenderBlock) {
44597
+ return;
44598
+ }
44599
+ const ctx = context.ctx;
44600
+ ctx.save();
44601
+ this.transformation.matrix.applyToContext(ctx);
44602
+ ctx.drawImage(this.image, 0, 0);
44603
+ ctx.restore();
44604
+ if (this.getLinkTo()) {
44605
+ const { top, right } = this.getMbr();
44606
+ this.linkTo.render(context, top, right, this.board.camera.getScale());
44607
+ }
44608
+ }
44609
+ renderHTML(documentFactory) {
44610
+ const div = documentFactory.createElement("image-item");
44611
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44612
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
44613
+ div.style.backgroundImage = `url(${this.storageLink})`;
44614
+ div.id = this.getId();
44615
+ div.style.width = `${this.imageDimension.width}px`;
44616
+ div.style.height = `${this.imageDimension.height}px`;
44617
+ div.style.transformOrigin = "top left";
44618
+ div.style.transform = transform;
44619
+ div.style.position = "absolute";
44620
+ div.style.backgroundSize = "cover";
44621
+ div.setAttribute("data-link-to", this.linkTo.serialize() || "");
44622
+ if (this.getLinkTo()) {
44623
+ const linkElement = this.linkTo.renderHTML(documentFactory);
44624
+ scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
44625
+ translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
44626
+ div.appendChild(linkElement);
44627
+ }
44628
+ return div;
44629
+ }
44630
+ getPath() {
44631
+ const { left, top, right, bottom } = this.getMbr();
44632
+ const leftTop = new Point(left, top);
44633
+ const rightTop = new Point(right, top);
44634
+ const rightBottom = new Point(right, bottom);
44635
+ const leftBottom = new Point(left, bottom);
44636
+ return new Path([
44637
+ new Line(leftTop, rightTop),
44638
+ new Line(rightTop, rightBottom),
44639
+ new Line(rightBottom, leftBottom),
44640
+ new Line(leftBottom, leftTop)
44641
+ ], true);
44642
+ }
44643
+ getSnapAnchorPoints() {
44644
+ const mbr = this.getMbr();
44645
+ const width2 = mbr.getWidth();
44646
+ const height2 = mbr.getHeight();
44647
+ return [
44648
+ new Point(mbr.left + width2 / 2, mbr.top),
44649
+ new Point(mbr.left + width2 / 2, mbr.bottom),
44650
+ new Point(mbr.left, mbr.top + height2 / 2),
44651
+ new Point(mbr.right, mbr.top + height2 / 2)
44652
+ ];
44653
+ }
44654
+ isClosed() {
44655
+ return true;
44826
44656
  }
44827
44657
  getRichText() {
44828
44658
  return null;
44829
44659
  }
44660
+ getLinkTo() {
44661
+ return this.linkTo.link;
44662
+ }
44663
+ download() {
44664
+ const linkElem = document.createElement("a");
44665
+ linkElem.href = this.storageLink;
44666
+ linkElem.setAttribute("download", "");
44667
+ linkElem.click();
44668
+ }
44669
+ onRemove() {
44670
+ const storageId = this.getStorageId();
44671
+ if (storageId) {
44672
+ conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
44673
+ }
44674
+ super.onRemove();
44675
+ }
44830
44676
  }
44831
- // src/Items/Image/Image.ts
44832
- function getPlaceholderImage(board, imageDimension) {
44833
- const placeholderCanvas = conf.documentFactory.createElement("canvas");
44834
- const placeholderContext = placeholderCanvas.getContext("2d");
44835
- const context = new DrawingContext(board.camera, placeholderContext);
44836
- const placeholder = new Placeholder(board);
44837
- if (imageDimension) {
44838
- placeholderCanvas.width = imageDimension.width;
44839
- placeholderCanvas.height = imageDimension.height;
44840
- placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
44841
- } else {
44842
- placeholderCanvas.width = 250;
44843
- placeholderCanvas.height = 50;
44844
- placeholder.transformation.scaleTo(250 / 100, 50 / 100);
44677
+ // src/isSafari.ts
44678
+ function isSafari() {
44679
+ if (typeof navigator === "undefined") {
44680
+ return false;
44845
44681
  }
44846
- const placeholderImage = new Image;
44847
- placeholderImage.src = placeholderCanvas.toDataURL();
44848
- return placeholderImage;
44682
+ const agent = navigator.userAgent;
44683
+ const vendor = navigator.vendor;
44684
+ const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
44685
+ return is2;
44849
44686
  }
44850
44687
 
44851
- class ImageItem extends BaseItem {
44688
+ // src/Items/Drawing/Drawing.ts
44689
+ class Drawing extends BaseItem {
44690
+ points;
44852
44691
  events;
44853
- itemType = "Image";
44692
+ itemType = "Drawing";
44854
44693
  parent = "Board";
44855
- image;
44856
44694
  transformation;
44857
- linkTo;
44695
+ path2d = new conf.path2DFactory;
44858
44696
  subject = new Subject;
44859
- loadCallbacks = [];
44860
- beforeLoadCallbacks = [];
44697
+ untransformedMbr = new Mbr;
44698
+ lines = [];
44699
+ linkTo;
44700
+ strokeWidth = 1;
44701
+ borderStyle = "solid";
44702
+ linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44703
+ borderOpacity = 1;
44861
44704
  transformationRenderBlock = undefined;
44862
- storageLink;
44863
- imageDimension;
44864
- board;
44865
- constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
44705
+ constructor(board, points, events, id = "") {
44866
44706
  super(board, id);
44707
+ this.points = points;
44867
44708
  this.events = events;
44868
- this.linkTo = new LinkTo(this.id, events);
44869
- this.board = board;
44870
- this.setStorageLink(storageLink);
44871
- this.imageDimension = imageDimension;
44872
44709
  this.transformation = new Transformation(id, events);
44873
- this.image = new Image;
44874
- this.image.crossOrigin = "anonymous";
44875
- this.image.onload = this.onLoad;
44876
- this.image.onerror = this.onError;
44877
- if (typeof base64 === "string") {
44878
- this.image.src = base64;
44879
- }
44710
+ this.linkTo = new LinkTo(this.id, this.events);
44711
+ this.transformation.subject.subscribe(() => {
44712
+ this.updateMbr();
44713
+ this.updateLines();
44714
+ this.subject.publish(this);
44715
+ });
44880
44716
  this.linkTo.subject.subscribe(() => {
44881
44717
  this.updateMbr();
44718
+ this.updateLines();
44882
44719
  this.subject.publish(this);
44883
44720
  });
44884
- this.transformation.subject.subscribe(this.onTransform);
44885
- }
44886
- setStorageLink(link2) {
44887
- try {
44888
- const url = new URL(link2);
44889
- this.storageLink = `${window?.location.origin}${url.pathname}`;
44890
- } catch (_) {}
44891
- }
44892
- getStorageId() {
44893
- return this.storageLink.split("/").pop();
44894
- }
44895
- handleError = () => {
44896
- console.error("Invalid dataUrl or image failed to load.");
44897
- this.image = getPlaceholderImage(this.board);
44898
- this.updateMbr();
44899
- this.subject.publish(this);
44900
- this.shootLoadCallbacks();
44901
- };
44902
- onLoad = async () => {
44903
- this.shootBeforeLoadCallbacks();
44904
- this.updateMbr();
44905
- this.subject.publish(this);
44906
- this.shootLoadCallbacks();
44907
- };
44908
- onError = (_error) => {
44909
- this.image = getPlaceholderImage(this.board);
44910
- this.updateMbr();
44911
- this.subject.publish(this);
44912
- this.shootLoadCallbacks();
44913
- };
44914
- onTransform = () => {
44915
- this.updateMbr();
44916
- this.subject.publish(this);
44917
- };
44918
- updateMbr() {
44919
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44920
- this.left = translateX;
44921
- this.top = translateY;
44922
- this.right = this.left + this.image.width * scaleX;
44923
- this.bottom = this.top + this.image.height * scaleY;
44924
- }
44925
- doOnceBeforeOnLoad = (callback) => {
44926
- this.loadCallbacks.push(callback);
44927
- };
44928
- doOnceOnLoad = (callback) => {
44929
- this.loadCallbacks.push(callback);
44930
- };
44931
- setId(id) {
44932
- this.id = id;
44933
- this.transformation.setId(id);
44934
- this.linkTo.setId(id);
44935
- return this;
44936
- }
44937
- getId() {
44938
- return this.id;
44721
+ this.updateLines();
44939
44722
  }
44940
44723
  serialize() {
44724
+ this.optimizePoints();
44725
+ const points = [];
44726
+ for (const point5 of this.points) {
44727
+ points.push({ x: point5.x, y: point5.y });
44728
+ }
44941
44729
  return {
44942
- itemType: "Image",
44943
- storageLink: this.storageLink,
44944
- imageDimension: this.imageDimension,
44730
+ itemType: "Drawing",
44731
+ points,
44945
44732
  transformation: this.transformation.serialize(),
44733
+ strokeStyle: this.borderColor,
44734
+ strokeWidth: this.strokeWidth,
44946
44735
  linkTo: this.linkTo.serialize()
44947
44736
  };
44948
44737
  }
44949
- setCoordinates() {
44950
- this.left = this.transformation.matrix.translateX;
44951
- this.top = this.transformation.matrix.translateY;
44952
- this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
44953
- this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
44954
- this.subject.publish(this);
44955
- }
44956
- shootBeforeLoadCallbacks() {
44957
- while (this.beforeLoadCallbacks.length > 0) {
44958
- this.beforeLoadCallbacks.shift()(this);
44738
+ deserialize(data) {
44739
+ this.points = [];
44740
+ for (const point5 of data.points) {
44741
+ this.points.push(new Point(point5.x, point5.y));
44959
44742
  }
44743
+ this.linkTo.deserialize(data.linkTo);
44744
+ this.optimizePoints();
44745
+ this.transformation.deserialize(data.transformation);
44746
+ this.borderColor = data.strokeStyle;
44747
+ this.strokeWidth = data.strokeWidth;
44748
+ this.updateGeometry();
44749
+ return this;
44960
44750
  }
44961
- shootLoadCallbacks() {
44962
- while (this.loadCallbacks.length > 0) {
44963
- this.loadCallbacks.shift()(this);
44964
- }
44751
+ updateGeometry() {
44752
+ this.updatePath2d();
44753
+ this.updateLines();
44754
+ this.updateMbr();
44965
44755
  }
44966
- deserialize(data) {
44967
- if (data.transformation) {
44968
- this.transformation.deserialize(data.transformation);
44756
+ updateMbr() {
44757
+ const offset = this.getStrokeWidth() / 2;
44758
+ const untransformedMbr = this.untransformedMbr.copy();
44759
+ untransformedMbr.left -= offset;
44760
+ untransformedMbr.top -= offset;
44761
+ untransformedMbr.right += offset;
44762
+ untransformedMbr.bottom += offset;
44763
+ const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
44764
+ this.left = mbr.left;
44765
+ this.top = mbr.top;
44766
+ this.right = mbr.right;
44767
+ this.bottom = mbr.bottom;
44768
+ }
44769
+ updatePath2d() {
44770
+ this.path2d = new conf.path2DFactory;
44771
+ const context = this.path2d;
44772
+ const points = this.points;
44773
+ if (points.length < 3) {
44774
+ context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
44775
+ context.closePath();
44776
+ } else {
44777
+ context.moveTo(points[0].x, points[0].y);
44778
+ let j = 1;
44779
+ for (;j < points.length - 2; j++) {
44780
+ const cx = (points[j].x + points[j + 1].x) / 2;
44781
+ const cy = (points[j].y + points[j + 1].y) / 2;
44782
+ context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
44783
+ }
44784
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
44785
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
44786
+ context.quadraticCurveTo(points[j].x, points[j].y, x, y);
44969
44787
  }
44970
- this.linkTo.deserialize(data.linkTo);
44971
- this.image.onload = () => {
44972
- this.setCoordinates();
44973
- this.shootLoadCallbacks();
44974
- };
44975
- if (data.storageLink) {
44976
- this.setStorageLink(data.storageLink);
44788
+ let left = Number.MAX_SAFE_INTEGER;
44789
+ let right = Number.MIN_SAFE_INTEGER;
44790
+ let top = Number.MAX_SAFE_INTEGER;
44791
+ let bottom = Number.MIN_SAFE_INTEGER;
44792
+ for (const { x, y } of this.points) {
44793
+ if (x < left) {
44794
+ left = x;
44795
+ }
44796
+ if (x > right) {
44797
+ right = x;
44798
+ }
44799
+ if (y < top) {
44800
+ top = y;
44801
+ }
44802
+ if (y > bottom) {
44803
+ bottom = y;
44804
+ }
44977
44805
  }
44978
- if (this.image.src) {
44979
- return this;
44806
+ this.untransformedMbr = new Mbr(left, top, right, bottom);
44807
+ }
44808
+ updateLines() {
44809
+ this.lines = [];
44810
+ const matrix = this.transformation.matrix;
44811
+ if (this.points.length < 2) {
44812
+ return;
44813
+ }
44814
+ for (let i = 0;i < this.points.length - 2; i++) {
44815
+ const p1 = this.points[i];
44816
+ const p22 = this.points[i + 1];
44817
+ const line = new Line(p1.copy(), p22.copy());
44818
+ line.transform(matrix);
44819
+ this.lines.push(line);
44980
44820
  }
44981
- this.image = getPlaceholderImage(this.board, data.imageDimension);
44982
- const storageImage = new Image;
44983
- storageImage.onload = () => {
44984
- this.image = storageImage;
44985
- this.onLoad();
44986
- };
44987
- storageImage.onerror = this.onError;
44988
- storageImage.src = this.storageLink;
44989
- return this;
44990
44821
  }
44991
- emit(operation) {
44992
- if (this.events) {
44993
- const command = new ImageCommand([this], operation);
44994
- command.apply();
44995
- this.events.emit(operation, command);
44822
+ optimizePoints() {
44823
+ const dp = douglasPeucker(this.points, 1);
44824
+ dp.push(this.points[this.points.length - 1]);
44825
+ this.points = dp;
44826
+ }
44827
+ addPoint(point5) {
44828
+ const previous2 = this.points[this.points.length - 1];
44829
+ if (previous2) {
44830
+ const distance = point5.getDistance(previous2);
44831
+ if (distance >= 2) {
44832
+ this.points.push(point5);
44833
+ }
44996
44834
  } else {
44997
- this.apply(operation);
44835
+ this.points.push(point5);
44998
44836
  }
44837
+ this.updateGeometry();
44999
44838
  }
45000
- setDimensions(dim) {
45001
- this.imageDimension = dim;
44839
+ setId(id) {
44840
+ this.id = id;
44841
+ this.transformation.setId(id);
44842
+ this.linkTo.setId(id);
44843
+ return this;
45002
44844
  }
45003
- apply(op) {
45004
- switch (op.class) {
45005
- case "Transformation":
45006
- this.transformation.apply(op);
45007
- break;
45008
- case "LinkTo":
45009
- this.linkTo.apply(op);
45010
- break;
45011
- case "Image":
45012
- if (op.data.base64) {
45013
- this.image.src = op.data.base64;
45014
- }
45015
- this.setStorageLink(op.data.storageLink);
45016
- this.setDimensions(op.data.imageDimension);
45017
- this.subject.publish(this);
45018
- break;
45019
- }
44845
+ getId() {
44846
+ return this.id;
45020
44847
  }
45021
44848
  render(context) {
45022
44849
  if (this.transformationRenderBlock) {
@@ -45024,8 +44851,12 @@ class ImageItem extends BaseItem {
45024
44851
  }
45025
44852
  const ctx = context.ctx;
45026
44853
  ctx.save();
44854
+ ctx.strokeStyle = this.borderColor;
44855
+ ctx.lineWidth = this.strokeWidth;
44856
+ ctx.lineCap = "round";
44857
+ ctx.setLineDash(this.linePattern);
45027
44858
  this.transformation.matrix.applyToContext(ctx);
45028
- ctx.drawImage(this.image, 0, 0);
44859
+ ctx.stroke(this.path2d.nativePath);
45029
44860
  ctx.restore();
45030
44861
  if (this.getLinkTo()) {
45031
44862
  const { top, right } = this.getMbr();
@@ -45033,26 +44864,61 @@ class ImageItem extends BaseItem {
45033
44864
  }
45034
44865
  }
45035
44866
  renderHTML(documentFactory) {
45036
- const div = documentFactory.createElement("image-item");
44867
+ const div = documentFactory.createElement("drawing-item");
45037
44868
  const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
45038
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
45039
- div.style.backgroundImage = `url(${this.storageLink})`;
44869
+ const mbr = this.getMbr();
44870
+ const width2 = mbr.getWidth();
44871
+ const height2 = mbr.getHeight();
44872
+ const unscaledWidth = width2 / scaleX;
44873
+ const unscaledHeight = height2 / scaleY;
44874
+ const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
44875
+ svg3.setAttribute("width", `${unscaledWidth}px`);
44876
+ svg3.setAttribute("height", `${unscaledHeight}px`);
44877
+ svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
44878
+ svg3.setAttribute("style", "position: absolute; overflow: visible;");
44879
+ const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
44880
+ pathElement.setAttribute("d", this.getPathData());
44881
+ pathElement.setAttribute("stroke", this.borderColor);
44882
+ pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
44883
+ pathElement.setAttribute("fill", "none");
44884
+ svg3.appendChild(pathElement);
44885
+ div.appendChild(svg3);
45040
44886
  div.id = this.getId();
45041
- div.style.width = `${this.imageDimension.width}px`;
45042
- div.style.height = `${this.imageDimension.height}px`;
45043
- div.style.transformOrigin = "top left";
45044
- div.style.transform = transform;
44887
+ div.style.width = unscaledWidth + "px";
44888
+ div.style.height = unscaledHeight + "px";
44889
+ div.style.transformOrigin = "left top";
44890
+ div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
45045
44891
  div.style.position = "absolute";
45046
- div.style.backgroundSize = "cover";
45047
44892
  div.setAttribute("data-link-to", this.linkTo.serialize() || "");
45048
44893
  if (this.getLinkTo()) {
45049
44894
  const linkElement = this.linkTo.renderHTML(documentFactory);
45050
44895
  scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
45051
- translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
44896
+ translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
45052
44897
  div.appendChild(linkElement);
45053
44898
  }
45054
44899
  return div;
45055
44900
  }
44901
+ getPathData() {
44902
+ const points = this.points;
44903
+ if (points.length < 2) {
44904
+ return "";
44905
+ }
44906
+ let pathData = `M ${points[0].x} ${points[0].y}`;
44907
+ if (points.length < 3) {
44908
+ pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
44909
+ } else {
44910
+ let j = 1;
44911
+ for (;j < points.length - 2; j++) {
44912
+ const cx = (points[j].x + points[j + 1].x) / 2;
44913
+ const cy = (points[j].y + points[j + 1].y) / 2;
44914
+ pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
44915
+ }
44916
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
44917
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
44918
+ pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
44919
+ }
44920
+ return pathData;
44921
+ }
45056
44922
  getPath() {
45057
44923
  const { left, top, right, bottom } = this.getMbr();
45058
44924
  const leftTop = new Point(left, top);
@@ -45077,27 +44943,162 @@ class ImageItem extends BaseItem {
45077
44943
  new Point(mbr.right, mbr.top + height2 / 2)
45078
44944
  ];
45079
44945
  }
44946
+ getLines() {
44947
+ return this.lines;
44948
+ }
45080
44949
  isClosed() {
45081
44950
  return true;
45082
44951
  }
45083
- getRichText() {
45084
- return null;
44952
+ isEnclosedOrCrossedBy(rect) {
44953
+ for (const line of this.lines) {
44954
+ if (line.isEnclosedOrCrossedBy(rect)) {
44955
+ return true;
44956
+ }
44957
+ }
44958
+ return false;
44959
+ }
44960
+ emit(operation) {
44961
+ if (this.events) {
44962
+ const command = new DrawingCommand([this], operation);
44963
+ command.apply();
44964
+ this.events.emit(operation, command);
44965
+ } else {
44966
+ this.apply(operation);
44967
+ }
44968
+ }
44969
+ apply(op) {
44970
+ switch (op.class) {
44971
+ case "Drawing":
44972
+ switch (op.method) {
44973
+ case "setStrokeColor":
44974
+ this.borderColor = op.color;
44975
+ break;
44976
+ case "setStrokeWidth":
44977
+ this.strokeWidth = op.width;
44978
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44979
+ break;
44980
+ case "setStrokeOpacity":
44981
+ this.borderOpacity = op.opacity;
44982
+ break;
44983
+ case "setStrokeStyle":
44984
+ this.borderStyle = op.style;
44985
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44986
+ break;
44987
+ }
44988
+ this.updateMbr();
44989
+ break;
44990
+ case "Transformation":
44991
+ this.transformation.apply(op);
44992
+ break;
44993
+ case "LinkTo":
44994
+ this.linkTo.apply(op);
44995
+ break;
44996
+ default:
44997
+ return;
44998
+ }
44999
+ this.subject.publish(this);
45000
+ }
45001
+ setStrokeOpacity(opacity) {
45002
+ this.emit({
45003
+ class: "Drawing",
45004
+ method: "setStrokeOpacity",
45005
+ item: [this.id],
45006
+ opacity
45007
+ });
45008
+ return this;
45009
+ }
45010
+ getStrokeOpacity() {
45011
+ return this.borderOpacity;
45012
+ }
45013
+ setBorderStyle(style2) {
45014
+ this.emit({
45015
+ class: "Drawing",
45016
+ method: "setStrokeStyle",
45017
+ item: [this.id],
45018
+ style: style2
45019
+ });
45020
+ return this;
45021
+ }
45022
+ getBorderStyle() {
45023
+ return this.borderStyle;
45024
+ }
45025
+ setStrokeColor(color2) {
45026
+ this.emit({
45027
+ class: "Drawing",
45028
+ method: "setStrokeColor",
45029
+ item: [this.id],
45030
+ color: color2
45031
+ });
45032
+ return this;
45033
+ }
45034
+ getStrokeColor() {
45035
+ return this.borderColor;
45036
+ }
45037
+ setStrokeWidth(width2) {
45038
+ this.emit({
45039
+ class: "Drawing",
45040
+ method: "setStrokeWidth",
45041
+ item: [this.id],
45042
+ width: width2,
45043
+ prevWidth: this.strokeWidth
45044
+ });
45045
+ return this;
45085
45046
  }
45086
45047
  getLinkTo() {
45087
45048
  return this.linkTo.link;
45088
45049
  }
45089
- download() {
45090
- const linkElem = document.createElement("a");
45091
- linkElem.href = this.storageLink;
45092
- linkElem.setAttribute("download", "");
45093
- linkElem.click();
45050
+ getStrokeWidth() {
45051
+ return this.strokeWidth;
45094
45052
  }
45095
- onRemove() {
45096
- const storageId = this.getStorageId();
45097
- if (storageId) {
45098
- conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
45053
+ getRichText() {
45054
+ return null;
45055
+ }
45056
+ isPointNearLine(point5, threshold = 10) {
45057
+ const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
45058
+ const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
45059
+ const transformedMouse = new Point(transformedMouseX, transformedMouseY);
45060
+ for (let i = 0;i < this.points.length - 1; i++) {
45061
+ const p1 = this.points[i];
45062
+ const p22 = this.points[i + 1];
45063
+ const distance = getPerpendicularDistance(transformedMouse, p1, p22);
45064
+ if (distance < threshold) {
45065
+ return true;
45066
+ }
45099
45067
  }
45100
- super.onRemove();
45068
+ return false;
45069
+ }
45070
+ }
45071
+ function getPerpendicularDistance(point5, lineStart, lineEnd) {
45072
+ const { x: px, y: py } = point5;
45073
+ const { x: sx, y: sy } = lineStart;
45074
+ const { x: ex, y: ey } = lineEnd;
45075
+ const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
45076
+ const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
45077
+ return numerator / denominator;
45078
+ }
45079
+ function douglasPeucker(points, epsilon2) {
45080
+ if (points.length < 3) {
45081
+ return points;
45082
+ }
45083
+ const start = points[0];
45084
+ const end = points[points.length - 1];
45085
+ let maxDistance = 0;
45086
+ let maxIndex = 0;
45087
+ for (let i = 1;i < points.length - 1; i++) {
45088
+ const distance = getPerpendicularDistance(points[i], start, end);
45089
+ if (distance > maxDistance) {
45090
+ maxDistance = distance;
45091
+ maxIndex = i;
45092
+ }
45093
+ }
45094
+ if (maxDistance > epsilon2) {
45095
+ const leftSubPoints = points.slice(0, maxIndex + 1);
45096
+ const rightSubPoints = points.slice(maxIndex);
45097
+ const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
45098
+ const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
45099
+ return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
45100
+ } else {
45101
+ return [start, end];
45101
45102
  }
45102
45103
  }
45103
45104
  // src/Items/Group/Group.ts