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/esm/index.js
CHANGED
|
@@ -19486,433 +19486,6 @@ class NoOpCommand {
|
|
|
19486
19486
|
}
|
|
19487
19487
|
}
|
|
19488
19488
|
|
|
19489
|
-
// src/isSafari.ts
|
|
19490
|
-
function isSafari() {
|
|
19491
|
-
if (typeof navigator === "undefined") {
|
|
19492
|
-
return false;
|
|
19493
|
-
}
|
|
19494
|
-
const agent = navigator.userAgent;
|
|
19495
|
-
const vendor = navigator.vendor;
|
|
19496
|
-
const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
19497
|
-
return is;
|
|
19498
|
-
}
|
|
19499
|
-
|
|
19500
|
-
// src/Items/Drawing/Drawing.ts
|
|
19501
|
-
class Drawing extends BaseItem {
|
|
19502
|
-
points;
|
|
19503
|
-
events;
|
|
19504
|
-
itemType = "Drawing";
|
|
19505
|
-
parent = "Board";
|
|
19506
|
-
transformation;
|
|
19507
|
-
path2d = new conf.path2DFactory;
|
|
19508
|
-
subject = new Subject;
|
|
19509
|
-
untransformedMbr = new Mbr;
|
|
19510
|
-
lines = [];
|
|
19511
|
-
linkTo;
|
|
19512
|
-
strokeWidth = 1;
|
|
19513
|
-
borderStyle = "solid";
|
|
19514
|
-
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
19515
|
-
borderOpacity = 1;
|
|
19516
|
-
transformationRenderBlock = undefined;
|
|
19517
|
-
constructor(board, points, events, id = "") {
|
|
19518
|
-
super(board, id);
|
|
19519
|
-
this.points = points;
|
|
19520
|
-
this.events = events;
|
|
19521
|
-
this.transformation = new Transformation(id, events);
|
|
19522
|
-
this.linkTo = new LinkTo(this.id, this.events);
|
|
19523
|
-
this.transformation.subject.subscribe(() => {
|
|
19524
|
-
this.updateMbr();
|
|
19525
|
-
this.updateLines();
|
|
19526
|
-
this.subject.publish(this);
|
|
19527
|
-
});
|
|
19528
|
-
this.linkTo.subject.subscribe(() => {
|
|
19529
|
-
this.updateMbr();
|
|
19530
|
-
this.updateLines();
|
|
19531
|
-
this.subject.publish(this);
|
|
19532
|
-
});
|
|
19533
|
-
this.updateLines();
|
|
19534
|
-
}
|
|
19535
|
-
serialize() {
|
|
19536
|
-
this.optimizePoints();
|
|
19537
|
-
const points = [];
|
|
19538
|
-
for (const point3 of this.points) {
|
|
19539
|
-
points.push({ x: point3.x, y: point3.y });
|
|
19540
|
-
}
|
|
19541
|
-
return {
|
|
19542
|
-
itemType: "Drawing",
|
|
19543
|
-
points,
|
|
19544
|
-
transformation: this.transformation.serialize(),
|
|
19545
|
-
strokeStyle: this.borderColor,
|
|
19546
|
-
strokeWidth: this.strokeWidth,
|
|
19547
|
-
linkTo: this.linkTo.serialize()
|
|
19548
|
-
};
|
|
19549
|
-
}
|
|
19550
|
-
deserialize(data) {
|
|
19551
|
-
this.points = [];
|
|
19552
|
-
for (const point3 of data.points) {
|
|
19553
|
-
this.points.push(new Point(point3.x, point3.y));
|
|
19554
|
-
}
|
|
19555
|
-
this.linkTo.deserialize(data.linkTo);
|
|
19556
|
-
this.optimizePoints();
|
|
19557
|
-
this.transformation.deserialize(data.transformation);
|
|
19558
|
-
this.borderColor = data.strokeStyle;
|
|
19559
|
-
this.strokeWidth = data.strokeWidth;
|
|
19560
|
-
this.updateGeometry();
|
|
19561
|
-
return this;
|
|
19562
|
-
}
|
|
19563
|
-
updateGeometry() {
|
|
19564
|
-
this.updatePath2d();
|
|
19565
|
-
this.updateLines();
|
|
19566
|
-
this.updateMbr();
|
|
19567
|
-
}
|
|
19568
|
-
updateMbr() {
|
|
19569
|
-
const offset = this.getStrokeWidth() / 2;
|
|
19570
|
-
const untransformedMbr = this.untransformedMbr.copy();
|
|
19571
|
-
untransformedMbr.left -= offset;
|
|
19572
|
-
untransformedMbr.top -= offset;
|
|
19573
|
-
untransformedMbr.right += offset;
|
|
19574
|
-
untransformedMbr.bottom += offset;
|
|
19575
|
-
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
19576
|
-
this.left = mbr.left;
|
|
19577
|
-
this.top = mbr.top;
|
|
19578
|
-
this.right = mbr.right;
|
|
19579
|
-
this.bottom = mbr.bottom;
|
|
19580
|
-
}
|
|
19581
|
-
updatePath2d() {
|
|
19582
|
-
this.path2d = new conf.path2DFactory;
|
|
19583
|
-
const context = this.path2d;
|
|
19584
|
-
const points = this.points;
|
|
19585
|
-
if (points.length < 3) {
|
|
19586
|
-
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
19587
|
-
context.closePath();
|
|
19588
|
-
} else {
|
|
19589
|
-
context.moveTo(points[0].x, points[0].y);
|
|
19590
|
-
let j = 1;
|
|
19591
|
-
for (;j < points.length - 2; j++) {
|
|
19592
|
-
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
19593
|
-
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
19594
|
-
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
19595
|
-
}
|
|
19596
|
-
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
19597
|
-
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
19598
|
-
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
19599
|
-
}
|
|
19600
|
-
let left = Number.MAX_SAFE_INTEGER;
|
|
19601
|
-
let right = Number.MIN_SAFE_INTEGER;
|
|
19602
|
-
let top = Number.MAX_SAFE_INTEGER;
|
|
19603
|
-
let bottom = Number.MIN_SAFE_INTEGER;
|
|
19604
|
-
for (const { x, y } of this.points) {
|
|
19605
|
-
if (x < left) {
|
|
19606
|
-
left = x;
|
|
19607
|
-
}
|
|
19608
|
-
if (x > right) {
|
|
19609
|
-
right = x;
|
|
19610
|
-
}
|
|
19611
|
-
if (y < top) {
|
|
19612
|
-
top = y;
|
|
19613
|
-
}
|
|
19614
|
-
if (y > bottom) {
|
|
19615
|
-
bottom = y;
|
|
19616
|
-
}
|
|
19617
|
-
}
|
|
19618
|
-
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
19619
|
-
}
|
|
19620
|
-
updateLines() {
|
|
19621
|
-
this.lines = [];
|
|
19622
|
-
const matrix = this.transformation.matrix;
|
|
19623
|
-
if (this.points.length < 2) {
|
|
19624
|
-
return;
|
|
19625
|
-
}
|
|
19626
|
-
for (let i = 0;i < this.points.length - 2; i++) {
|
|
19627
|
-
const p1 = this.points[i];
|
|
19628
|
-
const p2 = this.points[i + 1];
|
|
19629
|
-
const line = new Line(p1.copy(), p2.copy());
|
|
19630
|
-
line.transform(matrix);
|
|
19631
|
-
this.lines.push(line);
|
|
19632
|
-
}
|
|
19633
|
-
}
|
|
19634
|
-
optimizePoints() {
|
|
19635
|
-
const dp = douglasPeucker(this.points, 1);
|
|
19636
|
-
dp.push(this.points[this.points.length - 1]);
|
|
19637
|
-
this.points = dp;
|
|
19638
|
-
}
|
|
19639
|
-
addPoint(point3) {
|
|
19640
|
-
const previous2 = this.points[this.points.length - 1];
|
|
19641
|
-
if (previous2) {
|
|
19642
|
-
const distance = point3.getDistance(previous2);
|
|
19643
|
-
if (distance >= 2) {
|
|
19644
|
-
this.points.push(point3);
|
|
19645
|
-
}
|
|
19646
|
-
} else {
|
|
19647
|
-
this.points.push(point3);
|
|
19648
|
-
}
|
|
19649
|
-
this.updateGeometry();
|
|
19650
|
-
}
|
|
19651
|
-
setId(id) {
|
|
19652
|
-
this.id = id;
|
|
19653
|
-
this.transformation.setId(id);
|
|
19654
|
-
this.linkTo.setId(id);
|
|
19655
|
-
return this;
|
|
19656
|
-
}
|
|
19657
|
-
getId() {
|
|
19658
|
-
return this.id;
|
|
19659
|
-
}
|
|
19660
|
-
render(context) {
|
|
19661
|
-
if (this.transformationRenderBlock) {
|
|
19662
|
-
return;
|
|
19663
|
-
}
|
|
19664
|
-
const ctx = context.ctx;
|
|
19665
|
-
ctx.save();
|
|
19666
|
-
ctx.strokeStyle = this.borderColor;
|
|
19667
|
-
ctx.lineWidth = this.strokeWidth;
|
|
19668
|
-
ctx.lineCap = "round";
|
|
19669
|
-
ctx.setLineDash(this.linePattern);
|
|
19670
|
-
this.transformation.matrix.applyToContext(ctx);
|
|
19671
|
-
ctx.stroke(this.path2d.nativePath);
|
|
19672
|
-
ctx.restore();
|
|
19673
|
-
if (this.getLinkTo()) {
|
|
19674
|
-
const { top, right } = this.getMbr();
|
|
19675
|
-
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
19676
|
-
}
|
|
19677
|
-
}
|
|
19678
|
-
renderHTML(documentFactory) {
|
|
19679
|
-
const div = documentFactory.createElement("drawing-item");
|
|
19680
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
19681
|
-
const mbr = this.getMbr();
|
|
19682
|
-
const width = mbr.getWidth();
|
|
19683
|
-
const height = mbr.getHeight();
|
|
19684
|
-
const unscaledWidth = width / scaleX;
|
|
19685
|
-
const unscaledHeight = height / scaleY;
|
|
19686
|
-
const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
19687
|
-
svg.setAttribute("width", `${unscaledWidth}px`);
|
|
19688
|
-
svg.setAttribute("height", `${unscaledHeight}px`);
|
|
19689
|
-
svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
19690
|
-
svg.setAttribute("style", "position: absolute; overflow: visible;");
|
|
19691
|
-
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
19692
|
-
pathElement.setAttribute("d", this.getPathData());
|
|
19693
|
-
pathElement.setAttribute("stroke", this.borderColor);
|
|
19694
|
-
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
19695
|
-
pathElement.setAttribute("fill", "none");
|
|
19696
|
-
svg.appendChild(pathElement);
|
|
19697
|
-
div.appendChild(svg);
|
|
19698
|
-
div.id = this.getId();
|
|
19699
|
-
div.style.width = unscaledWidth + "px";
|
|
19700
|
-
div.style.height = unscaledHeight + "px";
|
|
19701
|
-
div.style.transformOrigin = "left top";
|
|
19702
|
-
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
19703
|
-
div.style.position = "absolute";
|
|
19704
|
-
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
19705
|
-
if (this.getLinkTo()) {
|
|
19706
|
-
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
19707
|
-
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
19708
|
-
translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
19709
|
-
div.appendChild(linkElement);
|
|
19710
|
-
}
|
|
19711
|
-
return div;
|
|
19712
|
-
}
|
|
19713
|
-
getPathData() {
|
|
19714
|
-
const points = this.points;
|
|
19715
|
-
if (points.length < 2) {
|
|
19716
|
-
return "";
|
|
19717
|
-
}
|
|
19718
|
-
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
19719
|
-
if (points.length < 3) {
|
|
19720
|
-
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
19721
|
-
} else {
|
|
19722
|
-
let j = 1;
|
|
19723
|
-
for (;j < points.length - 2; j++) {
|
|
19724
|
-
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
19725
|
-
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
19726
|
-
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
19727
|
-
}
|
|
19728
|
-
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
19729
|
-
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
19730
|
-
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
19731
|
-
}
|
|
19732
|
-
return pathData;
|
|
19733
|
-
}
|
|
19734
|
-
getPath() {
|
|
19735
|
-
const { left, top, right, bottom } = this.getMbr();
|
|
19736
|
-
const leftTop = new Point(left, top);
|
|
19737
|
-
const rightTop = new Point(right, top);
|
|
19738
|
-
const rightBottom = new Point(right, bottom);
|
|
19739
|
-
const leftBottom = new Point(left, bottom);
|
|
19740
|
-
return new Path([
|
|
19741
|
-
new Line(leftTop, rightTop),
|
|
19742
|
-
new Line(rightTop, rightBottom),
|
|
19743
|
-
new Line(rightBottom, leftBottom),
|
|
19744
|
-
new Line(leftBottom, leftTop)
|
|
19745
|
-
], true);
|
|
19746
|
-
}
|
|
19747
|
-
getSnapAnchorPoints() {
|
|
19748
|
-
const mbr = this.getMbr();
|
|
19749
|
-
const width = mbr.getWidth();
|
|
19750
|
-
const height = mbr.getHeight();
|
|
19751
|
-
return [
|
|
19752
|
-
new Point(mbr.left + width / 2, mbr.top),
|
|
19753
|
-
new Point(mbr.left + width / 2, mbr.bottom),
|
|
19754
|
-
new Point(mbr.left, mbr.top + height / 2),
|
|
19755
|
-
new Point(mbr.right, mbr.top + height / 2)
|
|
19756
|
-
];
|
|
19757
|
-
}
|
|
19758
|
-
getLines() {
|
|
19759
|
-
return this.lines;
|
|
19760
|
-
}
|
|
19761
|
-
isClosed() {
|
|
19762
|
-
return true;
|
|
19763
|
-
}
|
|
19764
|
-
isEnclosedOrCrossedBy(rect) {
|
|
19765
|
-
for (const line of this.lines) {
|
|
19766
|
-
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
19767
|
-
return true;
|
|
19768
|
-
}
|
|
19769
|
-
}
|
|
19770
|
-
return false;
|
|
19771
|
-
}
|
|
19772
|
-
emit(operation) {
|
|
19773
|
-
if (this.events) {
|
|
19774
|
-
const command = new DrawingCommand([this], operation);
|
|
19775
|
-
command.apply();
|
|
19776
|
-
this.events.emit(operation, command);
|
|
19777
|
-
} else {
|
|
19778
|
-
this.apply(operation);
|
|
19779
|
-
}
|
|
19780
|
-
}
|
|
19781
|
-
apply(op) {
|
|
19782
|
-
switch (op.class) {
|
|
19783
|
-
case "Drawing":
|
|
19784
|
-
switch (op.method) {
|
|
19785
|
-
case "setStrokeColor":
|
|
19786
|
-
this.borderColor = op.color;
|
|
19787
|
-
break;
|
|
19788
|
-
case "setStrokeWidth":
|
|
19789
|
-
this.strokeWidth = op.width;
|
|
19790
|
-
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
19791
|
-
break;
|
|
19792
|
-
case "setStrokeOpacity":
|
|
19793
|
-
this.borderOpacity = op.opacity;
|
|
19794
|
-
break;
|
|
19795
|
-
case "setStrokeStyle":
|
|
19796
|
-
this.borderStyle = op.style;
|
|
19797
|
-
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
19798
|
-
break;
|
|
19799
|
-
}
|
|
19800
|
-
this.updateMbr();
|
|
19801
|
-
break;
|
|
19802
|
-
case "Transformation":
|
|
19803
|
-
this.transformation.apply(op);
|
|
19804
|
-
break;
|
|
19805
|
-
case "LinkTo":
|
|
19806
|
-
this.linkTo.apply(op);
|
|
19807
|
-
break;
|
|
19808
|
-
default:
|
|
19809
|
-
return;
|
|
19810
|
-
}
|
|
19811
|
-
this.subject.publish(this);
|
|
19812
|
-
}
|
|
19813
|
-
setStrokeOpacity(opacity) {
|
|
19814
|
-
this.emit({
|
|
19815
|
-
class: "Drawing",
|
|
19816
|
-
method: "setStrokeOpacity",
|
|
19817
|
-
item: [this.id],
|
|
19818
|
-
opacity
|
|
19819
|
-
});
|
|
19820
|
-
return this;
|
|
19821
|
-
}
|
|
19822
|
-
getStrokeOpacity() {
|
|
19823
|
-
return this.borderOpacity;
|
|
19824
|
-
}
|
|
19825
|
-
setBorderStyle(style) {
|
|
19826
|
-
this.emit({
|
|
19827
|
-
class: "Drawing",
|
|
19828
|
-
method: "setStrokeStyle",
|
|
19829
|
-
item: [this.id],
|
|
19830
|
-
style
|
|
19831
|
-
});
|
|
19832
|
-
return this;
|
|
19833
|
-
}
|
|
19834
|
-
getBorderStyle() {
|
|
19835
|
-
return this.borderStyle;
|
|
19836
|
-
}
|
|
19837
|
-
setStrokeColor(color) {
|
|
19838
|
-
this.emit({
|
|
19839
|
-
class: "Drawing",
|
|
19840
|
-
method: "setStrokeColor",
|
|
19841
|
-
item: [this.id],
|
|
19842
|
-
color
|
|
19843
|
-
});
|
|
19844
|
-
return this;
|
|
19845
|
-
}
|
|
19846
|
-
getStrokeColor() {
|
|
19847
|
-
return this.borderColor;
|
|
19848
|
-
}
|
|
19849
|
-
setStrokeWidth(width) {
|
|
19850
|
-
this.emit({
|
|
19851
|
-
class: "Drawing",
|
|
19852
|
-
method: "setStrokeWidth",
|
|
19853
|
-
item: [this.id],
|
|
19854
|
-
width,
|
|
19855
|
-
prevWidth: this.strokeWidth
|
|
19856
|
-
});
|
|
19857
|
-
return this;
|
|
19858
|
-
}
|
|
19859
|
-
getLinkTo() {
|
|
19860
|
-
return this.linkTo.link;
|
|
19861
|
-
}
|
|
19862
|
-
getStrokeWidth() {
|
|
19863
|
-
return this.strokeWidth;
|
|
19864
|
-
}
|
|
19865
|
-
getRichText() {
|
|
19866
|
-
return null;
|
|
19867
|
-
}
|
|
19868
|
-
isPointNearLine(point3, threshold = 10) {
|
|
19869
|
-
const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
19870
|
-
const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
19871
|
-
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
19872
|
-
for (let i = 0;i < this.points.length - 1; i++) {
|
|
19873
|
-
const p1 = this.points[i];
|
|
19874
|
-
const p2 = this.points[i + 1];
|
|
19875
|
-
const distance = getPerpendicularDistance(transformedMouse, p1, p2);
|
|
19876
|
-
if (distance < threshold) {
|
|
19877
|
-
return true;
|
|
19878
|
-
}
|
|
19879
|
-
}
|
|
19880
|
-
return false;
|
|
19881
|
-
}
|
|
19882
|
-
}
|
|
19883
|
-
function getPerpendicularDistance(point3, lineStart, lineEnd) {
|
|
19884
|
-
const { x: px, y: py } = point3;
|
|
19885
|
-
const { x: sx, y: sy } = lineStart;
|
|
19886
|
-
const { x: ex, y: ey } = lineEnd;
|
|
19887
|
-
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
19888
|
-
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
19889
|
-
return numerator / denominator;
|
|
19890
|
-
}
|
|
19891
|
-
function douglasPeucker(points, epsilon2) {
|
|
19892
|
-
if (points.length < 3) {
|
|
19893
|
-
return points;
|
|
19894
|
-
}
|
|
19895
|
-
const start = points[0];
|
|
19896
|
-
const end = points[points.length - 1];
|
|
19897
|
-
let maxDistance = 0;
|
|
19898
|
-
let maxIndex = 0;
|
|
19899
|
-
for (let i = 1;i < points.length - 1; i++) {
|
|
19900
|
-
const distance = getPerpendicularDistance(points[i], start, end);
|
|
19901
|
-
if (distance > maxDistance) {
|
|
19902
|
-
maxDistance = distance;
|
|
19903
|
-
maxIndex = i;
|
|
19904
|
-
}
|
|
19905
|
-
}
|
|
19906
|
-
if (maxDistance > epsilon2) {
|
|
19907
|
-
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
19908
|
-
const rightSubPoints = points.slice(maxIndex);
|
|
19909
|
-
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
19910
|
-
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
19911
|
-
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
19912
|
-
} else {
|
|
19913
|
-
return [start, end];
|
|
19914
|
-
}
|
|
19915
|
-
}
|
|
19916
19489
|
// src/SpatialIndex/LayeredIndex/Layers.ts
|
|
19917
19490
|
class Layers {
|
|
19918
19491
|
getNewLayer;
|
|
@@ -21147,6 +20720,7 @@ class SpatialIndex {
|
|
|
21147
20720
|
}
|
|
21148
20721
|
});
|
|
21149
20722
|
});
|
|
20723
|
+
console.log([...items, ...children]);
|
|
21150
20724
|
return [...items, ...children];
|
|
21151
20725
|
}
|
|
21152
20726
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21161,6 +20735,7 @@ class SpatialIndex {
|
|
|
21161
20735
|
}
|
|
21162
20736
|
});
|
|
21163
20737
|
});
|
|
20738
|
+
console.log([...items, ...children]);
|
|
21164
20739
|
return [...items, ...children];
|
|
21165
20740
|
}
|
|
21166
20741
|
getUnderPoint(point3, tolerance = 5) {
|
|
@@ -21174,6 +20749,7 @@ class SpatialIndex {
|
|
|
21174
20749
|
}
|
|
21175
20750
|
});
|
|
21176
20751
|
});
|
|
20752
|
+
console.log([...items, ...children]);
|
|
21177
20753
|
return [...items, ...children];
|
|
21178
20754
|
}
|
|
21179
20755
|
getRectsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21188,6 +20764,7 @@ class SpatialIndex {
|
|
|
21188
20764
|
}
|
|
21189
20765
|
});
|
|
21190
20766
|
});
|
|
20767
|
+
console.log([...items, ...children]);
|
|
21191
20768
|
return [...items, ...children];
|
|
21192
20769
|
}
|
|
21193
20770
|
getItemsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21207,9 +20784,11 @@ class SpatialIndex {
|
|
|
21207
20784
|
distance: point3.getDistance(item.getMbr().getCenter())
|
|
21208
20785
|
})).filter(({ distance }) => distance <= maxDistance);
|
|
21209
20786
|
withDistance.sort((a, b) => a.distance - b.distance);
|
|
20787
|
+
console.log(withDistance.slice(0, maxItems).map(({ item }) => item));
|
|
21210
20788
|
return withDistance.slice(0, maxItems).map(({ item }) => item);
|
|
21211
20789
|
}
|
|
21212
20790
|
list() {
|
|
20791
|
+
console.log("list", this.getItemsWithIncludedChildren(this.itemsArray).concat());
|
|
21213
20792
|
return this.getItemsWithIncludedChildren(this.itemsArray).concat();
|
|
21214
20793
|
}
|
|
21215
20794
|
getZIndex(item) {
|
|
@@ -21302,12 +20881,12 @@ class Items {
|
|
|
21302
20881
|
if (enclosed.length === 0) {
|
|
21303
20882
|
enclosed = underPointer;
|
|
21304
20883
|
}
|
|
21305
|
-
if (underPointer.some((item) => item
|
|
20884
|
+
if (underPointer.some((item) => item.itemType === "Drawing")) {
|
|
21306
20885
|
enclosed = [...underPointer, ...enclosed];
|
|
21307
20886
|
}
|
|
21308
20887
|
const { nearest } = enclosed.reduce((acc, item) => {
|
|
21309
20888
|
const area = item.getMbr().getHeight() * item.getMbr().getWidth();
|
|
21310
|
-
if (item
|
|
20889
|
+
if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
|
|
21311
20890
|
return acc;
|
|
21312
20891
|
}
|
|
21313
20892
|
const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
|
|
@@ -21580,6 +21159,7 @@ class SimpleSpatialIndex {
|
|
|
21580
21159
|
items.push(item);
|
|
21581
21160
|
}
|
|
21582
21161
|
});
|
|
21162
|
+
console.log("simple", items);
|
|
21583
21163
|
return items;
|
|
21584
21164
|
}
|
|
21585
21165
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21590,6 +21170,7 @@ class SimpleSpatialIndex {
|
|
|
21590
21170
|
items.push(item);
|
|
21591
21171
|
}
|
|
21592
21172
|
});
|
|
21173
|
+
console.log("simple", items);
|
|
21593
21174
|
return items;
|
|
21594
21175
|
}
|
|
21595
21176
|
getUnderPoint(point3, tolerace = 5) {
|
|
@@ -21599,12 +21180,14 @@ class SimpleSpatialIndex {
|
|
|
21599
21180
|
items.push(item);
|
|
21600
21181
|
}
|
|
21601
21182
|
});
|
|
21183
|
+
console.log("simple", items);
|
|
21602
21184
|
return items;
|
|
21603
21185
|
}
|
|
21604
21186
|
getMbr() {
|
|
21605
21187
|
return this.Mbr;
|
|
21606
21188
|
}
|
|
21607
21189
|
list() {
|
|
21190
|
+
console.log("simple list", this.itemsArray.concat());
|
|
21608
21191
|
return this.itemsArray.concat();
|
|
21609
21192
|
}
|
|
21610
21193
|
getZIndex(item) {
|
|
@@ -42192,202 +41775,455 @@ class Placeholder extends BaseItem {
|
|
|
42192
41775
|
renderHTML(documentFactory) {
|
|
42193
41776
|
return documentFactory.createElement("div");
|
|
42194
41777
|
}
|
|
42195
|
-
getLinkTo() {
|
|
42196
|
-
return;
|
|
41778
|
+
getLinkTo() {
|
|
41779
|
+
return;
|
|
41780
|
+
}
|
|
41781
|
+
getRichText() {
|
|
41782
|
+
return null;
|
|
41783
|
+
}
|
|
41784
|
+
}
|
|
41785
|
+
// src/Items/Image/Image.ts
|
|
41786
|
+
function getPlaceholderImage(board, imageDimension) {
|
|
41787
|
+
const placeholderCanvas = conf.documentFactory.createElement("canvas");
|
|
41788
|
+
const placeholderContext = placeholderCanvas.getContext("2d");
|
|
41789
|
+
const context = new DrawingContext(board.camera, placeholderContext);
|
|
41790
|
+
const placeholder = new Placeholder(board);
|
|
41791
|
+
if (imageDimension) {
|
|
41792
|
+
placeholderCanvas.width = imageDimension.width;
|
|
41793
|
+
placeholderCanvas.height = imageDimension.height;
|
|
41794
|
+
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
41795
|
+
} else {
|
|
41796
|
+
placeholderCanvas.width = 250;
|
|
41797
|
+
placeholderCanvas.height = 50;
|
|
41798
|
+
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
41799
|
+
}
|
|
41800
|
+
const placeholderImage = new Image;
|
|
41801
|
+
placeholderImage.src = placeholderCanvas.toDataURL();
|
|
41802
|
+
return placeholderImage;
|
|
41803
|
+
}
|
|
41804
|
+
|
|
41805
|
+
class ImageItem extends BaseItem {
|
|
41806
|
+
events;
|
|
41807
|
+
itemType = "Image";
|
|
41808
|
+
parent = "Board";
|
|
41809
|
+
image;
|
|
41810
|
+
transformation;
|
|
41811
|
+
linkTo;
|
|
41812
|
+
subject = new Subject;
|
|
41813
|
+
loadCallbacks = [];
|
|
41814
|
+
beforeLoadCallbacks = [];
|
|
41815
|
+
transformationRenderBlock = undefined;
|
|
41816
|
+
storageLink;
|
|
41817
|
+
imageDimension;
|
|
41818
|
+
board;
|
|
41819
|
+
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
41820
|
+
super(board, id);
|
|
41821
|
+
this.events = events;
|
|
41822
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
41823
|
+
this.board = board;
|
|
41824
|
+
this.setStorageLink(storageLink);
|
|
41825
|
+
this.imageDimension = imageDimension;
|
|
41826
|
+
this.transformation = new Transformation(id, events);
|
|
41827
|
+
this.image = new Image;
|
|
41828
|
+
this.image.crossOrigin = "anonymous";
|
|
41829
|
+
this.image.onload = this.onLoad;
|
|
41830
|
+
this.image.onerror = this.onError;
|
|
41831
|
+
if (typeof base64 === "string") {
|
|
41832
|
+
this.image.src = base64;
|
|
41833
|
+
}
|
|
41834
|
+
this.linkTo.subject.subscribe(() => {
|
|
41835
|
+
this.updateMbr();
|
|
41836
|
+
this.subject.publish(this);
|
|
41837
|
+
});
|
|
41838
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
41839
|
+
}
|
|
41840
|
+
setStorageLink(link2) {
|
|
41841
|
+
try {
|
|
41842
|
+
const url = new URL(link2);
|
|
41843
|
+
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
41844
|
+
} catch (_) {}
|
|
41845
|
+
}
|
|
41846
|
+
getStorageId() {
|
|
41847
|
+
return this.storageLink.split("/").pop();
|
|
41848
|
+
}
|
|
41849
|
+
handleError = () => {
|
|
41850
|
+
console.error("Invalid dataUrl or image failed to load.");
|
|
41851
|
+
this.image = getPlaceholderImage(this.board);
|
|
41852
|
+
this.updateMbr();
|
|
41853
|
+
this.subject.publish(this);
|
|
41854
|
+
this.shootLoadCallbacks();
|
|
41855
|
+
};
|
|
41856
|
+
onLoad = async () => {
|
|
41857
|
+
this.shootBeforeLoadCallbacks();
|
|
41858
|
+
this.updateMbr();
|
|
41859
|
+
this.subject.publish(this);
|
|
41860
|
+
this.shootLoadCallbacks();
|
|
41861
|
+
};
|
|
41862
|
+
onError = (_error) => {
|
|
41863
|
+
this.image = getPlaceholderImage(this.board);
|
|
41864
|
+
this.updateMbr();
|
|
41865
|
+
this.subject.publish(this);
|
|
41866
|
+
this.shootLoadCallbacks();
|
|
41867
|
+
};
|
|
41868
|
+
onTransform = () => {
|
|
41869
|
+
this.updateMbr();
|
|
41870
|
+
this.subject.publish(this);
|
|
41871
|
+
};
|
|
41872
|
+
updateMbr() {
|
|
41873
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
41874
|
+
this.left = translateX;
|
|
41875
|
+
this.top = translateY;
|
|
41876
|
+
this.right = this.left + this.image.width * scaleX;
|
|
41877
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
41878
|
+
}
|
|
41879
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
41880
|
+
this.loadCallbacks.push(callback);
|
|
41881
|
+
};
|
|
41882
|
+
doOnceOnLoad = (callback) => {
|
|
41883
|
+
this.loadCallbacks.push(callback);
|
|
41884
|
+
};
|
|
41885
|
+
setId(id) {
|
|
41886
|
+
this.id = id;
|
|
41887
|
+
this.transformation.setId(id);
|
|
41888
|
+
this.linkTo.setId(id);
|
|
41889
|
+
return this;
|
|
41890
|
+
}
|
|
41891
|
+
getId() {
|
|
41892
|
+
return this.id;
|
|
41893
|
+
}
|
|
41894
|
+
serialize() {
|
|
41895
|
+
return {
|
|
41896
|
+
itemType: "Image",
|
|
41897
|
+
storageLink: this.storageLink,
|
|
41898
|
+
imageDimension: this.imageDimension,
|
|
41899
|
+
transformation: this.transformation.serialize(),
|
|
41900
|
+
linkTo: this.linkTo.serialize()
|
|
41901
|
+
};
|
|
41902
|
+
}
|
|
41903
|
+
setCoordinates() {
|
|
41904
|
+
this.left = this.transformation.matrix.translateX;
|
|
41905
|
+
this.top = this.transformation.matrix.translateY;
|
|
41906
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
41907
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
41908
|
+
this.subject.publish(this);
|
|
41909
|
+
}
|
|
41910
|
+
shootBeforeLoadCallbacks() {
|
|
41911
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
41912
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
41913
|
+
}
|
|
41914
|
+
}
|
|
41915
|
+
shootLoadCallbacks() {
|
|
41916
|
+
while (this.loadCallbacks.length > 0) {
|
|
41917
|
+
this.loadCallbacks.shift()(this);
|
|
41918
|
+
}
|
|
41919
|
+
}
|
|
41920
|
+
deserialize(data) {
|
|
41921
|
+
if (data.transformation) {
|
|
41922
|
+
this.transformation.deserialize(data.transformation);
|
|
41923
|
+
}
|
|
41924
|
+
this.linkTo.deserialize(data.linkTo);
|
|
41925
|
+
this.image.onload = () => {
|
|
41926
|
+
this.setCoordinates();
|
|
41927
|
+
this.shootLoadCallbacks();
|
|
41928
|
+
};
|
|
41929
|
+
if (data.storageLink) {
|
|
41930
|
+
this.setStorageLink(data.storageLink);
|
|
41931
|
+
}
|
|
41932
|
+
if (this.image.src) {
|
|
41933
|
+
return this;
|
|
41934
|
+
}
|
|
41935
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
41936
|
+
const storageImage = new Image;
|
|
41937
|
+
storageImage.onload = () => {
|
|
41938
|
+
this.image = storageImage;
|
|
41939
|
+
this.onLoad();
|
|
41940
|
+
};
|
|
41941
|
+
storageImage.onerror = this.onError;
|
|
41942
|
+
storageImage.src = this.storageLink;
|
|
41943
|
+
return this;
|
|
41944
|
+
}
|
|
41945
|
+
emit(operation) {
|
|
41946
|
+
if (this.events) {
|
|
41947
|
+
const command = new ImageCommand([this], operation);
|
|
41948
|
+
command.apply();
|
|
41949
|
+
this.events.emit(operation, command);
|
|
41950
|
+
} else {
|
|
41951
|
+
this.apply(operation);
|
|
41952
|
+
}
|
|
41953
|
+
}
|
|
41954
|
+
setDimensions(dim) {
|
|
41955
|
+
this.imageDimension = dim;
|
|
41956
|
+
}
|
|
41957
|
+
apply(op) {
|
|
41958
|
+
switch (op.class) {
|
|
41959
|
+
case "Transformation":
|
|
41960
|
+
this.transformation.apply(op);
|
|
41961
|
+
break;
|
|
41962
|
+
case "LinkTo":
|
|
41963
|
+
this.linkTo.apply(op);
|
|
41964
|
+
break;
|
|
41965
|
+
case "Image":
|
|
41966
|
+
if (op.data.base64) {
|
|
41967
|
+
this.image.src = op.data.base64;
|
|
41968
|
+
}
|
|
41969
|
+
this.setStorageLink(op.data.storageLink);
|
|
41970
|
+
this.setDimensions(op.data.imageDimension);
|
|
41971
|
+
this.subject.publish(this);
|
|
41972
|
+
break;
|
|
41973
|
+
}
|
|
41974
|
+
}
|
|
41975
|
+
render(context) {
|
|
41976
|
+
if (this.transformationRenderBlock) {
|
|
41977
|
+
return;
|
|
41978
|
+
}
|
|
41979
|
+
const ctx = context.ctx;
|
|
41980
|
+
ctx.save();
|
|
41981
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
41982
|
+
ctx.drawImage(this.image, 0, 0);
|
|
41983
|
+
ctx.restore();
|
|
41984
|
+
if (this.getLinkTo()) {
|
|
41985
|
+
const { top, right } = this.getMbr();
|
|
41986
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
41987
|
+
}
|
|
41988
|
+
}
|
|
41989
|
+
renderHTML(documentFactory) {
|
|
41990
|
+
const div = documentFactory.createElement("image-item");
|
|
41991
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
41992
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
41993
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
41994
|
+
div.id = this.getId();
|
|
41995
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
41996
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
41997
|
+
div.style.transformOrigin = "top left";
|
|
41998
|
+
div.style.transform = transform;
|
|
41999
|
+
div.style.position = "absolute";
|
|
42000
|
+
div.style.backgroundSize = "cover";
|
|
42001
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
42002
|
+
if (this.getLinkTo()) {
|
|
42003
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
42004
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
42005
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
42006
|
+
div.appendChild(linkElement);
|
|
42007
|
+
}
|
|
42008
|
+
return div;
|
|
42009
|
+
}
|
|
42010
|
+
getPath() {
|
|
42011
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
42012
|
+
const leftTop = new Point(left, top);
|
|
42013
|
+
const rightTop = new Point(right, top);
|
|
42014
|
+
const rightBottom = new Point(right, bottom);
|
|
42015
|
+
const leftBottom = new Point(left, bottom);
|
|
42016
|
+
return new Path([
|
|
42017
|
+
new Line(leftTop, rightTop),
|
|
42018
|
+
new Line(rightTop, rightBottom),
|
|
42019
|
+
new Line(rightBottom, leftBottom),
|
|
42020
|
+
new Line(leftBottom, leftTop)
|
|
42021
|
+
], true);
|
|
42022
|
+
}
|
|
42023
|
+
getSnapAnchorPoints() {
|
|
42024
|
+
const mbr = this.getMbr();
|
|
42025
|
+
const width2 = mbr.getWidth();
|
|
42026
|
+
const height2 = mbr.getHeight();
|
|
42027
|
+
return [
|
|
42028
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
42029
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
42030
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
42031
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
42032
|
+
];
|
|
42033
|
+
}
|
|
42034
|
+
isClosed() {
|
|
42035
|
+
return true;
|
|
42197
42036
|
}
|
|
42198
42037
|
getRichText() {
|
|
42199
42038
|
return null;
|
|
42200
42039
|
}
|
|
42040
|
+
getLinkTo() {
|
|
42041
|
+
return this.linkTo.link;
|
|
42042
|
+
}
|
|
42043
|
+
download() {
|
|
42044
|
+
const linkElem = document.createElement("a");
|
|
42045
|
+
linkElem.href = this.storageLink;
|
|
42046
|
+
linkElem.setAttribute("download", "");
|
|
42047
|
+
linkElem.click();
|
|
42048
|
+
}
|
|
42049
|
+
onRemove() {
|
|
42050
|
+
const storageId = this.getStorageId();
|
|
42051
|
+
if (storageId) {
|
|
42052
|
+
conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
|
|
42053
|
+
}
|
|
42054
|
+
super.onRemove();
|
|
42055
|
+
}
|
|
42201
42056
|
}
|
|
42202
|
-
// src/
|
|
42203
|
-
function
|
|
42204
|
-
|
|
42205
|
-
|
|
42206
|
-
const context = new DrawingContext(board.camera, placeholderContext);
|
|
42207
|
-
const placeholder = new Placeholder(board);
|
|
42208
|
-
if (imageDimension) {
|
|
42209
|
-
placeholderCanvas.width = imageDimension.width;
|
|
42210
|
-
placeholderCanvas.height = imageDimension.height;
|
|
42211
|
-
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
42212
|
-
} else {
|
|
42213
|
-
placeholderCanvas.width = 250;
|
|
42214
|
-
placeholderCanvas.height = 50;
|
|
42215
|
-
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
42057
|
+
// src/isSafari.ts
|
|
42058
|
+
function isSafari() {
|
|
42059
|
+
if (typeof navigator === "undefined") {
|
|
42060
|
+
return false;
|
|
42216
42061
|
}
|
|
42217
|
-
const
|
|
42218
|
-
|
|
42219
|
-
|
|
42062
|
+
const agent = navigator.userAgent;
|
|
42063
|
+
const vendor = navigator.vendor;
|
|
42064
|
+
const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
42065
|
+
return is2;
|
|
42220
42066
|
}
|
|
42221
42067
|
|
|
42222
|
-
|
|
42068
|
+
// src/Items/Drawing/Drawing.ts
|
|
42069
|
+
class Drawing extends BaseItem {
|
|
42070
|
+
points;
|
|
42223
42071
|
events;
|
|
42224
|
-
itemType = "
|
|
42072
|
+
itemType = "Drawing";
|
|
42225
42073
|
parent = "Board";
|
|
42226
|
-
image;
|
|
42227
42074
|
transformation;
|
|
42228
|
-
|
|
42075
|
+
path2d = new conf.path2DFactory;
|
|
42229
42076
|
subject = new Subject;
|
|
42230
|
-
|
|
42231
|
-
|
|
42077
|
+
untransformedMbr = new Mbr;
|
|
42078
|
+
lines = [];
|
|
42079
|
+
linkTo;
|
|
42080
|
+
strokeWidth = 1;
|
|
42081
|
+
borderStyle = "solid";
|
|
42082
|
+
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
42083
|
+
borderOpacity = 1;
|
|
42232
42084
|
transformationRenderBlock = undefined;
|
|
42233
|
-
|
|
42234
|
-
imageDimension;
|
|
42235
|
-
board;
|
|
42236
|
-
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
42085
|
+
constructor(board, points, events, id = "") {
|
|
42237
42086
|
super(board, id);
|
|
42087
|
+
this.points = points;
|
|
42238
42088
|
this.events = events;
|
|
42239
|
-
this.linkTo = new LinkTo(this.id, events);
|
|
42240
|
-
this.board = board;
|
|
42241
|
-
this.setStorageLink(storageLink);
|
|
42242
|
-
this.imageDimension = imageDimension;
|
|
42243
42089
|
this.transformation = new Transformation(id, events);
|
|
42244
|
-
this.
|
|
42245
|
-
this.
|
|
42246
|
-
|
|
42247
|
-
|
|
42248
|
-
|
|
42249
|
-
|
|
42250
|
-
}
|
|
42090
|
+
this.linkTo = new LinkTo(this.id, this.events);
|
|
42091
|
+
this.transformation.subject.subscribe(() => {
|
|
42092
|
+
this.updateMbr();
|
|
42093
|
+
this.updateLines();
|
|
42094
|
+
this.subject.publish(this);
|
|
42095
|
+
});
|
|
42251
42096
|
this.linkTo.subject.subscribe(() => {
|
|
42252
42097
|
this.updateMbr();
|
|
42098
|
+
this.updateLines();
|
|
42253
42099
|
this.subject.publish(this);
|
|
42254
42100
|
});
|
|
42255
|
-
this.
|
|
42256
|
-
}
|
|
42257
|
-
setStorageLink(link2) {
|
|
42258
|
-
try {
|
|
42259
|
-
const url = new URL(link2);
|
|
42260
|
-
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
42261
|
-
} catch (_) {}
|
|
42262
|
-
}
|
|
42263
|
-
getStorageId() {
|
|
42264
|
-
return this.storageLink.split("/").pop();
|
|
42265
|
-
}
|
|
42266
|
-
handleError = () => {
|
|
42267
|
-
console.error("Invalid dataUrl or image failed to load.");
|
|
42268
|
-
this.image = getPlaceholderImage(this.board);
|
|
42269
|
-
this.updateMbr();
|
|
42270
|
-
this.subject.publish(this);
|
|
42271
|
-
this.shootLoadCallbacks();
|
|
42272
|
-
};
|
|
42273
|
-
onLoad = async () => {
|
|
42274
|
-
this.shootBeforeLoadCallbacks();
|
|
42275
|
-
this.updateMbr();
|
|
42276
|
-
this.subject.publish(this);
|
|
42277
|
-
this.shootLoadCallbacks();
|
|
42278
|
-
};
|
|
42279
|
-
onError = (_error) => {
|
|
42280
|
-
this.image = getPlaceholderImage(this.board);
|
|
42281
|
-
this.updateMbr();
|
|
42282
|
-
this.subject.publish(this);
|
|
42283
|
-
this.shootLoadCallbacks();
|
|
42284
|
-
};
|
|
42285
|
-
onTransform = () => {
|
|
42286
|
-
this.updateMbr();
|
|
42287
|
-
this.subject.publish(this);
|
|
42288
|
-
};
|
|
42289
|
-
updateMbr() {
|
|
42290
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42291
|
-
this.left = translateX;
|
|
42292
|
-
this.top = translateY;
|
|
42293
|
-
this.right = this.left + this.image.width * scaleX;
|
|
42294
|
-
this.bottom = this.top + this.image.height * scaleY;
|
|
42295
|
-
}
|
|
42296
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
42297
|
-
this.loadCallbacks.push(callback);
|
|
42298
|
-
};
|
|
42299
|
-
doOnceOnLoad = (callback) => {
|
|
42300
|
-
this.loadCallbacks.push(callback);
|
|
42301
|
-
};
|
|
42302
|
-
setId(id) {
|
|
42303
|
-
this.id = id;
|
|
42304
|
-
this.transformation.setId(id);
|
|
42305
|
-
this.linkTo.setId(id);
|
|
42306
|
-
return this;
|
|
42307
|
-
}
|
|
42308
|
-
getId() {
|
|
42309
|
-
return this.id;
|
|
42101
|
+
this.updateLines();
|
|
42310
42102
|
}
|
|
42311
42103
|
serialize() {
|
|
42104
|
+
this.optimizePoints();
|
|
42105
|
+
const points = [];
|
|
42106
|
+
for (const point5 of this.points) {
|
|
42107
|
+
points.push({ x: point5.x, y: point5.y });
|
|
42108
|
+
}
|
|
42312
42109
|
return {
|
|
42313
|
-
itemType: "
|
|
42314
|
-
|
|
42315
|
-
imageDimension: this.imageDimension,
|
|
42110
|
+
itemType: "Drawing",
|
|
42111
|
+
points,
|
|
42316
42112
|
transformation: this.transformation.serialize(),
|
|
42113
|
+
strokeStyle: this.borderColor,
|
|
42114
|
+
strokeWidth: this.strokeWidth,
|
|
42317
42115
|
linkTo: this.linkTo.serialize()
|
|
42318
42116
|
};
|
|
42319
42117
|
}
|
|
42320
|
-
|
|
42321
|
-
this.
|
|
42322
|
-
|
|
42323
|
-
|
|
42324
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
42325
|
-
this.subject.publish(this);
|
|
42326
|
-
}
|
|
42327
|
-
shootBeforeLoadCallbacks() {
|
|
42328
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
42329
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
42118
|
+
deserialize(data) {
|
|
42119
|
+
this.points = [];
|
|
42120
|
+
for (const point5 of data.points) {
|
|
42121
|
+
this.points.push(new Point(point5.x, point5.y));
|
|
42330
42122
|
}
|
|
42123
|
+
this.linkTo.deserialize(data.linkTo);
|
|
42124
|
+
this.optimizePoints();
|
|
42125
|
+
this.transformation.deserialize(data.transformation);
|
|
42126
|
+
this.borderColor = data.strokeStyle;
|
|
42127
|
+
this.strokeWidth = data.strokeWidth;
|
|
42128
|
+
this.updateGeometry();
|
|
42129
|
+
return this;
|
|
42331
42130
|
}
|
|
42332
|
-
|
|
42333
|
-
|
|
42334
|
-
|
|
42335
|
-
|
|
42131
|
+
updateGeometry() {
|
|
42132
|
+
this.updatePath2d();
|
|
42133
|
+
this.updateLines();
|
|
42134
|
+
this.updateMbr();
|
|
42336
42135
|
}
|
|
42337
|
-
|
|
42338
|
-
|
|
42339
|
-
|
|
42136
|
+
updateMbr() {
|
|
42137
|
+
const offset = this.getStrokeWidth() / 2;
|
|
42138
|
+
const untransformedMbr = this.untransformedMbr.copy();
|
|
42139
|
+
untransformedMbr.left -= offset;
|
|
42140
|
+
untransformedMbr.top -= offset;
|
|
42141
|
+
untransformedMbr.right += offset;
|
|
42142
|
+
untransformedMbr.bottom += offset;
|
|
42143
|
+
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
42144
|
+
this.left = mbr.left;
|
|
42145
|
+
this.top = mbr.top;
|
|
42146
|
+
this.right = mbr.right;
|
|
42147
|
+
this.bottom = mbr.bottom;
|
|
42148
|
+
}
|
|
42149
|
+
updatePath2d() {
|
|
42150
|
+
this.path2d = new conf.path2DFactory;
|
|
42151
|
+
const context = this.path2d;
|
|
42152
|
+
const points = this.points;
|
|
42153
|
+
if (points.length < 3) {
|
|
42154
|
+
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
42155
|
+
context.closePath();
|
|
42156
|
+
} else {
|
|
42157
|
+
context.moveTo(points[0].x, points[0].y);
|
|
42158
|
+
let j = 1;
|
|
42159
|
+
for (;j < points.length - 2; j++) {
|
|
42160
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
42161
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
42162
|
+
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
42163
|
+
}
|
|
42164
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
42165
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
42166
|
+
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
42340
42167
|
}
|
|
42341
|
-
|
|
42342
|
-
|
|
42343
|
-
|
|
42344
|
-
|
|
42345
|
-
}
|
|
42346
|
-
|
|
42347
|
-
|
|
42168
|
+
let left = Number.MAX_SAFE_INTEGER;
|
|
42169
|
+
let right = Number.MIN_SAFE_INTEGER;
|
|
42170
|
+
let top = Number.MAX_SAFE_INTEGER;
|
|
42171
|
+
let bottom = Number.MIN_SAFE_INTEGER;
|
|
42172
|
+
for (const { x, y } of this.points) {
|
|
42173
|
+
if (x < left) {
|
|
42174
|
+
left = x;
|
|
42175
|
+
}
|
|
42176
|
+
if (x > right) {
|
|
42177
|
+
right = x;
|
|
42178
|
+
}
|
|
42179
|
+
if (y < top) {
|
|
42180
|
+
top = y;
|
|
42181
|
+
}
|
|
42182
|
+
if (y > bottom) {
|
|
42183
|
+
bottom = y;
|
|
42184
|
+
}
|
|
42348
42185
|
}
|
|
42349
|
-
|
|
42350
|
-
|
|
42186
|
+
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
42187
|
+
}
|
|
42188
|
+
updateLines() {
|
|
42189
|
+
this.lines = [];
|
|
42190
|
+
const matrix = this.transformation.matrix;
|
|
42191
|
+
if (this.points.length < 2) {
|
|
42192
|
+
return;
|
|
42193
|
+
}
|
|
42194
|
+
for (let i = 0;i < this.points.length - 2; i++) {
|
|
42195
|
+
const p1 = this.points[i];
|
|
42196
|
+
const p22 = this.points[i + 1];
|
|
42197
|
+
const line = new Line(p1.copy(), p22.copy());
|
|
42198
|
+
line.transform(matrix);
|
|
42199
|
+
this.lines.push(line);
|
|
42351
42200
|
}
|
|
42352
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
42353
|
-
const storageImage = new Image;
|
|
42354
|
-
storageImage.onload = () => {
|
|
42355
|
-
this.image = storageImage;
|
|
42356
|
-
this.onLoad();
|
|
42357
|
-
};
|
|
42358
|
-
storageImage.onerror = this.onError;
|
|
42359
|
-
storageImage.src = this.storageLink;
|
|
42360
|
-
return this;
|
|
42361
42201
|
}
|
|
42362
|
-
|
|
42363
|
-
|
|
42364
|
-
|
|
42365
|
-
|
|
42366
|
-
|
|
42202
|
+
optimizePoints() {
|
|
42203
|
+
const dp = douglasPeucker(this.points, 1);
|
|
42204
|
+
dp.push(this.points[this.points.length - 1]);
|
|
42205
|
+
this.points = dp;
|
|
42206
|
+
}
|
|
42207
|
+
addPoint(point5) {
|
|
42208
|
+
const previous2 = this.points[this.points.length - 1];
|
|
42209
|
+
if (previous2) {
|
|
42210
|
+
const distance = point5.getDistance(previous2);
|
|
42211
|
+
if (distance >= 2) {
|
|
42212
|
+
this.points.push(point5);
|
|
42213
|
+
}
|
|
42367
42214
|
} else {
|
|
42368
|
-
this.
|
|
42215
|
+
this.points.push(point5);
|
|
42369
42216
|
}
|
|
42217
|
+
this.updateGeometry();
|
|
42370
42218
|
}
|
|
42371
|
-
|
|
42372
|
-
this.
|
|
42219
|
+
setId(id) {
|
|
42220
|
+
this.id = id;
|
|
42221
|
+
this.transformation.setId(id);
|
|
42222
|
+
this.linkTo.setId(id);
|
|
42223
|
+
return this;
|
|
42373
42224
|
}
|
|
42374
|
-
|
|
42375
|
-
|
|
42376
|
-
case "Transformation":
|
|
42377
|
-
this.transformation.apply(op);
|
|
42378
|
-
break;
|
|
42379
|
-
case "LinkTo":
|
|
42380
|
-
this.linkTo.apply(op);
|
|
42381
|
-
break;
|
|
42382
|
-
case "Image":
|
|
42383
|
-
if (op.data.base64) {
|
|
42384
|
-
this.image.src = op.data.base64;
|
|
42385
|
-
}
|
|
42386
|
-
this.setStorageLink(op.data.storageLink);
|
|
42387
|
-
this.setDimensions(op.data.imageDimension);
|
|
42388
|
-
this.subject.publish(this);
|
|
42389
|
-
break;
|
|
42390
|
-
}
|
|
42225
|
+
getId() {
|
|
42226
|
+
return this.id;
|
|
42391
42227
|
}
|
|
42392
42228
|
render(context) {
|
|
42393
42229
|
if (this.transformationRenderBlock) {
|
|
@@ -42395,8 +42231,12 @@ class ImageItem extends BaseItem {
|
|
|
42395
42231
|
}
|
|
42396
42232
|
const ctx = context.ctx;
|
|
42397
42233
|
ctx.save();
|
|
42234
|
+
ctx.strokeStyle = this.borderColor;
|
|
42235
|
+
ctx.lineWidth = this.strokeWidth;
|
|
42236
|
+
ctx.lineCap = "round";
|
|
42237
|
+
ctx.setLineDash(this.linePattern);
|
|
42398
42238
|
this.transformation.matrix.applyToContext(ctx);
|
|
42399
|
-
ctx.
|
|
42239
|
+
ctx.stroke(this.path2d.nativePath);
|
|
42400
42240
|
ctx.restore();
|
|
42401
42241
|
if (this.getLinkTo()) {
|
|
42402
42242
|
const { top, right } = this.getMbr();
|
|
@@ -42404,26 +42244,61 @@ class ImageItem extends BaseItem {
|
|
|
42404
42244
|
}
|
|
42405
42245
|
}
|
|
42406
42246
|
renderHTML(documentFactory) {
|
|
42407
|
-
const div = documentFactory.createElement("
|
|
42247
|
+
const div = documentFactory.createElement("drawing-item");
|
|
42408
42248
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42409
|
-
const
|
|
42410
|
-
|
|
42249
|
+
const mbr = this.getMbr();
|
|
42250
|
+
const width2 = mbr.getWidth();
|
|
42251
|
+
const height2 = mbr.getHeight();
|
|
42252
|
+
const unscaledWidth = width2 / scaleX;
|
|
42253
|
+
const unscaledHeight = height2 / scaleY;
|
|
42254
|
+
const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
42255
|
+
svg3.setAttribute("width", `${unscaledWidth}px`);
|
|
42256
|
+
svg3.setAttribute("height", `${unscaledHeight}px`);
|
|
42257
|
+
svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
42258
|
+
svg3.setAttribute("style", "position: absolute; overflow: visible;");
|
|
42259
|
+
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
42260
|
+
pathElement.setAttribute("d", this.getPathData());
|
|
42261
|
+
pathElement.setAttribute("stroke", this.borderColor);
|
|
42262
|
+
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
42263
|
+
pathElement.setAttribute("fill", "none");
|
|
42264
|
+
svg3.appendChild(pathElement);
|
|
42265
|
+
div.appendChild(svg3);
|
|
42411
42266
|
div.id = this.getId();
|
|
42412
|
-
div.style.width =
|
|
42413
|
-
div.style.height =
|
|
42414
|
-
div.style.transformOrigin = "top
|
|
42415
|
-
div.style.transform =
|
|
42267
|
+
div.style.width = unscaledWidth + "px";
|
|
42268
|
+
div.style.height = unscaledHeight + "px";
|
|
42269
|
+
div.style.transformOrigin = "left top";
|
|
42270
|
+
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42416
42271
|
div.style.position = "absolute";
|
|
42417
|
-
div.style.backgroundSize = "cover";
|
|
42418
42272
|
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
42419
42273
|
if (this.getLinkTo()) {
|
|
42420
42274
|
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
42421
42275
|
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
42422
|
-
translateElementBy(linkElement, (
|
|
42276
|
+
translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
42423
42277
|
div.appendChild(linkElement);
|
|
42424
42278
|
}
|
|
42425
42279
|
return div;
|
|
42426
42280
|
}
|
|
42281
|
+
getPathData() {
|
|
42282
|
+
const points = this.points;
|
|
42283
|
+
if (points.length < 2) {
|
|
42284
|
+
return "";
|
|
42285
|
+
}
|
|
42286
|
+
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
42287
|
+
if (points.length < 3) {
|
|
42288
|
+
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
42289
|
+
} else {
|
|
42290
|
+
let j = 1;
|
|
42291
|
+
for (;j < points.length - 2; j++) {
|
|
42292
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
42293
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
42294
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
42295
|
+
}
|
|
42296
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
42297
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
42298
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
42299
|
+
}
|
|
42300
|
+
return pathData;
|
|
42301
|
+
}
|
|
42427
42302
|
getPath() {
|
|
42428
42303
|
const { left, top, right, bottom } = this.getMbr();
|
|
42429
42304
|
const leftTop = new Point(left, top);
|
|
@@ -42448,27 +42323,162 @@ class ImageItem extends BaseItem {
|
|
|
42448
42323
|
new Point(mbr.right, mbr.top + height2 / 2)
|
|
42449
42324
|
];
|
|
42450
42325
|
}
|
|
42326
|
+
getLines() {
|
|
42327
|
+
return this.lines;
|
|
42328
|
+
}
|
|
42451
42329
|
isClosed() {
|
|
42452
42330
|
return true;
|
|
42453
42331
|
}
|
|
42454
|
-
|
|
42455
|
-
|
|
42332
|
+
isEnclosedOrCrossedBy(rect) {
|
|
42333
|
+
for (const line of this.lines) {
|
|
42334
|
+
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
42335
|
+
return true;
|
|
42336
|
+
}
|
|
42337
|
+
}
|
|
42338
|
+
return false;
|
|
42339
|
+
}
|
|
42340
|
+
emit(operation) {
|
|
42341
|
+
if (this.events) {
|
|
42342
|
+
const command = new DrawingCommand([this], operation);
|
|
42343
|
+
command.apply();
|
|
42344
|
+
this.events.emit(operation, command);
|
|
42345
|
+
} else {
|
|
42346
|
+
this.apply(operation);
|
|
42347
|
+
}
|
|
42348
|
+
}
|
|
42349
|
+
apply(op) {
|
|
42350
|
+
switch (op.class) {
|
|
42351
|
+
case "Drawing":
|
|
42352
|
+
switch (op.method) {
|
|
42353
|
+
case "setStrokeColor":
|
|
42354
|
+
this.borderColor = op.color;
|
|
42355
|
+
break;
|
|
42356
|
+
case "setStrokeWidth":
|
|
42357
|
+
this.strokeWidth = op.width;
|
|
42358
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
42359
|
+
break;
|
|
42360
|
+
case "setStrokeOpacity":
|
|
42361
|
+
this.borderOpacity = op.opacity;
|
|
42362
|
+
break;
|
|
42363
|
+
case "setStrokeStyle":
|
|
42364
|
+
this.borderStyle = op.style;
|
|
42365
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
42366
|
+
break;
|
|
42367
|
+
}
|
|
42368
|
+
this.updateMbr();
|
|
42369
|
+
break;
|
|
42370
|
+
case "Transformation":
|
|
42371
|
+
this.transformation.apply(op);
|
|
42372
|
+
break;
|
|
42373
|
+
case "LinkTo":
|
|
42374
|
+
this.linkTo.apply(op);
|
|
42375
|
+
break;
|
|
42376
|
+
default:
|
|
42377
|
+
return;
|
|
42378
|
+
}
|
|
42379
|
+
this.subject.publish(this);
|
|
42380
|
+
}
|
|
42381
|
+
setStrokeOpacity(opacity) {
|
|
42382
|
+
this.emit({
|
|
42383
|
+
class: "Drawing",
|
|
42384
|
+
method: "setStrokeOpacity",
|
|
42385
|
+
item: [this.id],
|
|
42386
|
+
opacity
|
|
42387
|
+
});
|
|
42388
|
+
return this;
|
|
42389
|
+
}
|
|
42390
|
+
getStrokeOpacity() {
|
|
42391
|
+
return this.borderOpacity;
|
|
42392
|
+
}
|
|
42393
|
+
setBorderStyle(style2) {
|
|
42394
|
+
this.emit({
|
|
42395
|
+
class: "Drawing",
|
|
42396
|
+
method: "setStrokeStyle",
|
|
42397
|
+
item: [this.id],
|
|
42398
|
+
style: style2
|
|
42399
|
+
});
|
|
42400
|
+
return this;
|
|
42401
|
+
}
|
|
42402
|
+
getBorderStyle() {
|
|
42403
|
+
return this.borderStyle;
|
|
42404
|
+
}
|
|
42405
|
+
setStrokeColor(color2) {
|
|
42406
|
+
this.emit({
|
|
42407
|
+
class: "Drawing",
|
|
42408
|
+
method: "setStrokeColor",
|
|
42409
|
+
item: [this.id],
|
|
42410
|
+
color: color2
|
|
42411
|
+
});
|
|
42412
|
+
return this;
|
|
42413
|
+
}
|
|
42414
|
+
getStrokeColor() {
|
|
42415
|
+
return this.borderColor;
|
|
42416
|
+
}
|
|
42417
|
+
setStrokeWidth(width2) {
|
|
42418
|
+
this.emit({
|
|
42419
|
+
class: "Drawing",
|
|
42420
|
+
method: "setStrokeWidth",
|
|
42421
|
+
item: [this.id],
|
|
42422
|
+
width: width2,
|
|
42423
|
+
prevWidth: this.strokeWidth
|
|
42424
|
+
});
|
|
42425
|
+
return this;
|
|
42456
42426
|
}
|
|
42457
42427
|
getLinkTo() {
|
|
42458
42428
|
return this.linkTo.link;
|
|
42459
42429
|
}
|
|
42460
|
-
|
|
42461
|
-
|
|
42462
|
-
linkElem.href = this.storageLink;
|
|
42463
|
-
linkElem.setAttribute("download", "");
|
|
42464
|
-
linkElem.click();
|
|
42430
|
+
getStrokeWidth() {
|
|
42431
|
+
return this.strokeWidth;
|
|
42465
42432
|
}
|
|
42466
|
-
|
|
42467
|
-
|
|
42468
|
-
|
|
42469
|
-
|
|
42433
|
+
getRichText() {
|
|
42434
|
+
return null;
|
|
42435
|
+
}
|
|
42436
|
+
isPointNearLine(point5, threshold = 10) {
|
|
42437
|
+
const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
42438
|
+
const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
42439
|
+
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
42440
|
+
for (let i = 0;i < this.points.length - 1; i++) {
|
|
42441
|
+
const p1 = this.points[i];
|
|
42442
|
+
const p22 = this.points[i + 1];
|
|
42443
|
+
const distance = getPerpendicularDistance(transformedMouse, p1, p22);
|
|
42444
|
+
if (distance < threshold) {
|
|
42445
|
+
return true;
|
|
42446
|
+
}
|
|
42470
42447
|
}
|
|
42471
|
-
|
|
42448
|
+
return false;
|
|
42449
|
+
}
|
|
42450
|
+
}
|
|
42451
|
+
function getPerpendicularDistance(point5, lineStart, lineEnd) {
|
|
42452
|
+
const { x: px, y: py } = point5;
|
|
42453
|
+
const { x: sx, y: sy } = lineStart;
|
|
42454
|
+
const { x: ex, y: ey } = lineEnd;
|
|
42455
|
+
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
42456
|
+
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
42457
|
+
return numerator / denominator;
|
|
42458
|
+
}
|
|
42459
|
+
function douglasPeucker(points, epsilon2) {
|
|
42460
|
+
if (points.length < 3) {
|
|
42461
|
+
return points;
|
|
42462
|
+
}
|
|
42463
|
+
const start = points[0];
|
|
42464
|
+
const end = points[points.length - 1];
|
|
42465
|
+
let maxDistance = 0;
|
|
42466
|
+
let maxIndex = 0;
|
|
42467
|
+
for (let i = 1;i < points.length - 1; i++) {
|
|
42468
|
+
const distance = getPerpendicularDistance(points[i], start, end);
|
|
42469
|
+
if (distance > maxDistance) {
|
|
42470
|
+
maxDistance = distance;
|
|
42471
|
+
maxIndex = i;
|
|
42472
|
+
}
|
|
42473
|
+
}
|
|
42474
|
+
if (maxDistance > epsilon2) {
|
|
42475
|
+
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
42476
|
+
const rightSubPoints = points.slice(maxIndex);
|
|
42477
|
+
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
42478
|
+
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
42479
|
+
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
42480
|
+
} else {
|
|
42481
|
+
return [start, end];
|
|
42472
42482
|
}
|
|
42473
42483
|
}
|
|
42474
42484
|
// src/Items/Group/Group.ts
|