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