microboard-temp 0.4.41 → 0.4.43
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/browser.js +619 -609
- package/dist/cjs/index.js +619 -609
- package/dist/cjs/node.js +619 -609
- package/dist/esm/browser.js +619 -609
- package/dist/esm/index.js +619 -609
- package/dist/esm/node.js +619 -609
- package/package.json +1 -1
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;
|
|
@@ -23776,6 +23349,7 @@ class SpatialIndex {
|
|
|
23776
23349
|
}
|
|
23777
23350
|
});
|
|
23778
23351
|
});
|
|
23352
|
+
console.log([...items, ...children]);
|
|
23779
23353
|
return [...items, ...children];
|
|
23780
23354
|
}
|
|
23781
23355
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -23790,6 +23364,7 @@ class SpatialIndex {
|
|
|
23790
23364
|
}
|
|
23791
23365
|
});
|
|
23792
23366
|
});
|
|
23367
|
+
console.log([...items, ...children]);
|
|
23793
23368
|
return [...items, ...children];
|
|
23794
23369
|
}
|
|
23795
23370
|
getUnderPoint(point3, tolerance = 5) {
|
|
@@ -23803,6 +23378,7 @@ class SpatialIndex {
|
|
|
23803
23378
|
}
|
|
23804
23379
|
});
|
|
23805
23380
|
});
|
|
23381
|
+
console.log([...items, ...children]);
|
|
23806
23382
|
return [...items, ...children];
|
|
23807
23383
|
}
|
|
23808
23384
|
getRectsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -23817,6 +23393,7 @@ class SpatialIndex {
|
|
|
23817
23393
|
}
|
|
23818
23394
|
});
|
|
23819
23395
|
});
|
|
23396
|
+
console.log([...items, ...children]);
|
|
23820
23397
|
return [...items, ...children];
|
|
23821
23398
|
}
|
|
23822
23399
|
getItemsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -23836,9 +23413,11 @@ class SpatialIndex {
|
|
|
23836
23413
|
distance: point3.getDistance(item.getMbr().getCenter())
|
|
23837
23414
|
})).filter(({ distance }) => distance <= maxDistance);
|
|
23838
23415
|
withDistance.sort((a, b) => a.distance - b.distance);
|
|
23416
|
+
console.log(withDistance.slice(0, maxItems).map(({ item }) => item));
|
|
23839
23417
|
return withDistance.slice(0, maxItems).map(({ item }) => item);
|
|
23840
23418
|
}
|
|
23841
23419
|
list() {
|
|
23420
|
+
console.log("list", this.getItemsWithIncludedChildren(this.itemsArray).concat());
|
|
23842
23421
|
return this.getItemsWithIncludedChildren(this.itemsArray).concat();
|
|
23843
23422
|
}
|
|
23844
23423
|
getZIndex(item) {
|
|
@@ -23931,12 +23510,12 @@ class Items {
|
|
|
23931
23510
|
if (enclosed.length === 0) {
|
|
23932
23511
|
enclosed = underPointer;
|
|
23933
23512
|
}
|
|
23934
|
-
if (underPointer.some((item) => item
|
|
23513
|
+
if (underPointer.some((item) => item.itemType === "Drawing")) {
|
|
23935
23514
|
enclosed = [...underPointer, ...enclosed];
|
|
23936
23515
|
}
|
|
23937
23516
|
const { nearest } = enclosed.reduce((acc, item) => {
|
|
23938
23517
|
const area = item.getMbr().getHeight() * item.getMbr().getWidth();
|
|
23939
|
-
if (item
|
|
23518
|
+
if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
|
|
23940
23519
|
return acc;
|
|
23941
23520
|
}
|
|
23942
23521
|
const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
|
|
@@ -24209,6 +23788,7 @@ class SimpleSpatialIndex {
|
|
|
24209
23788
|
items.push(item);
|
|
24210
23789
|
}
|
|
24211
23790
|
});
|
|
23791
|
+
console.log("simple", items);
|
|
24212
23792
|
return items;
|
|
24213
23793
|
}
|
|
24214
23794
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -24219,6 +23799,7 @@ class SimpleSpatialIndex {
|
|
|
24219
23799
|
items.push(item);
|
|
24220
23800
|
}
|
|
24221
23801
|
});
|
|
23802
|
+
console.log("simple", items);
|
|
24222
23803
|
return items;
|
|
24223
23804
|
}
|
|
24224
23805
|
getUnderPoint(point3, tolerace = 5) {
|
|
@@ -24228,12 +23809,14 @@ class SimpleSpatialIndex {
|
|
|
24228
23809
|
items.push(item);
|
|
24229
23810
|
}
|
|
24230
23811
|
});
|
|
23812
|
+
console.log("simple", items);
|
|
24231
23813
|
return items;
|
|
24232
23814
|
}
|
|
24233
23815
|
getMbr() {
|
|
24234
23816
|
return this.Mbr;
|
|
24235
23817
|
}
|
|
24236
23818
|
list() {
|
|
23819
|
+
console.log("simple list", this.itemsArray.concat());
|
|
24237
23820
|
return this.itemsArray.concat();
|
|
24238
23821
|
}
|
|
24239
23822
|
getZIndex(item) {
|
|
@@ -44822,202 +44405,455 @@ class Placeholder extends BaseItem {
|
|
|
44822
44405
|
renderHTML(documentFactory) {
|
|
44823
44406
|
return documentFactory.createElement("div");
|
|
44824
44407
|
}
|
|
44825
|
-
getLinkTo() {
|
|
44826
|
-
return;
|
|
44408
|
+
getLinkTo() {
|
|
44409
|
+
return;
|
|
44410
|
+
}
|
|
44411
|
+
getRichText() {
|
|
44412
|
+
return null;
|
|
44413
|
+
}
|
|
44414
|
+
}
|
|
44415
|
+
// src/Items/Image/Image.ts
|
|
44416
|
+
function getPlaceholderImage(board, imageDimension) {
|
|
44417
|
+
const placeholderCanvas = conf.documentFactory.createElement("canvas");
|
|
44418
|
+
const placeholderContext = placeholderCanvas.getContext("2d");
|
|
44419
|
+
const context = new DrawingContext(board.camera, placeholderContext);
|
|
44420
|
+
const placeholder = new Placeholder(board);
|
|
44421
|
+
if (imageDimension) {
|
|
44422
|
+
placeholderCanvas.width = imageDimension.width;
|
|
44423
|
+
placeholderCanvas.height = imageDimension.height;
|
|
44424
|
+
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
44425
|
+
} else {
|
|
44426
|
+
placeholderCanvas.width = 250;
|
|
44427
|
+
placeholderCanvas.height = 50;
|
|
44428
|
+
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
44429
|
+
}
|
|
44430
|
+
const placeholderImage = new Image;
|
|
44431
|
+
placeholderImage.src = placeholderCanvas.toDataURL();
|
|
44432
|
+
return placeholderImage;
|
|
44433
|
+
}
|
|
44434
|
+
|
|
44435
|
+
class ImageItem extends BaseItem {
|
|
44436
|
+
events;
|
|
44437
|
+
itemType = "Image";
|
|
44438
|
+
parent = "Board";
|
|
44439
|
+
image;
|
|
44440
|
+
transformation;
|
|
44441
|
+
linkTo;
|
|
44442
|
+
subject = new Subject;
|
|
44443
|
+
loadCallbacks = [];
|
|
44444
|
+
beforeLoadCallbacks = [];
|
|
44445
|
+
transformationRenderBlock = undefined;
|
|
44446
|
+
storageLink;
|
|
44447
|
+
imageDimension;
|
|
44448
|
+
board;
|
|
44449
|
+
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
44450
|
+
super(board, id);
|
|
44451
|
+
this.events = events;
|
|
44452
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
44453
|
+
this.board = board;
|
|
44454
|
+
this.setStorageLink(storageLink);
|
|
44455
|
+
this.imageDimension = imageDimension;
|
|
44456
|
+
this.transformation = new Transformation(id, events);
|
|
44457
|
+
this.image = new Image;
|
|
44458
|
+
this.image.crossOrigin = "anonymous";
|
|
44459
|
+
this.image.onload = this.onLoad;
|
|
44460
|
+
this.image.onerror = this.onError;
|
|
44461
|
+
if (typeof base64 === "string") {
|
|
44462
|
+
this.image.src = base64;
|
|
44463
|
+
}
|
|
44464
|
+
this.linkTo.subject.subscribe(() => {
|
|
44465
|
+
this.updateMbr();
|
|
44466
|
+
this.subject.publish(this);
|
|
44467
|
+
});
|
|
44468
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
44469
|
+
}
|
|
44470
|
+
setStorageLink(link2) {
|
|
44471
|
+
try {
|
|
44472
|
+
const url = new URL(link2);
|
|
44473
|
+
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
44474
|
+
} catch (_) {}
|
|
44475
|
+
}
|
|
44476
|
+
getStorageId() {
|
|
44477
|
+
return this.storageLink.split("/").pop();
|
|
44478
|
+
}
|
|
44479
|
+
handleError = () => {
|
|
44480
|
+
console.error("Invalid dataUrl or image failed to load.");
|
|
44481
|
+
this.image = getPlaceholderImage(this.board);
|
|
44482
|
+
this.updateMbr();
|
|
44483
|
+
this.subject.publish(this);
|
|
44484
|
+
this.shootLoadCallbacks();
|
|
44485
|
+
};
|
|
44486
|
+
onLoad = async () => {
|
|
44487
|
+
this.shootBeforeLoadCallbacks();
|
|
44488
|
+
this.updateMbr();
|
|
44489
|
+
this.subject.publish(this);
|
|
44490
|
+
this.shootLoadCallbacks();
|
|
44491
|
+
};
|
|
44492
|
+
onError = (_error) => {
|
|
44493
|
+
this.image = getPlaceholderImage(this.board);
|
|
44494
|
+
this.updateMbr();
|
|
44495
|
+
this.subject.publish(this);
|
|
44496
|
+
this.shootLoadCallbacks();
|
|
44497
|
+
};
|
|
44498
|
+
onTransform = () => {
|
|
44499
|
+
this.updateMbr();
|
|
44500
|
+
this.subject.publish(this);
|
|
44501
|
+
};
|
|
44502
|
+
updateMbr() {
|
|
44503
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44504
|
+
this.left = translateX;
|
|
44505
|
+
this.top = translateY;
|
|
44506
|
+
this.right = this.left + this.image.width * scaleX;
|
|
44507
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
44508
|
+
}
|
|
44509
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
44510
|
+
this.loadCallbacks.push(callback);
|
|
44511
|
+
};
|
|
44512
|
+
doOnceOnLoad = (callback) => {
|
|
44513
|
+
this.loadCallbacks.push(callback);
|
|
44514
|
+
};
|
|
44515
|
+
setId(id) {
|
|
44516
|
+
this.id = id;
|
|
44517
|
+
this.transformation.setId(id);
|
|
44518
|
+
this.linkTo.setId(id);
|
|
44519
|
+
return this;
|
|
44520
|
+
}
|
|
44521
|
+
getId() {
|
|
44522
|
+
return this.id;
|
|
44523
|
+
}
|
|
44524
|
+
serialize() {
|
|
44525
|
+
return {
|
|
44526
|
+
itemType: "Image",
|
|
44527
|
+
storageLink: this.storageLink,
|
|
44528
|
+
imageDimension: this.imageDimension,
|
|
44529
|
+
transformation: this.transformation.serialize(),
|
|
44530
|
+
linkTo: this.linkTo.serialize()
|
|
44531
|
+
};
|
|
44532
|
+
}
|
|
44533
|
+
setCoordinates() {
|
|
44534
|
+
this.left = this.transformation.matrix.translateX;
|
|
44535
|
+
this.top = this.transformation.matrix.translateY;
|
|
44536
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
44537
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
44538
|
+
this.subject.publish(this);
|
|
44539
|
+
}
|
|
44540
|
+
shootBeforeLoadCallbacks() {
|
|
44541
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
44542
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
44543
|
+
}
|
|
44544
|
+
}
|
|
44545
|
+
shootLoadCallbacks() {
|
|
44546
|
+
while (this.loadCallbacks.length > 0) {
|
|
44547
|
+
this.loadCallbacks.shift()(this);
|
|
44548
|
+
}
|
|
44549
|
+
}
|
|
44550
|
+
deserialize(data) {
|
|
44551
|
+
if (data.transformation) {
|
|
44552
|
+
this.transformation.deserialize(data.transformation);
|
|
44553
|
+
}
|
|
44554
|
+
this.linkTo.deserialize(data.linkTo);
|
|
44555
|
+
this.image.onload = () => {
|
|
44556
|
+
this.setCoordinates();
|
|
44557
|
+
this.shootLoadCallbacks();
|
|
44558
|
+
};
|
|
44559
|
+
if (data.storageLink) {
|
|
44560
|
+
this.setStorageLink(data.storageLink);
|
|
44561
|
+
}
|
|
44562
|
+
if (this.image.src) {
|
|
44563
|
+
return this;
|
|
44564
|
+
}
|
|
44565
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
44566
|
+
const storageImage = new Image;
|
|
44567
|
+
storageImage.onload = () => {
|
|
44568
|
+
this.image = storageImage;
|
|
44569
|
+
this.onLoad();
|
|
44570
|
+
};
|
|
44571
|
+
storageImage.onerror = this.onError;
|
|
44572
|
+
storageImage.src = this.storageLink;
|
|
44573
|
+
return this;
|
|
44574
|
+
}
|
|
44575
|
+
emit(operation) {
|
|
44576
|
+
if (this.events) {
|
|
44577
|
+
const command = new ImageCommand([this], operation);
|
|
44578
|
+
command.apply();
|
|
44579
|
+
this.events.emit(operation, command);
|
|
44580
|
+
} else {
|
|
44581
|
+
this.apply(operation);
|
|
44582
|
+
}
|
|
44583
|
+
}
|
|
44584
|
+
setDimensions(dim) {
|
|
44585
|
+
this.imageDimension = dim;
|
|
44586
|
+
}
|
|
44587
|
+
apply(op) {
|
|
44588
|
+
switch (op.class) {
|
|
44589
|
+
case "Transformation":
|
|
44590
|
+
this.transformation.apply(op);
|
|
44591
|
+
break;
|
|
44592
|
+
case "LinkTo":
|
|
44593
|
+
this.linkTo.apply(op);
|
|
44594
|
+
break;
|
|
44595
|
+
case "Image":
|
|
44596
|
+
if (op.data.base64) {
|
|
44597
|
+
this.image.src = op.data.base64;
|
|
44598
|
+
}
|
|
44599
|
+
this.setStorageLink(op.data.storageLink);
|
|
44600
|
+
this.setDimensions(op.data.imageDimension);
|
|
44601
|
+
this.subject.publish(this);
|
|
44602
|
+
break;
|
|
44603
|
+
}
|
|
44604
|
+
}
|
|
44605
|
+
render(context) {
|
|
44606
|
+
if (this.transformationRenderBlock) {
|
|
44607
|
+
return;
|
|
44608
|
+
}
|
|
44609
|
+
const ctx = context.ctx;
|
|
44610
|
+
ctx.save();
|
|
44611
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
44612
|
+
ctx.drawImage(this.image, 0, 0);
|
|
44613
|
+
ctx.restore();
|
|
44614
|
+
if (this.getLinkTo()) {
|
|
44615
|
+
const { top, right } = this.getMbr();
|
|
44616
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
44617
|
+
}
|
|
44618
|
+
}
|
|
44619
|
+
renderHTML(documentFactory) {
|
|
44620
|
+
const div = documentFactory.createElement("image-item");
|
|
44621
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44622
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
44623
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
44624
|
+
div.id = this.getId();
|
|
44625
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
44626
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
44627
|
+
div.style.transformOrigin = "top left";
|
|
44628
|
+
div.style.transform = transform;
|
|
44629
|
+
div.style.position = "absolute";
|
|
44630
|
+
div.style.backgroundSize = "cover";
|
|
44631
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
44632
|
+
if (this.getLinkTo()) {
|
|
44633
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
44634
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
44635
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
44636
|
+
div.appendChild(linkElement);
|
|
44637
|
+
}
|
|
44638
|
+
return div;
|
|
44639
|
+
}
|
|
44640
|
+
getPath() {
|
|
44641
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
44642
|
+
const leftTop = new Point(left, top);
|
|
44643
|
+
const rightTop = new Point(right, top);
|
|
44644
|
+
const rightBottom = new Point(right, bottom);
|
|
44645
|
+
const leftBottom = new Point(left, bottom);
|
|
44646
|
+
return new Path([
|
|
44647
|
+
new Line(leftTop, rightTop),
|
|
44648
|
+
new Line(rightTop, rightBottom),
|
|
44649
|
+
new Line(rightBottom, leftBottom),
|
|
44650
|
+
new Line(leftBottom, leftTop)
|
|
44651
|
+
], true);
|
|
44652
|
+
}
|
|
44653
|
+
getSnapAnchorPoints() {
|
|
44654
|
+
const mbr = this.getMbr();
|
|
44655
|
+
const width2 = mbr.getWidth();
|
|
44656
|
+
const height2 = mbr.getHeight();
|
|
44657
|
+
return [
|
|
44658
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
44659
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
44660
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
44661
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
44662
|
+
];
|
|
44663
|
+
}
|
|
44664
|
+
isClosed() {
|
|
44665
|
+
return true;
|
|
44827
44666
|
}
|
|
44828
44667
|
getRichText() {
|
|
44829
44668
|
return null;
|
|
44830
44669
|
}
|
|
44670
|
+
getLinkTo() {
|
|
44671
|
+
return this.linkTo.link;
|
|
44672
|
+
}
|
|
44673
|
+
download() {
|
|
44674
|
+
const linkElem = document.createElement("a");
|
|
44675
|
+
linkElem.href = this.storageLink;
|
|
44676
|
+
linkElem.setAttribute("download", "");
|
|
44677
|
+
linkElem.click();
|
|
44678
|
+
}
|
|
44679
|
+
onRemove() {
|
|
44680
|
+
const storageId = this.getStorageId();
|
|
44681
|
+
if (storageId) {
|
|
44682
|
+
conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
|
|
44683
|
+
}
|
|
44684
|
+
super.onRemove();
|
|
44685
|
+
}
|
|
44831
44686
|
}
|
|
44832
|
-
// src/
|
|
44833
|
-
function
|
|
44834
|
-
|
|
44835
|
-
|
|
44836
|
-
const context = new DrawingContext(board.camera, placeholderContext);
|
|
44837
|
-
const placeholder = new Placeholder(board);
|
|
44838
|
-
if (imageDimension) {
|
|
44839
|
-
placeholderCanvas.width = imageDimension.width;
|
|
44840
|
-
placeholderCanvas.height = imageDimension.height;
|
|
44841
|
-
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
44842
|
-
} else {
|
|
44843
|
-
placeholderCanvas.width = 250;
|
|
44844
|
-
placeholderCanvas.height = 50;
|
|
44845
|
-
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
44687
|
+
// src/isSafari.ts
|
|
44688
|
+
function isSafari() {
|
|
44689
|
+
if (typeof navigator === "undefined") {
|
|
44690
|
+
return false;
|
|
44846
44691
|
}
|
|
44847
|
-
const
|
|
44848
|
-
|
|
44849
|
-
|
|
44692
|
+
const agent = navigator.userAgent;
|
|
44693
|
+
const vendor = navigator.vendor;
|
|
44694
|
+
const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
44695
|
+
return is2;
|
|
44850
44696
|
}
|
|
44851
44697
|
|
|
44852
|
-
|
|
44698
|
+
// src/Items/Drawing/Drawing.ts
|
|
44699
|
+
class Drawing extends BaseItem {
|
|
44700
|
+
points;
|
|
44853
44701
|
events;
|
|
44854
|
-
itemType = "
|
|
44702
|
+
itemType = "Drawing";
|
|
44855
44703
|
parent = "Board";
|
|
44856
|
-
image;
|
|
44857
44704
|
transformation;
|
|
44858
|
-
|
|
44705
|
+
path2d = new conf.path2DFactory;
|
|
44859
44706
|
subject = new Subject;
|
|
44860
|
-
|
|
44861
|
-
|
|
44707
|
+
untransformedMbr = new Mbr;
|
|
44708
|
+
lines = [];
|
|
44709
|
+
linkTo;
|
|
44710
|
+
strokeWidth = 1;
|
|
44711
|
+
borderStyle = "solid";
|
|
44712
|
+
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
44713
|
+
borderOpacity = 1;
|
|
44862
44714
|
transformationRenderBlock = undefined;
|
|
44863
|
-
|
|
44864
|
-
imageDimension;
|
|
44865
|
-
board;
|
|
44866
|
-
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
44715
|
+
constructor(board, points, events, id = "") {
|
|
44867
44716
|
super(board, id);
|
|
44717
|
+
this.points = points;
|
|
44868
44718
|
this.events = events;
|
|
44869
|
-
this.linkTo = new LinkTo(this.id, events);
|
|
44870
|
-
this.board = board;
|
|
44871
|
-
this.setStorageLink(storageLink);
|
|
44872
|
-
this.imageDimension = imageDimension;
|
|
44873
44719
|
this.transformation = new Transformation(id, events);
|
|
44874
|
-
this.
|
|
44875
|
-
this.
|
|
44876
|
-
|
|
44877
|
-
|
|
44878
|
-
|
|
44879
|
-
|
|
44880
|
-
}
|
|
44720
|
+
this.linkTo = new LinkTo(this.id, this.events);
|
|
44721
|
+
this.transformation.subject.subscribe(() => {
|
|
44722
|
+
this.updateMbr();
|
|
44723
|
+
this.updateLines();
|
|
44724
|
+
this.subject.publish(this);
|
|
44725
|
+
});
|
|
44881
44726
|
this.linkTo.subject.subscribe(() => {
|
|
44882
44727
|
this.updateMbr();
|
|
44728
|
+
this.updateLines();
|
|
44883
44729
|
this.subject.publish(this);
|
|
44884
44730
|
});
|
|
44885
|
-
this.
|
|
44886
|
-
}
|
|
44887
|
-
setStorageLink(link2) {
|
|
44888
|
-
try {
|
|
44889
|
-
const url = new URL(link2);
|
|
44890
|
-
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
44891
|
-
} catch (_) {}
|
|
44892
|
-
}
|
|
44893
|
-
getStorageId() {
|
|
44894
|
-
return this.storageLink.split("/").pop();
|
|
44895
|
-
}
|
|
44896
|
-
handleError = () => {
|
|
44897
|
-
console.error("Invalid dataUrl or image failed to load.");
|
|
44898
|
-
this.image = getPlaceholderImage(this.board);
|
|
44899
|
-
this.updateMbr();
|
|
44900
|
-
this.subject.publish(this);
|
|
44901
|
-
this.shootLoadCallbacks();
|
|
44902
|
-
};
|
|
44903
|
-
onLoad = async () => {
|
|
44904
|
-
this.shootBeforeLoadCallbacks();
|
|
44905
|
-
this.updateMbr();
|
|
44906
|
-
this.subject.publish(this);
|
|
44907
|
-
this.shootLoadCallbacks();
|
|
44908
|
-
};
|
|
44909
|
-
onError = (_error) => {
|
|
44910
|
-
this.image = getPlaceholderImage(this.board);
|
|
44911
|
-
this.updateMbr();
|
|
44912
|
-
this.subject.publish(this);
|
|
44913
|
-
this.shootLoadCallbacks();
|
|
44914
|
-
};
|
|
44915
|
-
onTransform = () => {
|
|
44916
|
-
this.updateMbr();
|
|
44917
|
-
this.subject.publish(this);
|
|
44918
|
-
};
|
|
44919
|
-
updateMbr() {
|
|
44920
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44921
|
-
this.left = translateX;
|
|
44922
|
-
this.top = translateY;
|
|
44923
|
-
this.right = this.left + this.image.width * scaleX;
|
|
44924
|
-
this.bottom = this.top + this.image.height * scaleY;
|
|
44925
|
-
}
|
|
44926
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
44927
|
-
this.loadCallbacks.push(callback);
|
|
44928
|
-
};
|
|
44929
|
-
doOnceOnLoad = (callback) => {
|
|
44930
|
-
this.loadCallbacks.push(callback);
|
|
44931
|
-
};
|
|
44932
|
-
setId(id) {
|
|
44933
|
-
this.id = id;
|
|
44934
|
-
this.transformation.setId(id);
|
|
44935
|
-
this.linkTo.setId(id);
|
|
44936
|
-
return this;
|
|
44937
|
-
}
|
|
44938
|
-
getId() {
|
|
44939
|
-
return this.id;
|
|
44731
|
+
this.updateLines();
|
|
44940
44732
|
}
|
|
44941
44733
|
serialize() {
|
|
44734
|
+
this.optimizePoints();
|
|
44735
|
+
const points = [];
|
|
44736
|
+
for (const point5 of this.points) {
|
|
44737
|
+
points.push({ x: point5.x, y: point5.y });
|
|
44738
|
+
}
|
|
44942
44739
|
return {
|
|
44943
|
-
itemType: "
|
|
44944
|
-
|
|
44945
|
-
imageDimension: this.imageDimension,
|
|
44740
|
+
itemType: "Drawing",
|
|
44741
|
+
points,
|
|
44946
44742
|
transformation: this.transformation.serialize(),
|
|
44743
|
+
strokeStyle: this.borderColor,
|
|
44744
|
+
strokeWidth: this.strokeWidth,
|
|
44947
44745
|
linkTo: this.linkTo.serialize()
|
|
44948
44746
|
};
|
|
44949
44747
|
}
|
|
44950
|
-
|
|
44951
|
-
this.
|
|
44952
|
-
|
|
44953
|
-
|
|
44954
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
44955
|
-
this.subject.publish(this);
|
|
44956
|
-
}
|
|
44957
|
-
shootBeforeLoadCallbacks() {
|
|
44958
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
44959
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
44748
|
+
deserialize(data) {
|
|
44749
|
+
this.points = [];
|
|
44750
|
+
for (const point5 of data.points) {
|
|
44751
|
+
this.points.push(new Point(point5.x, point5.y));
|
|
44960
44752
|
}
|
|
44753
|
+
this.linkTo.deserialize(data.linkTo);
|
|
44754
|
+
this.optimizePoints();
|
|
44755
|
+
this.transformation.deserialize(data.transformation);
|
|
44756
|
+
this.borderColor = data.strokeStyle;
|
|
44757
|
+
this.strokeWidth = data.strokeWidth;
|
|
44758
|
+
this.updateGeometry();
|
|
44759
|
+
return this;
|
|
44961
44760
|
}
|
|
44962
|
-
|
|
44963
|
-
|
|
44964
|
-
|
|
44965
|
-
|
|
44761
|
+
updateGeometry() {
|
|
44762
|
+
this.updatePath2d();
|
|
44763
|
+
this.updateLines();
|
|
44764
|
+
this.updateMbr();
|
|
44966
44765
|
}
|
|
44967
|
-
|
|
44968
|
-
|
|
44969
|
-
|
|
44766
|
+
updateMbr() {
|
|
44767
|
+
const offset = this.getStrokeWidth() / 2;
|
|
44768
|
+
const untransformedMbr = this.untransformedMbr.copy();
|
|
44769
|
+
untransformedMbr.left -= offset;
|
|
44770
|
+
untransformedMbr.top -= offset;
|
|
44771
|
+
untransformedMbr.right += offset;
|
|
44772
|
+
untransformedMbr.bottom += offset;
|
|
44773
|
+
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
44774
|
+
this.left = mbr.left;
|
|
44775
|
+
this.top = mbr.top;
|
|
44776
|
+
this.right = mbr.right;
|
|
44777
|
+
this.bottom = mbr.bottom;
|
|
44778
|
+
}
|
|
44779
|
+
updatePath2d() {
|
|
44780
|
+
this.path2d = new conf.path2DFactory;
|
|
44781
|
+
const context = this.path2d;
|
|
44782
|
+
const points = this.points;
|
|
44783
|
+
if (points.length < 3) {
|
|
44784
|
+
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
44785
|
+
context.closePath();
|
|
44786
|
+
} else {
|
|
44787
|
+
context.moveTo(points[0].x, points[0].y);
|
|
44788
|
+
let j = 1;
|
|
44789
|
+
for (;j < points.length - 2; j++) {
|
|
44790
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
44791
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
44792
|
+
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
44793
|
+
}
|
|
44794
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
44795
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
44796
|
+
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
44970
44797
|
}
|
|
44971
|
-
|
|
44972
|
-
|
|
44973
|
-
|
|
44974
|
-
|
|
44975
|
-
}
|
|
44976
|
-
|
|
44977
|
-
|
|
44798
|
+
let left = Number.MAX_SAFE_INTEGER;
|
|
44799
|
+
let right = Number.MIN_SAFE_INTEGER;
|
|
44800
|
+
let top = Number.MAX_SAFE_INTEGER;
|
|
44801
|
+
let bottom = Number.MIN_SAFE_INTEGER;
|
|
44802
|
+
for (const { x, y } of this.points) {
|
|
44803
|
+
if (x < left) {
|
|
44804
|
+
left = x;
|
|
44805
|
+
}
|
|
44806
|
+
if (x > right) {
|
|
44807
|
+
right = x;
|
|
44808
|
+
}
|
|
44809
|
+
if (y < top) {
|
|
44810
|
+
top = y;
|
|
44811
|
+
}
|
|
44812
|
+
if (y > bottom) {
|
|
44813
|
+
bottom = y;
|
|
44814
|
+
}
|
|
44978
44815
|
}
|
|
44979
|
-
|
|
44980
|
-
|
|
44816
|
+
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
44817
|
+
}
|
|
44818
|
+
updateLines() {
|
|
44819
|
+
this.lines = [];
|
|
44820
|
+
const matrix = this.transformation.matrix;
|
|
44821
|
+
if (this.points.length < 2) {
|
|
44822
|
+
return;
|
|
44823
|
+
}
|
|
44824
|
+
for (let i = 0;i < this.points.length - 2; i++) {
|
|
44825
|
+
const p1 = this.points[i];
|
|
44826
|
+
const p22 = this.points[i + 1];
|
|
44827
|
+
const line = new Line(p1.copy(), p22.copy());
|
|
44828
|
+
line.transform(matrix);
|
|
44829
|
+
this.lines.push(line);
|
|
44981
44830
|
}
|
|
44982
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
44983
|
-
const storageImage = new Image;
|
|
44984
|
-
storageImage.onload = () => {
|
|
44985
|
-
this.image = storageImage;
|
|
44986
|
-
this.onLoad();
|
|
44987
|
-
};
|
|
44988
|
-
storageImage.onerror = this.onError;
|
|
44989
|
-
storageImage.src = this.storageLink;
|
|
44990
|
-
return this;
|
|
44991
44831
|
}
|
|
44992
|
-
|
|
44993
|
-
|
|
44994
|
-
|
|
44995
|
-
|
|
44996
|
-
|
|
44832
|
+
optimizePoints() {
|
|
44833
|
+
const dp = douglasPeucker(this.points, 1);
|
|
44834
|
+
dp.push(this.points[this.points.length - 1]);
|
|
44835
|
+
this.points = dp;
|
|
44836
|
+
}
|
|
44837
|
+
addPoint(point5) {
|
|
44838
|
+
const previous2 = this.points[this.points.length - 1];
|
|
44839
|
+
if (previous2) {
|
|
44840
|
+
const distance = point5.getDistance(previous2);
|
|
44841
|
+
if (distance >= 2) {
|
|
44842
|
+
this.points.push(point5);
|
|
44843
|
+
}
|
|
44997
44844
|
} else {
|
|
44998
|
-
this.
|
|
44845
|
+
this.points.push(point5);
|
|
44999
44846
|
}
|
|
44847
|
+
this.updateGeometry();
|
|
45000
44848
|
}
|
|
45001
|
-
|
|
45002
|
-
this.
|
|
44849
|
+
setId(id) {
|
|
44850
|
+
this.id = id;
|
|
44851
|
+
this.transformation.setId(id);
|
|
44852
|
+
this.linkTo.setId(id);
|
|
44853
|
+
return this;
|
|
45003
44854
|
}
|
|
45004
|
-
|
|
45005
|
-
|
|
45006
|
-
case "Transformation":
|
|
45007
|
-
this.transformation.apply(op);
|
|
45008
|
-
break;
|
|
45009
|
-
case "LinkTo":
|
|
45010
|
-
this.linkTo.apply(op);
|
|
45011
|
-
break;
|
|
45012
|
-
case "Image":
|
|
45013
|
-
if (op.data.base64) {
|
|
45014
|
-
this.image.src = op.data.base64;
|
|
45015
|
-
}
|
|
45016
|
-
this.setStorageLink(op.data.storageLink);
|
|
45017
|
-
this.setDimensions(op.data.imageDimension);
|
|
45018
|
-
this.subject.publish(this);
|
|
45019
|
-
break;
|
|
45020
|
-
}
|
|
44855
|
+
getId() {
|
|
44856
|
+
return this.id;
|
|
45021
44857
|
}
|
|
45022
44858
|
render(context) {
|
|
45023
44859
|
if (this.transformationRenderBlock) {
|
|
@@ -45025,8 +44861,12 @@ class ImageItem extends BaseItem {
|
|
|
45025
44861
|
}
|
|
45026
44862
|
const ctx = context.ctx;
|
|
45027
44863
|
ctx.save();
|
|
44864
|
+
ctx.strokeStyle = this.borderColor;
|
|
44865
|
+
ctx.lineWidth = this.strokeWidth;
|
|
44866
|
+
ctx.lineCap = "round";
|
|
44867
|
+
ctx.setLineDash(this.linePattern);
|
|
45028
44868
|
this.transformation.matrix.applyToContext(ctx);
|
|
45029
|
-
ctx.
|
|
44869
|
+
ctx.stroke(this.path2d.nativePath);
|
|
45030
44870
|
ctx.restore();
|
|
45031
44871
|
if (this.getLinkTo()) {
|
|
45032
44872
|
const { top, right } = this.getMbr();
|
|
@@ -45034,26 +44874,61 @@ class ImageItem extends BaseItem {
|
|
|
45034
44874
|
}
|
|
45035
44875
|
}
|
|
45036
44876
|
renderHTML(documentFactory) {
|
|
45037
|
-
const div = documentFactory.createElement("
|
|
44877
|
+
const div = documentFactory.createElement("drawing-item");
|
|
45038
44878
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
45039
|
-
const
|
|
45040
|
-
|
|
44879
|
+
const mbr = this.getMbr();
|
|
44880
|
+
const width2 = mbr.getWidth();
|
|
44881
|
+
const height2 = mbr.getHeight();
|
|
44882
|
+
const unscaledWidth = width2 / scaleX;
|
|
44883
|
+
const unscaledHeight = height2 / scaleY;
|
|
44884
|
+
const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
44885
|
+
svg3.setAttribute("width", `${unscaledWidth}px`);
|
|
44886
|
+
svg3.setAttribute("height", `${unscaledHeight}px`);
|
|
44887
|
+
svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
44888
|
+
svg3.setAttribute("style", "position: absolute; overflow: visible;");
|
|
44889
|
+
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
44890
|
+
pathElement.setAttribute("d", this.getPathData());
|
|
44891
|
+
pathElement.setAttribute("stroke", this.borderColor);
|
|
44892
|
+
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
44893
|
+
pathElement.setAttribute("fill", "none");
|
|
44894
|
+
svg3.appendChild(pathElement);
|
|
44895
|
+
div.appendChild(svg3);
|
|
45041
44896
|
div.id = this.getId();
|
|
45042
|
-
div.style.width =
|
|
45043
|
-
div.style.height =
|
|
45044
|
-
div.style.transformOrigin = "top
|
|
45045
|
-
div.style.transform =
|
|
44897
|
+
div.style.width = unscaledWidth + "px";
|
|
44898
|
+
div.style.height = unscaledHeight + "px";
|
|
44899
|
+
div.style.transformOrigin = "left top";
|
|
44900
|
+
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
45046
44901
|
div.style.position = "absolute";
|
|
45047
|
-
div.style.backgroundSize = "cover";
|
|
45048
44902
|
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
45049
44903
|
if (this.getLinkTo()) {
|
|
45050
44904
|
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
45051
44905
|
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
45052
|
-
translateElementBy(linkElement, (
|
|
44906
|
+
translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
45053
44907
|
div.appendChild(linkElement);
|
|
45054
44908
|
}
|
|
45055
44909
|
return div;
|
|
45056
44910
|
}
|
|
44911
|
+
getPathData() {
|
|
44912
|
+
const points = this.points;
|
|
44913
|
+
if (points.length < 2) {
|
|
44914
|
+
return "";
|
|
44915
|
+
}
|
|
44916
|
+
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
44917
|
+
if (points.length < 3) {
|
|
44918
|
+
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
44919
|
+
} else {
|
|
44920
|
+
let j = 1;
|
|
44921
|
+
for (;j < points.length - 2; j++) {
|
|
44922
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
44923
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
44924
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
44925
|
+
}
|
|
44926
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
44927
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
44928
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
44929
|
+
}
|
|
44930
|
+
return pathData;
|
|
44931
|
+
}
|
|
45057
44932
|
getPath() {
|
|
45058
44933
|
const { left, top, right, bottom } = this.getMbr();
|
|
45059
44934
|
const leftTop = new Point(left, top);
|
|
@@ -45078,27 +44953,162 @@ class ImageItem extends BaseItem {
|
|
|
45078
44953
|
new Point(mbr.right, mbr.top + height2 / 2)
|
|
45079
44954
|
];
|
|
45080
44955
|
}
|
|
44956
|
+
getLines() {
|
|
44957
|
+
return this.lines;
|
|
44958
|
+
}
|
|
45081
44959
|
isClosed() {
|
|
45082
44960
|
return true;
|
|
45083
44961
|
}
|
|
45084
|
-
|
|
45085
|
-
|
|
44962
|
+
isEnclosedOrCrossedBy(rect) {
|
|
44963
|
+
for (const line of this.lines) {
|
|
44964
|
+
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
44965
|
+
return true;
|
|
44966
|
+
}
|
|
44967
|
+
}
|
|
44968
|
+
return false;
|
|
44969
|
+
}
|
|
44970
|
+
emit(operation) {
|
|
44971
|
+
if (this.events) {
|
|
44972
|
+
const command = new DrawingCommand([this], operation);
|
|
44973
|
+
command.apply();
|
|
44974
|
+
this.events.emit(operation, command);
|
|
44975
|
+
} else {
|
|
44976
|
+
this.apply(operation);
|
|
44977
|
+
}
|
|
44978
|
+
}
|
|
44979
|
+
apply(op) {
|
|
44980
|
+
switch (op.class) {
|
|
44981
|
+
case "Drawing":
|
|
44982
|
+
switch (op.method) {
|
|
44983
|
+
case "setStrokeColor":
|
|
44984
|
+
this.borderColor = op.color;
|
|
44985
|
+
break;
|
|
44986
|
+
case "setStrokeWidth":
|
|
44987
|
+
this.strokeWidth = op.width;
|
|
44988
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
44989
|
+
break;
|
|
44990
|
+
case "setStrokeOpacity":
|
|
44991
|
+
this.borderOpacity = op.opacity;
|
|
44992
|
+
break;
|
|
44993
|
+
case "setStrokeStyle":
|
|
44994
|
+
this.borderStyle = op.style;
|
|
44995
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
44996
|
+
break;
|
|
44997
|
+
}
|
|
44998
|
+
this.updateMbr();
|
|
44999
|
+
break;
|
|
45000
|
+
case "Transformation":
|
|
45001
|
+
this.transformation.apply(op);
|
|
45002
|
+
break;
|
|
45003
|
+
case "LinkTo":
|
|
45004
|
+
this.linkTo.apply(op);
|
|
45005
|
+
break;
|
|
45006
|
+
default:
|
|
45007
|
+
return;
|
|
45008
|
+
}
|
|
45009
|
+
this.subject.publish(this);
|
|
45010
|
+
}
|
|
45011
|
+
setStrokeOpacity(opacity) {
|
|
45012
|
+
this.emit({
|
|
45013
|
+
class: "Drawing",
|
|
45014
|
+
method: "setStrokeOpacity",
|
|
45015
|
+
item: [this.id],
|
|
45016
|
+
opacity
|
|
45017
|
+
});
|
|
45018
|
+
return this;
|
|
45019
|
+
}
|
|
45020
|
+
getStrokeOpacity() {
|
|
45021
|
+
return this.borderOpacity;
|
|
45022
|
+
}
|
|
45023
|
+
setBorderStyle(style2) {
|
|
45024
|
+
this.emit({
|
|
45025
|
+
class: "Drawing",
|
|
45026
|
+
method: "setStrokeStyle",
|
|
45027
|
+
item: [this.id],
|
|
45028
|
+
style: style2
|
|
45029
|
+
});
|
|
45030
|
+
return this;
|
|
45031
|
+
}
|
|
45032
|
+
getBorderStyle() {
|
|
45033
|
+
return this.borderStyle;
|
|
45034
|
+
}
|
|
45035
|
+
setStrokeColor(color2) {
|
|
45036
|
+
this.emit({
|
|
45037
|
+
class: "Drawing",
|
|
45038
|
+
method: "setStrokeColor",
|
|
45039
|
+
item: [this.id],
|
|
45040
|
+
color: color2
|
|
45041
|
+
});
|
|
45042
|
+
return this;
|
|
45043
|
+
}
|
|
45044
|
+
getStrokeColor() {
|
|
45045
|
+
return this.borderColor;
|
|
45046
|
+
}
|
|
45047
|
+
setStrokeWidth(width2) {
|
|
45048
|
+
this.emit({
|
|
45049
|
+
class: "Drawing",
|
|
45050
|
+
method: "setStrokeWidth",
|
|
45051
|
+
item: [this.id],
|
|
45052
|
+
width: width2,
|
|
45053
|
+
prevWidth: this.strokeWidth
|
|
45054
|
+
});
|
|
45055
|
+
return this;
|
|
45086
45056
|
}
|
|
45087
45057
|
getLinkTo() {
|
|
45088
45058
|
return this.linkTo.link;
|
|
45089
45059
|
}
|
|
45090
|
-
|
|
45091
|
-
|
|
45092
|
-
linkElem.href = this.storageLink;
|
|
45093
|
-
linkElem.setAttribute("download", "");
|
|
45094
|
-
linkElem.click();
|
|
45060
|
+
getStrokeWidth() {
|
|
45061
|
+
return this.strokeWidth;
|
|
45095
45062
|
}
|
|
45096
|
-
|
|
45097
|
-
|
|
45098
|
-
|
|
45099
|
-
|
|
45063
|
+
getRichText() {
|
|
45064
|
+
return null;
|
|
45065
|
+
}
|
|
45066
|
+
isPointNearLine(point5, threshold = 10) {
|
|
45067
|
+
const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
45068
|
+
const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
45069
|
+
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
45070
|
+
for (let i = 0;i < this.points.length - 1; i++) {
|
|
45071
|
+
const p1 = this.points[i];
|
|
45072
|
+
const p22 = this.points[i + 1];
|
|
45073
|
+
const distance = getPerpendicularDistance(transformedMouse, p1, p22);
|
|
45074
|
+
if (distance < threshold) {
|
|
45075
|
+
return true;
|
|
45076
|
+
}
|
|
45100
45077
|
}
|
|
45101
|
-
|
|
45078
|
+
return false;
|
|
45079
|
+
}
|
|
45080
|
+
}
|
|
45081
|
+
function getPerpendicularDistance(point5, lineStart, lineEnd) {
|
|
45082
|
+
const { x: px, y: py } = point5;
|
|
45083
|
+
const { x: sx, y: sy } = lineStart;
|
|
45084
|
+
const { x: ex, y: ey } = lineEnd;
|
|
45085
|
+
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
45086
|
+
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
45087
|
+
return numerator / denominator;
|
|
45088
|
+
}
|
|
45089
|
+
function douglasPeucker(points, epsilon2) {
|
|
45090
|
+
if (points.length < 3) {
|
|
45091
|
+
return points;
|
|
45092
|
+
}
|
|
45093
|
+
const start = points[0];
|
|
45094
|
+
const end = points[points.length - 1];
|
|
45095
|
+
let maxDistance = 0;
|
|
45096
|
+
let maxIndex = 0;
|
|
45097
|
+
for (let i = 1;i < points.length - 1; i++) {
|
|
45098
|
+
const distance = getPerpendicularDistance(points[i], start, end);
|
|
45099
|
+
if (distance > maxDistance) {
|
|
45100
|
+
maxDistance = distance;
|
|
45101
|
+
maxIndex = i;
|
|
45102
|
+
}
|
|
45103
|
+
}
|
|
45104
|
+
if (maxDistance > epsilon2) {
|
|
45105
|
+
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
45106
|
+
const rightSubPoints = points.slice(maxIndex);
|
|
45107
|
+
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
45108
|
+
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
45109
|
+
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
45110
|
+
} else {
|
|
45111
|
+
return [start, end];
|
|
45102
45112
|
}
|
|
45103
45113
|
}
|
|
45104
45114
|
// src/Items/Group/Group.ts
|