microboard-temp 0.4.41 → 0.4.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/browser.js +619 -609
- package/dist/cjs/index.js +619 -609
- package/dist/cjs/node.js +619 -609
- package/dist/esm/browser.js +619 -609
- package/dist/esm/index.js +619 -609
- package/dist/esm/node.js +619 -609
- package/package.json +1 -1
package/dist/cjs/browser.js
CHANGED
|
@@ -19643,433 +19643,6 @@ class NoOpCommand {
|
|
|
19643
19643
|
}
|
|
19644
19644
|
}
|
|
19645
19645
|
|
|
19646
|
-
// src/isSafari.ts
|
|
19647
|
-
function isSafari() {
|
|
19648
|
-
if (typeof navigator === "undefined") {
|
|
19649
|
-
return false;
|
|
19650
|
-
}
|
|
19651
|
-
const agent = navigator.userAgent;
|
|
19652
|
-
const vendor = navigator.vendor;
|
|
19653
|
-
const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
19654
|
-
return is;
|
|
19655
|
-
}
|
|
19656
|
-
|
|
19657
|
-
// src/Items/Drawing/Drawing.ts
|
|
19658
|
-
class Drawing extends BaseItem {
|
|
19659
|
-
points;
|
|
19660
|
-
events;
|
|
19661
|
-
itemType = "Drawing";
|
|
19662
|
-
parent = "Board";
|
|
19663
|
-
transformation;
|
|
19664
|
-
path2d = new conf.path2DFactory;
|
|
19665
|
-
subject = new Subject;
|
|
19666
|
-
untransformedMbr = new Mbr;
|
|
19667
|
-
lines = [];
|
|
19668
|
-
linkTo;
|
|
19669
|
-
strokeWidth = 1;
|
|
19670
|
-
borderStyle = "solid";
|
|
19671
|
-
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
19672
|
-
borderOpacity = 1;
|
|
19673
|
-
transformationRenderBlock = undefined;
|
|
19674
|
-
constructor(board, points, events, id = "") {
|
|
19675
|
-
super(board, id);
|
|
19676
|
-
this.points = points;
|
|
19677
|
-
this.events = events;
|
|
19678
|
-
this.transformation = new Transformation(id, events);
|
|
19679
|
-
this.linkTo = new LinkTo(this.id, this.events);
|
|
19680
|
-
this.transformation.subject.subscribe(() => {
|
|
19681
|
-
this.updateMbr();
|
|
19682
|
-
this.updateLines();
|
|
19683
|
-
this.subject.publish(this);
|
|
19684
|
-
});
|
|
19685
|
-
this.linkTo.subject.subscribe(() => {
|
|
19686
|
-
this.updateMbr();
|
|
19687
|
-
this.updateLines();
|
|
19688
|
-
this.subject.publish(this);
|
|
19689
|
-
});
|
|
19690
|
-
this.updateLines();
|
|
19691
|
-
}
|
|
19692
|
-
serialize() {
|
|
19693
|
-
this.optimizePoints();
|
|
19694
|
-
const points = [];
|
|
19695
|
-
for (const point3 of this.points) {
|
|
19696
|
-
points.push({ x: point3.x, y: point3.y });
|
|
19697
|
-
}
|
|
19698
|
-
return {
|
|
19699
|
-
itemType: "Drawing",
|
|
19700
|
-
points,
|
|
19701
|
-
transformation: this.transformation.serialize(),
|
|
19702
|
-
strokeStyle: this.borderColor,
|
|
19703
|
-
strokeWidth: this.strokeWidth,
|
|
19704
|
-
linkTo: this.linkTo.serialize()
|
|
19705
|
-
};
|
|
19706
|
-
}
|
|
19707
|
-
deserialize(data) {
|
|
19708
|
-
this.points = [];
|
|
19709
|
-
for (const point3 of data.points) {
|
|
19710
|
-
this.points.push(new Point(point3.x, point3.y));
|
|
19711
|
-
}
|
|
19712
|
-
this.linkTo.deserialize(data.linkTo);
|
|
19713
|
-
this.optimizePoints();
|
|
19714
|
-
this.transformation.deserialize(data.transformation);
|
|
19715
|
-
this.borderColor = data.strokeStyle;
|
|
19716
|
-
this.strokeWidth = data.strokeWidth;
|
|
19717
|
-
this.updateGeometry();
|
|
19718
|
-
return this;
|
|
19719
|
-
}
|
|
19720
|
-
updateGeometry() {
|
|
19721
|
-
this.updatePath2d();
|
|
19722
|
-
this.updateLines();
|
|
19723
|
-
this.updateMbr();
|
|
19724
|
-
}
|
|
19725
|
-
updateMbr() {
|
|
19726
|
-
const offset = this.getStrokeWidth() / 2;
|
|
19727
|
-
const untransformedMbr = this.untransformedMbr.copy();
|
|
19728
|
-
untransformedMbr.left -= offset;
|
|
19729
|
-
untransformedMbr.top -= offset;
|
|
19730
|
-
untransformedMbr.right += offset;
|
|
19731
|
-
untransformedMbr.bottom += offset;
|
|
19732
|
-
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
19733
|
-
this.left = mbr.left;
|
|
19734
|
-
this.top = mbr.top;
|
|
19735
|
-
this.right = mbr.right;
|
|
19736
|
-
this.bottom = mbr.bottom;
|
|
19737
|
-
}
|
|
19738
|
-
updatePath2d() {
|
|
19739
|
-
this.path2d = new conf.path2DFactory;
|
|
19740
|
-
const context = this.path2d;
|
|
19741
|
-
const points = this.points;
|
|
19742
|
-
if (points.length < 3) {
|
|
19743
|
-
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
19744
|
-
context.closePath();
|
|
19745
|
-
} else {
|
|
19746
|
-
context.moveTo(points[0].x, points[0].y);
|
|
19747
|
-
let j = 1;
|
|
19748
|
-
for (;j < points.length - 2; j++) {
|
|
19749
|
-
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
19750
|
-
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
19751
|
-
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
19752
|
-
}
|
|
19753
|
-
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
19754
|
-
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
19755
|
-
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
19756
|
-
}
|
|
19757
|
-
let left = Number.MAX_SAFE_INTEGER;
|
|
19758
|
-
let right = Number.MIN_SAFE_INTEGER;
|
|
19759
|
-
let top = Number.MAX_SAFE_INTEGER;
|
|
19760
|
-
let bottom = Number.MIN_SAFE_INTEGER;
|
|
19761
|
-
for (const { x, y } of this.points) {
|
|
19762
|
-
if (x < left) {
|
|
19763
|
-
left = x;
|
|
19764
|
-
}
|
|
19765
|
-
if (x > right) {
|
|
19766
|
-
right = x;
|
|
19767
|
-
}
|
|
19768
|
-
if (y < top) {
|
|
19769
|
-
top = y;
|
|
19770
|
-
}
|
|
19771
|
-
if (y > bottom) {
|
|
19772
|
-
bottom = y;
|
|
19773
|
-
}
|
|
19774
|
-
}
|
|
19775
|
-
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
19776
|
-
}
|
|
19777
|
-
updateLines() {
|
|
19778
|
-
this.lines = [];
|
|
19779
|
-
const matrix = this.transformation.matrix;
|
|
19780
|
-
if (this.points.length < 2) {
|
|
19781
|
-
return;
|
|
19782
|
-
}
|
|
19783
|
-
for (let i = 0;i < this.points.length - 2; i++) {
|
|
19784
|
-
const p1 = this.points[i];
|
|
19785
|
-
const p2 = this.points[i + 1];
|
|
19786
|
-
const line = new Line(p1.copy(), p2.copy());
|
|
19787
|
-
line.transform(matrix);
|
|
19788
|
-
this.lines.push(line);
|
|
19789
|
-
}
|
|
19790
|
-
}
|
|
19791
|
-
optimizePoints() {
|
|
19792
|
-
const dp = douglasPeucker(this.points, 1);
|
|
19793
|
-
dp.push(this.points[this.points.length - 1]);
|
|
19794
|
-
this.points = dp;
|
|
19795
|
-
}
|
|
19796
|
-
addPoint(point3) {
|
|
19797
|
-
const previous2 = this.points[this.points.length - 1];
|
|
19798
|
-
if (previous2) {
|
|
19799
|
-
const distance = point3.getDistance(previous2);
|
|
19800
|
-
if (distance >= 2) {
|
|
19801
|
-
this.points.push(point3);
|
|
19802
|
-
}
|
|
19803
|
-
} else {
|
|
19804
|
-
this.points.push(point3);
|
|
19805
|
-
}
|
|
19806
|
-
this.updateGeometry();
|
|
19807
|
-
}
|
|
19808
|
-
setId(id) {
|
|
19809
|
-
this.id = id;
|
|
19810
|
-
this.transformation.setId(id);
|
|
19811
|
-
this.linkTo.setId(id);
|
|
19812
|
-
return this;
|
|
19813
|
-
}
|
|
19814
|
-
getId() {
|
|
19815
|
-
return this.id;
|
|
19816
|
-
}
|
|
19817
|
-
render(context) {
|
|
19818
|
-
if (this.transformationRenderBlock) {
|
|
19819
|
-
return;
|
|
19820
|
-
}
|
|
19821
|
-
const ctx = context.ctx;
|
|
19822
|
-
ctx.save();
|
|
19823
|
-
ctx.strokeStyle = this.borderColor;
|
|
19824
|
-
ctx.lineWidth = this.strokeWidth;
|
|
19825
|
-
ctx.lineCap = "round";
|
|
19826
|
-
ctx.setLineDash(this.linePattern);
|
|
19827
|
-
this.transformation.matrix.applyToContext(ctx);
|
|
19828
|
-
ctx.stroke(this.path2d.nativePath);
|
|
19829
|
-
ctx.restore();
|
|
19830
|
-
if (this.getLinkTo()) {
|
|
19831
|
-
const { top, right } = this.getMbr();
|
|
19832
|
-
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
19833
|
-
}
|
|
19834
|
-
}
|
|
19835
|
-
renderHTML(documentFactory) {
|
|
19836
|
-
const div = documentFactory.createElement("drawing-item");
|
|
19837
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
19838
|
-
const mbr = this.getMbr();
|
|
19839
|
-
const width = mbr.getWidth();
|
|
19840
|
-
const height = mbr.getHeight();
|
|
19841
|
-
const unscaledWidth = width / scaleX;
|
|
19842
|
-
const unscaledHeight = height / scaleY;
|
|
19843
|
-
const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
19844
|
-
svg.setAttribute("width", `${unscaledWidth}px`);
|
|
19845
|
-
svg.setAttribute("height", `${unscaledHeight}px`);
|
|
19846
|
-
svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
19847
|
-
svg.setAttribute("style", "position: absolute; overflow: visible;");
|
|
19848
|
-
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
19849
|
-
pathElement.setAttribute("d", this.getPathData());
|
|
19850
|
-
pathElement.setAttribute("stroke", this.borderColor);
|
|
19851
|
-
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
19852
|
-
pathElement.setAttribute("fill", "none");
|
|
19853
|
-
svg.appendChild(pathElement);
|
|
19854
|
-
div.appendChild(svg);
|
|
19855
|
-
div.id = this.getId();
|
|
19856
|
-
div.style.width = unscaledWidth + "px";
|
|
19857
|
-
div.style.height = unscaledHeight + "px";
|
|
19858
|
-
div.style.transformOrigin = "left top";
|
|
19859
|
-
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
19860
|
-
div.style.position = "absolute";
|
|
19861
|
-
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
19862
|
-
if (this.getLinkTo()) {
|
|
19863
|
-
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
19864
|
-
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
19865
|
-
translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
19866
|
-
div.appendChild(linkElement);
|
|
19867
|
-
}
|
|
19868
|
-
return div;
|
|
19869
|
-
}
|
|
19870
|
-
getPathData() {
|
|
19871
|
-
const points = this.points;
|
|
19872
|
-
if (points.length < 2) {
|
|
19873
|
-
return "";
|
|
19874
|
-
}
|
|
19875
|
-
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
19876
|
-
if (points.length < 3) {
|
|
19877
|
-
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
19878
|
-
} else {
|
|
19879
|
-
let j = 1;
|
|
19880
|
-
for (;j < points.length - 2; j++) {
|
|
19881
|
-
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
19882
|
-
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
19883
|
-
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
19884
|
-
}
|
|
19885
|
-
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
19886
|
-
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
19887
|
-
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
19888
|
-
}
|
|
19889
|
-
return pathData;
|
|
19890
|
-
}
|
|
19891
|
-
getPath() {
|
|
19892
|
-
const { left, top, right, bottom } = this.getMbr();
|
|
19893
|
-
const leftTop = new Point(left, top);
|
|
19894
|
-
const rightTop = new Point(right, top);
|
|
19895
|
-
const rightBottom = new Point(right, bottom);
|
|
19896
|
-
const leftBottom = new Point(left, bottom);
|
|
19897
|
-
return new Path([
|
|
19898
|
-
new Line(leftTop, rightTop),
|
|
19899
|
-
new Line(rightTop, rightBottom),
|
|
19900
|
-
new Line(rightBottom, leftBottom),
|
|
19901
|
-
new Line(leftBottom, leftTop)
|
|
19902
|
-
], true);
|
|
19903
|
-
}
|
|
19904
|
-
getSnapAnchorPoints() {
|
|
19905
|
-
const mbr = this.getMbr();
|
|
19906
|
-
const width = mbr.getWidth();
|
|
19907
|
-
const height = mbr.getHeight();
|
|
19908
|
-
return [
|
|
19909
|
-
new Point(mbr.left + width / 2, mbr.top),
|
|
19910
|
-
new Point(mbr.left + width / 2, mbr.bottom),
|
|
19911
|
-
new Point(mbr.left, mbr.top + height / 2),
|
|
19912
|
-
new Point(mbr.right, mbr.top + height / 2)
|
|
19913
|
-
];
|
|
19914
|
-
}
|
|
19915
|
-
getLines() {
|
|
19916
|
-
return this.lines;
|
|
19917
|
-
}
|
|
19918
|
-
isClosed() {
|
|
19919
|
-
return true;
|
|
19920
|
-
}
|
|
19921
|
-
isEnclosedOrCrossedBy(rect) {
|
|
19922
|
-
for (const line of this.lines) {
|
|
19923
|
-
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
19924
|
-
return true;
|
|
19925
|
-
}
|
|
19926
|
-
}
|
|
19927
|
-
return false;
|
|
19928
|
-
}
|
|
19929
|
-
emit(operation) {
|
|
19930
|
-
if (this.events) {
|
|
19931
|
-
const command = new DrawingCommand([this], operation);
|
|
19932
|
-
command.apply();
|
|
19933
|
-
this.events.emit(operation, command);
|
|
19934
|
-
} else {
|
|
19935
|
-
this.apply(operation);
|
|
19936
|
-
}
|
|
19937
|
-
}
|
|
19938
|
-
apply(op) {
|
|
19939
|
-
switch (op.class) {
|
|
19940
|
-
case "Drawing":
|
|
19941
|
-
switch (op.method) {
|
|
19942
|
-
case "setStrokeColor":
|
|
19943
|
-
this.borderColor = op.color;
|
|
19944
|
-
break;
|
|
19945
|
-
case "setStrokeWidth":
|
|
19946
|
-
this.strokeWidth = op.width;
|
|
19947
|
-
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
19948
|
-
break;
|
|
19949
|
-
case "setStrokeOpacity":
|
|
19950
|
-
this.borderOpacity = op.opacity;
|
|
19951
|
-
break;
|
|
19952
|
-
case "setStrokeStyle":
|
|
19953
|
-
this.borderStyle = op.style;
|
|
19954
|
-
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
19955
|
-
break;
|
|
19956
|
-
}
|
|
19957
|
-
this.updateMbr();
|
|
19958
|
-
break;
|
|
19959
|
-
case "Transformation":
|
|
19960
|
-
this.transformation.apply(op);
|
|
19961
|
-
break;
|
|
19962
|
-
case "LinkTo":
|
|
19963
|
-
this.linkTo.apply(op);
|
|
19964
|
-
break;
|
|
19965
|
-
default:
|
|
19966
|
-
return;
|
|
19967
|
-
}
|
|
19968
|
-
this.subject.publish(this);
|
|
19969
|
-
}
|
|
19970
|
-
setStrokeOpacity(opacity) {
|
|
19971
|
-
this.emit({
|
|
19972
|
-
class: "Drawing",
|
|
19973
|
-
method: "setStrokeOpacity",
|
|
19974
|
-
item: [this.id],
|
|
19975
|
-
opacity
|
|
19976
|
-
});
|
|
19977
|
-
return this;
|
|
19978
|
-
}
|
|
19979
|
-
getStrokeOpacity() {
|
|
19980
|
-
return this.borderOpacity;
|
|
19981
|
-
}
|
|
19982
|
-
setBorderStyle(style) {
|
|
19983
|
-
this.emit({
|
|
19984
|
-
class: "Drawing",
|
|
19985
|
-
method: "setStrokeStyle",
|
|
19986
|
-
item: [this.id],
|
|
19987
|
-
style
|
|
19988
|
-
});
|
|
19989
|
-
return this;
|
|
19990
|
-
}
|
|
19991
|
-
getBorderStyle() {
|
|
19992
|
-
return this.borderStyle;
|
|
19993
|
-
}
|
|
19994
|
-
setStrokeColor(color) {
|
|
19995
|
-
this.emit({
|
|
19996
|
-
class: "Drawing",
|
|
19997
|
-
method: "setStrokeColor",
|
|
19998
|
-
item: [this.id],
|
|
19999
|
-
color
|
|
20000
|
-
});
|
|
20001
|
-
return this;
|
|
20002
|
-
}
|
|
20003
|
-
getStrokeColor() {
|
|
20004
|
-
return this.borderColor;
|
|
20005
|
-
}
|
|
20006
|
-
setStrokeWidth(width) {
|
|
20007
|
-
this.emit({
|
|
20008
|
-
class: "Drawing",
|
|
20009
|
-
method: "setStrokeWidth",
|
|
20010
|
-
item: [this.id],
|
|
20011
|
-
width,
|
|
20012
|
-
prevWidth: this.strokeWidth
|
|
20013
|
-
});
|
|
20014
|
-
return this;
|
|
20015
|
-
}
|
|
20016
|
-
getLinkTo() {
|
|
20017
|
-
return this.linkTo.link;
|
|
20018
|
-
}
|
|
20019
|
-
getStrokeWidth() {
|
|
20020
|
-
return this.strokeWidth;
|
|
20021
|
-
}
|
|
20022
|
-
getRichText() {
|
|
20023
|
-
return null;
|
|
20024
|
-
}
|
|
20025
|
-
isPointNearLine(point3, threshold = 10) {
|
|
20026
|
-
const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
20027
|
-
const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
20028
|
-
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
20029
|
-
for (let i = 0;i < this.points.length - 1; i++) {
|
|
20030
|
-
const p1 = this.points[i];
|
|
20031
|
-
const p2 = this.points[i + 1];
|
|
20032
|
-
const distance = getPerpendicularDistance(transformedMouse, p1, p2);
|
|
20033
|
-
if (distance < threshold) {
|
|
20034
|
-
return true;
|
|
20035
|
-
}
|
|
20036
|
-
}
|
|
20037
|
-
return false;
|
|
20038
|
-
}
|
|
20039
|
-
}
|
|
20040
|
-
function getPerpendicularDistance(point3, lineStart, lineEnd) {
|
|
20041
|
-
const { x: px, y: py } = point3;
|
|
20042
|
-
const { x: sx, y: sy } = lineStart;
|
|
20043
|
-
const { x: ex, y: ey } = lineEnd;
|
|
20044
|
-
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
20045
|
-
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
20046
|
-
return numerator / denominator;
|
|
20047
|
-
}
|
|
20048
|
-
function douglasPeucker(points, epsilon2) {
|
|
20049
|
-
if (points.length < 3) {
|
|
20050
|
-
return points;
|
|
20051
|
-
}
|
|
20052
|
-
const start = points[0];
|
|
20053
|
-
const end = points[points.length - 1];
|
|
20054
|
-
let maxDistance = 0;
|
|
20055
|
-
let maxIndex = 0;
|
|
20056
|
-
for (let i = 1;i < points.length - 1; i++) {
|
|
20057
|
-
const distance = getPerpendicularDistance(points[i], start, end);
|
|
20058
|
-
if (distance > maxDistance) {
|
|
20059
|
-
maxDistance = distance;
|
|
20060
|
-
maxIndex = i;
|
|
20061
|
-
}
|
|
20062
|
-
}
|
|
20063
|
-
if (maxDistance > epsilon2) {
|
|
20064
|
-
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
20065
|
-
const rightSubPoints = points.slice(maxIndex);
|
|
20066
|
-
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
20067
|
-
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
20068
|
-
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
20069
|
-
} else {
|
|
20070
|
-
return [start, end];
|
|
20071
|
-
}
|
|
20072
|
-
}
|
|
20073
19646
|
// src/SpatialIndex/LayeredIndex/Layers.ts
|
|
20074
19647
|
class Layers {
|
|
20075
19648
|
getNewLayer;
|
|
@@ -21304,6 +20877,7 @@ class SpatialIndex {
|
|
|
21304
20877
|
}
|
|
21305
20878
|
});
|
|
21306
20879
|
});
|
|
20880
|
+
console.log([...items, ...children]);
|
|
21307
20881
|
return [...items, ...children];
|
|
21308
20882
|
}
|
|
21309
20883
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21318,6 +20892,7 @@ class SpatialIndex {
|
|
|
21318
20892
|
}
|
|
21319
20893
|
});
|
|
21320
20894
|
});
|
|
20895
|
+
console.log([...items, ...children]);
|
|
21321
20896
|
return [...items, ...children];
|
|
21322
20897
|
}
|
|
21323
20898
|
getUnderPoint(point3, tolerance = 5) {
|
|
@@ -21331,6 +20906,7 @@ class SpatialIndex {
|
|
|
21331
20906
|
}
|
|
21332
20907
|
});
|
|
21333
20908
|
});
|
|
20909
|
+
console.log([...items, ...children]);
|
|
21334
20910
|
return [...items, ...children];
|
|
21335
20911
|
}
|
|
21336
20912
|
getRectsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21345,6 +20921,7 @@ class SpatialIndex {
|
|
|
21345
20921
|
}
|
|
21346
20922
|
});
|
|
21347
20923
|
});
|
|
20924
|
+
console.log([...items, ...children]);
|
|
21348
20925
|
return [...items, ...children];
|
|
21349
20926
|
}
|
|
21350
20927
|
getItemsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21364,9 +20941,11 @@ class SpatialIndex {
|
|
|
21364
20941
|
distance: point3.getDistance(item.getMbr().getCenter())
|
|
21365
20942
|
})).filter(({ distance }) => distance <= maxDistance);
|
|
21366
20943
|
withDistance.sort((a, b) => a.distance - b.distance);
|
|
20944
|
+
console.log(withDistance.slice(0, maxItems).map(({ item }) => item));
|
|
21367
20945
|
return withDistance.slice(0, maxItems).map(({ item }) => item);
|
|
21368
20946
|
}
|
|
21369
20947
|
list() {
|
|
20948
|
+
console.log("list", this.getItemsWithIncludedChildren(this.itemsArray).concat());
|
|
21370
20949
|
return this.getItemsWithIncludedChildren(this.itemsArray).concat();
|
|
21371
20950
|
}
|
|
21372
20951
|
getZIndex(item) {
|
|
@@ -21459,12 +21038,12 @@ class Items {
|
|
|
21459
21038
|
if (enclosed.length === 0) {
|
|
21460
21039
|
enclosed = underPointer;
|
|
21461
21040
|
}
|
|
21462
|
-
if (underPointer.some((item) => item
|
|
21041
|
+
if (underPointer.some((item) => item.itemType === "Drawing")) {
|
|
21463
21042
|
enclosed = [...underPointer, ...enclosed];
|
|
21464
21043
|
}
|
|
21465
21044
|
const { nearest } = enclosed.reduce((acc, item) => {
|
|
21466
21045
|
const area = item.getMbr().getHeight() * item.getMbr().getWidth();
|
|
21467
|
-
if (item
|
|
21046
|
+
if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
|
|
21468
21047
|
return acc;
|
|
21469
21048
|
}
|
|
21470
21049
|
const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
|
|
@@ -21737,6 +21316,7 @@ class SimpleSpatialIndex {
|
|
|
21737
21316
|
items.push(item);
|
|
21738
21317
|
}
|
|
21739
21318
|
});
|
|
21319
|
+
console.log("simple", items);
|
|
21740
21320
|
return items;
|
|
21741
21321
|
}
|
|
21742
21322
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -21747,6 +21327,7 @@ class SimpleSpatialIndex {
|
|
|
21747
21327
|
items.push(item);
|
|
21748
21328
|
}
|
|
21749
21329
|
});
|
|
21330
|
+
console.log("simple", items);
|
|
21750
21331
|
return items;
|
|
21751
21332
|
}
|
|
21752
21333
|
getUnderPoint(point3, tolerace = 5) {
|
|
@@ -21756,12 +21337,14 @@ class SimpleSpatialIndex {
|
|
|
21756
21337
|
items.push(item);
|
|
21757
21338
|
}
|
|
21758
21339
|
});
|
|
21340
|
+
console.log("simple", items);
|
|
21759
21341
|
return items;
|
|
21760
21342
|
}
|
|
21761
21343
|
getMbr() {
|
|
21762
21344
|
return this.Mbr;
|
|
21763
21345
|
}
|
|
21764
21346
|
list() {
|
|
21347
|
+
console.log("simple list", this.itemsArray.concat());
|
|
21765
21348
|
return this.itemsArray.concat();
|
|
21766
21349
|
}
|
|
21767
21350
|
getZIndex(item) {
|
|
@@ -42349,202 +41932,455 @@ class Placeholder extends BaseItem {
|
|
|
42349
41932
|
renderHTML(documentFactory) {
|
|
42350
41933
|
return documentFactory.createElement("div");
|
|
42351
41934
|
}
|
|
42352
|
-
getLinkTo() {
|
|
42353
|
-
return;
|
|
41935
|
+
getLinkTo() {
|
|
41936
|
+
return;
|
|
41937
|
+
}
|
|
41938
|
+
getRichText() {
|
|
41939
|
+
return null;
|
|
41940
|
+
}
|
|
41941
|
+
}
|
|
41942
|
+
// src/Items/Image/Image.ts
|
|
41943
|
+
function getPlaceholderImage(board, imageDimension) {
|
|
41944
|
+
const placeholderCanvas = conf.documentFactory.createElement("canvas");
|
|
41945
|
+
const placeholderContext = placeholderCanvas.getContext("2d");
|
|
41946
|
+
const context = new DrawingContext(board.camera, placeholderContext);
|
|
41947
|
+
const placeholder = new Placeholder(board);
|
|
41948
|
+
if (imageDimension) {
|
|
41949
|
+
placeholderCanvas.width = imageDimension.width;
|
|
41950
|
+
placeholderCanvas.height = imageDimension.height;
|
|
41951
|
+
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
41952
|
+
} else {
|
|
41953
|
+
placeholderCanvas.width = 250;
|
|
41954
|
+
placeholderCanvas.height = 50;
|
|
41955
|
+
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
41956
|
+
}
|
|
41957
|
+
const placeholderImage = new Image;
|
|
41958
|
+
placeholderImage.src = placeholderCanvas.toDataURL();
|
|
41959
|
+
return placeholderImage;
|
|
41960
|
+
}
|
|
41961
|
+
|
|
41962
|
+
class ImageItem extends BaseItem {
|
|
41963
|
+
events;
|
|
41964
|
+
itemType = "Image";
|
|
41965
|
+
parent = "Board";
|
|
41966
|
+
image;
|
|
41967
|
+
transformation;
|
|
41968
|
+
linkTo;
|
|
41969
|
+
subject = new Subject;
|
|
41970
|
+
loadCallbacks = [];
|
|
41971
|
+
beforeLoadCallbacks = [];
|
|
41972
|
+
transformationRenderBlock = undefined;
|
|
41973
|
+
storageLink;
|
|
41974
|
+
imageDimension;
|
|
41975
|
+
board;
|
|
41976
|
+
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
41977
|
+
super(board, id);
|
|
41978
|
+
this.events = events;
|
|
41979
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
41980
|
+
this.board = board;
|
|
41981
|
+
this.setStorageLink(storageLink);
|
|
41982
|
+
this.imageDimension = imageDimension;
|
|
41983
|
+
this.transformation = new Transformation(id, events);
|
|
41984
|
+
this.image = new Image;
|
|
41985
|
+
this.image.crossOrigin = "anonymous";
|
|
41986
|
+
this.image.onload = this.onLoad;
|
|
41987
|
+
this.image.onerror = this.onError;
|
|
41988
|
+
if (typeof base64 === "string") {
|
|
41989
|
+
this.image.src = base64;
|
|
41990
|
+
}
|
|
41991
|
+
this.linkTo.subject.subscribe(() => {
|
|
41992
|
+
this.updateMbr();
|
|
41993
|
+
this.subject.publish(this);
|
|
41994
|
+
});
|
|
41995
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
41996
|
+
}
|
|
41997
|
+
setStorageLink(link2) {
|
|
41998
|
+
try {
|
|
41999
|
+
const url = new URL(link2);
|
|
42000
|
+
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
42001
|
+
} catch (_) {}
|
|
42002
|
+
}
|
|
42003
|
+
getStorageId() {
|
|
42004
|
+
return this.storageLink.split("/").pop();
|
|
42005
|
+
}
|
|
42006
|
+
handleError = () => {
|
|
42007
|
+
console.error("Invalid dataUrl or image failed to load.");
|
|
42008
|
+
this.image = getPlaceholderImage(this.board);
|
|
42009
|
+
this.updateMbr();
|
|
42010
|
+
this.subject.publish(this);
|
|
42011
|
+
this.shootLoadCallbacks();
|
|
42012
|
+
};
|
|
42013
|
+
onLoad = async () => {
|
|
42014
|
+
this.shootBeforeLoadCallbacks();
|
|
42015
|
+
this.updateMbr();
|
|
42016
|
+
this.subject.publish(this);
|
|
42017
|
+
this.shootLoadCallbacks();
|
|
42018
|
+
};
|
|
42019
|
+
onError = (_error) => {
|
|
42020
|
+
this.image = getPlaceholderImage(this.board);
|
|
42021
|
+
this.updateMbr();
|
|
42022
|
+
this.subject.publish(this);
|
|
42023
|
+
this.shootLoadCallbacks();
|
|
42024
|
+
};
|
|
42025
|
+
onTransform = () => {
|
|
42026
|
+
this.updateMbr();
|
|
42027
|
+
this.subject.publish(this);
|
|
42028
|
+
};
|
|
42029
|
+
updateMbr() {
|
|
42030
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42031
|
+
this.left = translateX;
|
|
42032
|
+
this.top = translateY;
|
|
42033
|
+
this.right = this.left + this.image.width * scaleX;
|
|
42034
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
42035
|
+
}
|
|
42036
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
42037
|
+
this.loadCallbacks.push(callback);
|
|
42038
|
+
};
|
|
42039
|
+
doOnceOnLoad = (callback) => {
|
|
42040
|
+
this.loadCallbacks.push(callback);
|
|
42041
|
+
};
|
|
42042
|
+
setId(id) {
|
|
42043
|
+
this.id = id;
|
|
42044
|
+
this.transformation.setId(id);
|
|
42045
|
+
this.linkTo.setId(id);
|
|
42046
|
+
return this;
|
|
42047
|
+
}
|
|
42048
|
+
getId() {
|
|
42049
|
+
return this.id;
|
|
42050
|
+
}
|
|
42051
|
+
serialize() {
|
|
42052
|
+
return {
|
|
42053
|
+
itemType: "Image",
|
|
42054
|
+
storageLink: this.storageLink,
|
|
42055
|
+
imageDimension: this.imageDimension,
|
|
42056
|
+
transformation: this.transformation.serialize(),
|
|
42057
|
+
linkTo: this.linkTo.serialize()
|
|
42058
|
+
};
|
|
42059
|
+
}
|
|
42060
|
+
setCoordinates() {
|
|
42061
|
+
this.left = this.transformation.matrix.translateX;
|
|
42062
|
+
this.top = this.transformation.matrix.translateY;
|
|
42063
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
42064
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
42065
|
+
this.subject.publish(this);
|
|
42066
|
+
}
|
|
42067
|
+
shootBeforeLoadCallbacks() {
|
|
42068
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
42069
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
42070
|
+
}
|
|
42071
|
+
}
|
|
42072
|
+
shootLoadCallbacks() {
|
|
42073
|
+
while (this.loadCallbacks.length > 0) {
|
|
42074
|
+
this.loadCallbacks.shift()(this);
|
|
42075
|
+
}
|
|
42076
|
+
}
|
|
42077
|
+
deserialize(data) {
|
|
42078
|
+
if (data.transformation) {
|
|
42079
|
+
this.transformation.deserialize(data.transformation);
|
|
42080
|
+
}
|
|
42081
|
+
this.linkTo.deserialize(data.linkTo);
|
|
42082
|
+
this.image.onload = () => {
|
|
42083
|
+
this.setCoordinates();
|
|
42084
|
+
this.shootLoadCallbacks();
|
|
42085
|
+
};
|
|
42086
|
+
if (data.storageLink) {
|
|
42087
|
+
this.setStorageLink(data.storageLink);
|
|
42088
|
+
}
|
|
42089
|
+
if (this.image.src) {
|
|
42090
|
+
return this;
|
|
42091
|
+
}
|
|
42092
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
42093
|
+
const storageImage = new Image;
|
|
42094
|
+
storageImage.onload = () => {
|
|
42095
|
+
this.image = storageImage;
|
|
42096
|
+
this.onLoad();
|
|
42097
|
+
};
|
|
42098
|
+
storageImage.onerror = this.onError;
|
|
42099
|
+
storageImage.src = this.storageLink;
|
|
42100
|
+
return this;
|
|
42101
|
+
}
|
|
42102
|
+
emit(operation) {
|
|
42103
|
+
if (this.events) {
|
|
42104
|
+
const command = new ImageCommand([this], operation);
|
|
42105
|
+
command.apply();
|
|
42106
|
+
this.events.emit(operation, command);
|
|
42107
|
+
} else {
|
|
42108
|
+
this.apply(operation);
|
|
42109
|
+
}
|
|
42110
|
+
}
|
|
42111
|
+
setDimensions(dim) {
|
|
42112
|
+
this.imageDimension = dim;
|
|
42113
|
+
}
|
|
42114
|
+
apply(op) {
|
|
42115
|
+
switch (op.class) {
|
|
42116
|
+
case "Transformation":
|
|
42117
|
+
this.transformation.apply(op);
|
|
42118
|
+
break;
|
|
42119
|
+
case "LinkTo":
|
|
42120
|
+
this.linkTo.apply(op);
|
|
42121
|
+
break;
|
|
42122
|
+
case "Image":
|
|
42123
|
+
if (op.data.base64) {
|
|
42124
|
+
this.image.src = op.data.base64;
|
|
42125
|
+
}
|
|
42126
|
+
this.setStorageLink(op.data.storageLink);
|
|
42127
|
+
this.setDimensions(op.data.imageDimension);
|
|
42128
|
+
this.subject.publish(this);
|
|
42129
|
+
break;
|
|
42130
|
+
}
|
|
42131
|
+
}
|
|
42132
|
+
render(context) {
|
|
42133
|
+
if (this.transformationRenderBlock) {
|
|
42134
|
+
return;
|
|
42135
|
+
}
|
|
42136
|
+
const ctx = context.ctx;
|
|
42137
|
+
ctx.save();
|
|
42138
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
42139
|
+
ctx.drawImage(this.image, 0, 0);
|
|
42140
|
+
ctx.restore();
|
|
42141
|
+
if (this.getLinkTo()) {
|
|
42142
|
+
const { top, right } = this.getMbr();
|
|
42143
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
42144
|
+
}
|
|
42145
|
+
}
|
|
42146
|
+
renderHTML(documentFactory) {
|
|
42147
|
+
const div = documentFactory.createElement("image-item");
|
|
42148
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42149
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42150
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
42151
|
+
div.id = this.getId();
|
|
42152
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
42153
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
42154
|
+
div.style.transformOrigin = "top left";
|
|
42155
|
+
div.style.transform = transform;
|
|
42156
|
+
div.style.position = "absolute";
|
|
42157
|
+
div.style.backgroundSize = "cover";
|
|
42158
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
42159
|
+
if (this.getLinkTo()) {
|
|
42160
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
42161
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
42162
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
42163
|
+
div.appendChild(linkElement);
|
|
42164
|
+
}
|
|
42165
|
+
return div;
|
|
42166
|
+
}
|
|
42167
|
+
getPath() {
|
|
42168
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
42169
|
+
const leftTop = new Point(left, top);
|
|
42170
|
+
const rightTop = new Point(right, top);
|
|
42171
|
+
const rightBottom = new Point(right, bottom);
|
|
42172
|
+
const leftBottom = new Point(left, bottom);
|
|
42173
|
+
return new Path([
|
|
42174
|
+
new Line(leftTop, rightTop),
|
|
42175
|
+
new Line(rightTop, rightBottom),
|
|
42176
|
+
new Line(rightBottom, leftBottom),
|
|
42177
|
+
new Line(leftBottom, leftTop)
|
|
42178
|
+
], true);
|
|
42179
|
+
}
|
|
42180
|
+
getSnapAnchorPoints() {
|
|
42181
|
+
const mbr = this.getMbr();
|
|
42182
|
+
const width2 = mbr.getWidth();
|
|
42183
|
+
const height2 = mbr.getHeight();
|
|
42184
|
+
return [
|
|
42185
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
42186
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
42187
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
42188
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
42189
|
+
];
|
|
42190
|
+
}
|
|
42191
|
+
isClosed() {
|
|
42192
|
+
return true;
|
|
42354
42193
|
}
|
|
42355
42194
|
getRichText() {
|
|
42356
42195
|
return null;
|
|
42357
42196
|
}
|
|
42197
|
+
getLinkTo() {
|
|
42198
|
+
return this.linkTo.link;
|
|
42199
|
+
}
|
|
42200
|
+
download() {
|
|
42201
|
+
const linkElem = document.createElement("a");
|
|
42202
|
+
linkElem.href = this.storageLink;
|
|
42203
|
+
linkElem.setAttribute("download", "");
|
|
42204
|
+
linkElem.click();
|
|
42205
|
+
}
|
|
42206
|
+
onRemove() {
|
|
42207
|
+
const storageId = this.getStorageId();
|
|
42208
|
+
if (storageId) {
|
|
42209
|
+
conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
|
|
42210
|
+
}
|
|
42211
|
+
super.onRemove();
|
|
42212
|
+
}
|
|
42358
42213
|
}
|
|
42359
|
-
// src/
|
|
42360
|
-
function
|
|
42361
|
-
|
|
42362
|
-
|
|
42363
|
-
const context = new DrawingContext(board.camera, placeholderContext);
|
|
42364
|
-
const placeholder = new Placeholder(board);
|
|
42365
|
-
if (imageDimension) {
|
|
42366
|
-
placeholderCanvas.width = imageDimension.width;
|
|
42367
|
-
placeholderCanvas.height = imageDimension.height;
|
|
42368
|
-
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
42369
|
-
} else {
|
|
42370
|
-
placeholderCanvas.width = 250;
|
|
42371
|
-
placeholderCanvas.height = 50;
|
|
42372
|
-
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
42214
|
+
// src/isSafari.ts
|
|
42215
|
+
function isSafari() {
|
|
42216
|
+
if (typeof navigator === "undefined") {
|
|
42217
|
+
return false;
|
|
42373
42218
|
}
|
|
42374
|
-
const
|
|
42375
|
-
|
|
42376
|
-
|
|
42219
|
+
const agent = navigator.userAgent;
|
|
42220
|
+
const vendor = navigator.vendor;
|
|
42221
|
+
const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
42222
|
+
return is2;
|
|
42377
42223
|
}
|
|
42378
42224
|
|
|
42379
|
-
|
|
42225
|
+
// src/Items/Drawing/Drawing.ts
|
|
42226
|
+
class Drawing extends BaseItem {
|
|
42227
|
+
points;
|
|
42380
42228
|
events;
|
|
42381
|
-
itemType = "
|
|
42229
|
+
itemType = "Drawing";
|
|
42382
42230
|
parent = "Board";
|
|
42383
|
-
image;
|
|
42384
42231
|
transformation;
|
|
42385
|
-
|
|
42232
|
+
path2d = new conf.path2DFactory;
|
|
42386
42233
|
subject = new Subject;
|
|
42387
|
-
|
|
42388
|
-
|
|
42234
|
+
untransformedMbr = new Mbr;
|
|
42235
|
+
lines = [];
|
|
42236
|
+
linkTo;
|
|
42237
|
+
strokeWidth = 1;
|
|
42238
|
+
borderStyle = "solid";
|
|
42239
|
+
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
42240
|
+
borderOpacity = 1;
|
|
42389
42241
|
transformationRenderBlock = undefined;
|
|
42390
|
-
|
|
42391
|
-
imageDimension;
|
|
42392
|
-
board;
|
|
42393
|
-
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
42242
|
+
constructor(board, points, events, id = "") {
|
|
42394
42243
|
super(board, id);
|
|
42244
|
+
this.points = points;
|
|
42395
42245
|
this.events = events;
|
|
42396
|
-
this.linkTo = new LinkTo(this.id, events);
|
|
42397
|
-
this.board = board;
|
|
42398
|
-
this.setStorageLink(storageLink);
|
|
42399
|
-
this.imageDimension = imageDimension;
|
|
42400
42246
|
this.transformation = new Transformation(id, events);
|
|
42401
|
-
this.
|
|
42402
|
-
this.
|
|
42403
|
-
|
|
42404
|
-
|
|
42405
|
-
|
|
42406
|
-
|
|
42407
|
-
}
|
|
42247
|
+
this.linkTo = new LinkTo(this.id, this.events);
|
|
42248
|
+
this.transformation.subject.subscribe(() => {
|
|
42249
|
+
this.updateMbr();
|
|
42250
|
+
this.updateLines();
|
|
42251
|
+
this.subject.publish(this);
|
|
42252
|
+
});
|
|
42408
42253
|
this.linkTo.subject.subscribe(() => {
|
|
42409
42254
|
this.updateMbr();
|
|
42255
|
+
this.updateLines();
|
|
42410
42256
|
this.subject.publish(this);
|
|
42411
42257
|
});
|
|
42412
|
-
this.
|
|
42413
|
-
}
|
|
42414
|
-
setStorageLink(link2) {
|
|
42415
|
-
try {
|
|
42416
|
-
const url = new URL(link2);
|
|
42417
|
-
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
42418
|
-
} catch (_) {}
|
|
42419
|
-
}
|
|
42420
|
-
getStorageId() {
|
|
42421
|
-
return this.storageLink.split("/").pop();
|
|
42422
|
-
}
|
|
42423
|
-
handleError = () => {
|
|
42424
|
-
console.error("Invalid dataUrl or image failed to load.");
|
|
42425
|
-
this.image = getPlaceholderImage(this.board);
|
|
42426
|
-
this.updateMbr();
|
|
42427
|
-
this.subject.publish(this);
|
|
42428
|
-
this.shootLoadCallbacks();
|
|
42429
|
-
};
|
|
42430
|
-
onLoad = async () => {
|
|
42431
|
-
this.shootBeforeLoadCallbacks();
|
|
42432
|
-
this.updateMbr();
|
|
42433
|
-
this.subject.publish(this);
|
|
42434
|
-
this.shootLoadCallbacks();
|
|
42435
|
-
};
|
|
42436
|
-
onError = (_error) => {
|
|
42437
|
-
this.image = getPlaceholderImage(this.board);
|
|
42438
|
-
this.updateMbr();
|
|
42439
|
-
this.subject.publish(this);
|
|
42440
|
-
this.shootLoadCallbacks();
|
|
42441
|
-
};
|
|
42442
|
-
onTransform = () => {
|
|
42443
|
-
this.updateMbr();
|
|
42444
|
-
this.subject.publish(this);
|
|
42445
|
-
};
|
|
42446
|
-
updateMbr() {
|
|
42447
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42448
|
-
this.left = translateX;
|
|
42449
|
-
this.top = translateY;
|
|
42450
|
-
this.right = this.left + this.image.width * scaleX;
|
|
42451
|
-
this.bottom = this.top + this.image.height * scaleY;
|
|
42452
|
-
}
|
|
42453
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
42454
|
-
this.loadCallbacks.push(callback);
|
|
42455
|
-
};
|
|
42456
|
-
doOnceOnLoad = (callback) => {
|
|
42457
|
-
this.loadCallbacks.push(callback);
|
|
42458
|
-
};
|
|
42459
|
-
setId(id) {
|
|
42460
|
-
this.id = id;
|
|
42461
|
-
this.transformation.setId(id);
|
|
42462
|
-
this.linkTo.setId(id);
|
|
42463
|
-
return this;
|
|
42464
|
-
}
|
|
42465
|
-
getId() {
|
|
42466
|
-
return this.id;
|
|
42258
|
+
this.updateLines();
|
|
42467
42259
|
}
|
|
42468
42260
|
serialize() {
|
|
42261
|
+
this.optimizePoints();
|
|
42262
|
+
const points = [];
|
|
42263
|
+
for (const point5 of this.points) {
|
|
42264
|
+
points.push({ x: point5.x, y: point5.y });
|
|
42265
|
+
}
|
|
42469
42266
|
return {
|
|
42470
|
-
itemType: "
|
|
42471
|
-
|
|
42472
|
-
imageDimension: this.imageDimension,
|
|
42267
|
+
itemType: "Drawing",
|
|
42268
|
+
points,
|
|
42473
42269
|
transformation: this.transformation.serialize(),
|
|
42270
|
+
strokeStyle: this.borderColor,
|
|
42271
|
+
strokeWidth: this.strokeWidth,
|
|
42474
42272
|
linkTo: this.linkTo.serialize()
|
|
42475
42273
|
};
|
|
42476
42274
|
}
|
|
42477
|
-
|
|
42478
|
-
this.
|
|
42479
|
-
|
|
42480
|
-
|
|
42481
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
42482
|
-
this.subject.publish(this);
|
|
42483
|
-
}
|
|
42484
|
-
shootBeforeLoadCallbacks() {
|
|
42485
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
42486
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
42275
|
+
deserialize(data) {
|
|
42276
|
+
this.points = [];
|
|
42277
|
+
for (const point5 of data.points) {
|
|
42278
|
+
this.points.push(new Point(point5.x, point5.y));
|
|
42487
42279
|
}
|
|
42280
|
+
this.linkTo.deserialize(data.linkTo);
|
|
42281
|
+
this.optimizePoints();
|
|
42282
|
+
this.transformation.deserialize(data.transformation);
|
|
42283
|
+
this.borderColor = data.strokeStyle;
|
|
42284
|
+
this.strokeWidth = data.strokeWidth;
|
|
42285
|
+
this.updateGeometry();
|
|
42286
|
+
return this;
|
|
42488
42287
|
}
|
|
42489
|
-
|
|
42490
|
-
|
|
42491
|
-
|
|
42492
|
-
|
|
42288
|
+
updateGeometry() {
|
|
42289
|
+
this.updatePath2d();
|
|
42290
|
+
this.updateLines();
|
|
42291
|
+
this.updateMbr();
|
|
42493
42292
|
}
|
|
42494
|
-
|
|
42495
|
-
|
|
42496
|
-
|
|
42293
|
+
updateMbr() {
|
|
42294
|
+
const offset = this.getStrokeWidth() / 2;
|
|
42295
|
+
const untransformedMbr = this.untransformedMbr.copy();
|
|
42296
|
+
untransformedMbr.left -= offset;
|
|
42297
|
+
untransformedMbr.top -= offset;
|
|
42298
|
+
untransformedMbr.right += offset;
|
|
42299
|
+
untransformedMbr.bottom += offset;
|
|
42300
|
+
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
42301
|
+
this.left = mbr.left;
|
|
42302
|
+
this.top = mbr.top;
|
|
42303
|
+
this.right = mbr.right;
|
|
42304
|
+
this.bottom = mbr.bottom;
|
|
42305
|
+
}
|
|
42306
|
+
updatePath2d() {
|
|
42307
|
+
this.path2d = new conf.path2DFactory;
|
|
42308
|
+
const context = this.path2d;
|
|
42309
|
+
const points = this.points;
|
|
42310
|
+
if (points.length < 3) {
|
|
42311
|
+
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
42312
|
+
context.closePath();
|
|
42313
|
+
} else {
|
|
42314
|
+
context.moveTo(points[0].x, points[0].y);
|
|
42315
|
+
let j = 1;
|
|
42316
|
+
for (;j < points.length - 2; j++) {
|
|
42317
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
42318
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
42319
|
+
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
42320
|
+
}
|
|
42321
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
42322
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
42323
|
+
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
42497
42324
|
}
|
|
42498
|
-
|
|
42499
|
-
|
|
42500
|
-
|
|
42501
|
-
|
|
42502
|
-
}
|
|
42503
|
-
|
|
42504
|
-
|
|
42325
|
+
let left = Number.MAX_SAFE_INTEGER;
|
|
42326
|
+
let right = Number.MIN_SAFE_INTEGER;
|
|
42327
|
+
let top = Number.MAX_SAFE_INTEGER;
|
|
42328
|
+
let bottom = Number.MIN_SAFE_INTEGER;
|
|
42329
|
+
for (const { x, y } of this.points) {
|
|
42330
|
+
if (x < left) {
|
|
42331
|
+
left = x;
|
|
42332
|
+
}
|
|
42333
|
+
if (x > right) {
|
|
42334
|
+
right = x;
|
|
42335
|
+
}
|
|
42336
|
+
if (y < top) {
|
|
42337
|
+
top = y;
|
|
42338
|
+
}
|
|
42339
|
+
if (y > bottom) {
|
|
42340
|
+
bottom = y;
|
|
42341
|
+
}
|
|
42505
42342
|
}
|
|
42506
|
-
|
|
42507
|
-
|
|
42343
|
+
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
42344
|
+
}
|
|
42345
|
+
updateLines() {
|
|
42346
|
+
this.lines = [];
|
|
42347
|
+
const matrix = this.transformation.matrix;
|
|
42348
|
+
if (this.points.length < 2) {
|
|
42349
|
+
return;
|
|
42350
|
+
}
|
|
42351
|
+
for (let i = 0;i < this.points.length - 2; i++) {
|
|
42352
|
+
const p1 = this.points[i];
|
|
42353
|
+
const p22 = this.points[i + 1];
|
|
42354
|
+
const line = new Line(p1.copy(), p22.copy());
|
|
42355
|
+
line.transform(matrix);
|
|
42356
|
+
this.lines.push(line);
|
|
42508
42357
|
}
|
|
42509
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
42510
|
-
const storageImage = new Image;
|
|
42511
|
-
storageImage.onload = () => {
|
|
42512
|
-
this.image = storageImage;
|
|
42513
|
-
this.onLoad();
|
|
42514
|
-
};
|
|
42515
|
-
storageImage.onerror = this.onError;
|
|
42516
|
-
storageImage.src = this.storageLink;
|
|
42517
|
-
return this;
|
|
42518
42358
|
}
|
|
42519
|
-
|
|
42520
|
-
|
|
42521
|
-
|
|
42522
|
-
|
|
42523
|
-
|
|
42359
|
+
optimizePoints() {
|
|
42360
|
+
const dp = douglasPeucker(this.points, 1);
|
|
42361
|
+
dp.push(this.points[this.points.length - 1]);
|
|
42362
|
+
this.points = dp;
|
|
42363
|
+
}
|
|
42364
|
+
addPoint(point5) {
|
|
42365
|
+
const previous2 = this.points[this.points.length - 1];
|
|
42366
|
+
if (previous2) {
|
|
42367
|
+
const distance = point5.getDistance(previous2);
|
|
42368
|
+
if (distance >= 2) {
|
|
42369
|
+
this.points.push(point5);
|
|
42370
|
+
}
|
|
42524
42371
|
} else {
|
|
42525
|
-
this.
|
|
42372
|
+
this.points.push(point5);
|
|
42526
42373
|
}
|
|
42374
|
+
this.updateGeometry();
|
|
42527
42375
|
}
|
|
42528
|
-
|
|
42529
|
-
this.
|
|
42376
|
+
setId(id) {
|
|
42377
|
+
this.id = id;
|
|
42378
|
+
this.transformation.setId(id);
|
|
42379
|
+
this.linkTo.setId(id);
|
|
42380
|
+
return this;
|
|
42530
42381
|
}
|
|
42531
|
-
|
|
42532
|
-
|
|
42533
|
-
case "Transformation":
|
|
42534
|
-
this.transformation.apply(op);
|
|
42535
|
-
break;
|
|
42536
|
-
case "LinkTo":
|
|
42537
|
-
this.linkTo.apply(op);
|
|
42538
|
-
break;
|
|
42539
|
-
case "Image":
|
|
42540
|
-
if (op.data.base64) {
|
|
42541
|
-
this.image.src = op.data.base64;
|
|
42542
|
-
}
|
|
42543
|
-
this.setStorageLink(op.data.storageLink);
|
|
42544
|
-
this.setDimensions(op.data.imageDimension);
|
|
42545
|
-
this.subject.publish(this);
|
|
42546
|
-
break;
|
|
42547
|
-
}
|
|
42382
|
+
getId() {
|
|
42383
|
+
return this.id;
|
|
42548
42384
|
}
|
|
42549
42385
|
render(context) {
|
|
42550
42386
|
if (this.transformationRenderBlock) {
|
|
@@ -42552,8 +42388,12 @@ class ImageItem extends BaseItem {
|
|
|
42552
42388
|
}
|
|
42553
42389
|
const ctx = context.ctx;
|
|
42554
42390
|
ctx.save();
|
|
42391
|
+
ctx.strokeStyle = this.borderColor;
|
|
42392
|
+
ctx.lineWidth = this.strokeWidth;
|
|
42393
|
+
ctx.lineCap = "round";
|
|
42394
|
+
ctx.setLineDash(this.linePattern);
|
|
42555
42395
|
this.transformation.matrix.applyToContext(ctx);
|
|
42556
|
-
ctx.
|
|
42396
|
+
ctx.stroke(this.path2d.nativePath);
|
|
42557
42397
|
ctx.restore();
|
|
42558
42398
|
if (this.getLinkTo()) {
|
|
42559
42399
|
const { top, right } = this.getMbr();
|
|
@@ -42561,26 +42401,61 @@ class ImageItem extends BaseItem {
|
|
|
42561
42401
|
}
|
|
42562
42402
|
}
|
|
42563
42403
|
renderHTML(documentFactory) {
|
|
42564
|
-
const div = documentFactory.createElement("
|
|
42404
|
+
const div = documentFactory.createElement("drawing-item");
|
|
42565
42405
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42566
|
-
const
|
|
42567
|
-
|
|
42406
|
+
const mbr = this.getMbr();
|
|
42407
|
+
const width2 = mbr.getWidth();
|
|
42408
|
+
const height2 = mbr.getHeight();
|
|
42409
|
+
const unscaledWidth = width2 / scaleX;
|
|
42410
|
+
const unscaledHeight = height2 / scaleY;
|
|
42411
|
+
const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
42412
|
+
svg3.setAttribute("width", `${unscaledWidth}px`);
|
|
42413
|
+
svg3.setAttribute("height", `${unscaledHeight}px`);
|
|
42414
|
+
svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
42415
|
+
svg3.setAttribute("style", "position: absolute; overflow: visible;");
|
|
42416
|
+
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
42417
|
+
pathElement.setAttribute("d", this.getPathData());
|
|
42418
|
+
pathElement.setAttribute("stroke", this.borderColor);
|
|
42419
|
+
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
42420
|
+
pathElement.setAttribute("fill", "none");
|
|
42421
|
+
svg3.appendChild(pathElement);
|
|
42422
|
+
div.appendChild(svg3);
|
|
42568
42423
|
div.id = this.getId();
|
|
42569
|
-
div.style.width =
|
|
42570
|
-
div.style.height =
|
|
42571
|
-
div.style.transformOrigin = "top
|
|
42572
|
-
div.style.transform =
|
|
42424
|
+
div.style.width = unscaledWidth + "px";
|
|
42425
|
+
div.style.height = unscaledHeight + "px";
|
|
42426
|
+
div.style.transformOrigin = "left top";
|
|
42427
|
+
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42573
42428
|
div.style.position = "absolute";
|
|
42574
|
-
div.style.backgroundSize = "cover";
|
|
42575
42429
|
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
42576
42430
|
if (this.getLinkTo()) {
|
|
42577
42431
|
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
42578
42432
|
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
42579
|
-
translateElementBy(linkElement, (
|
|
42433
|
+
translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
42580
42434
|
div.appendChild(linkElement);
|
|
42581
42435
|
}
|
|
42582
42436
|
return div;
|
|
42583
42437
|
}
|
|
42438
|
+
getPathData() {
|
|
42439
|
+
const points = this.points;
|
|
42440
|
+
if (points.length < 2) {
|
|
42441
|
+
return "";
|
|
42442
|
+
}
|
|
42443
|
+
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
42444
|
+
if (points.length < 3) {
|
|
42445
|
+
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
42446
|
+
} else {
|
|
42447
|
+
let j = 1;
|
|
42448
|
+
for (;j < points.length - 2; j++) {
|
|
42449
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
42450
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
42451
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
42452
|
+
}
|
|
42453
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
42454
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
42455
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
42456
|
+
}
|
|
42457
|
+
return pathData;
|
|
42458
|
+
}
|
|
42584
42459
|
getPath() {
|
|
42585
42460
|
const { left, top, right, bottom } = this.getMbr();
|
|
42586
42461
|
const leftTop = new Point(left, top);
|
|
@@ -42605,27 +42480,162 @@ class ImageItem extends BaseItem {
|
|
|
42605
42480
|
new Point(mbr.right, mbr.top + height2 / 2)
|
|
42606
42481
|
];
|
|
42607
42482
|
}
|
|
42483
|
+
getLines() {
|
|
42484
|
+
return this.lines;
|
|
42485
|
+
}
|
|
42608
42486
|
isClosed() {
|
|
42609
42487
|
return true;
|
|
42610
42488
|
}
|
|
42611
|
-
|
|
42612
|
-
|
|
42489
|
+
isEnclosedOrCrossedBy(rect) {
|
|
42490
|
+
for (const line of this.lines) {
|
|
42491
|
+
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
42492
|
+
return true;
|
|
42493
|
+
}
|
|
42494
|
+
}
|
|
42495
|
+
return false;
|
|
42496
|
+
}
|
|
42497
|
+
emit(operation) {
|
|
42498
|
+
if (this.events) {
|
|
42499
|
+
const command = new DrawingCommand([this], operation);
|
|
42500
|
+
command.apply();
|
|
42501
|
+
this.events.emit(operation, command);
|
|
42502
|
+
} else {
|
|
42503
|
+
this.apply(operation);
|
|
42504
|
+
}
|
|
42505
|
+
}
|
|
42506
|
+
apply(op) {
|
|
42507
|
+
switch (op.class) {
|
|
42508
|
+
case "Drawing":
|
|
42509
|
+
switch (op.method) {
|
|
42510
|
+
case "setStrokeColor":
|
|
42511
|
+
this.borderColor = op.color;
|
|
42512
|
+
break;
|
|
42513
|
+
case "setStrokeWidth":
|
|
42514
|
+
this.strokeWidth = op.width;
|
|
42515
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
42516
|
+
break;
|
|
42517
|
+
case "setStrokeOpacity":
|
|
42518
|
+
this.borderOpacity = op.opacity;
|
|
42519
|
+
break;
|
|
42520
|
+
case "setStrokeStyle":
|
|
42521
|
+
this.borderStyle = op.style;
|
|
42522
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
42523
|
+
break;
|
|
42524
|
+
}
|
|
42525
|
+
this.updateMbr();
|
|
42526
|
+
break;
|
|
42527
|
+
case "Transformation":
|
|
42528
|
+
this.transformation.apply(op);
|
|
42529
|
+
break;
|
|
42530
|
+
case "LinkTo":
|
|
42531
|
+
this.linkTo.apply(op);
|
|
42532
|
+
break;
|
|
42533
|
+
default:
|
|
42534
|
+
return;
|
|
42535
|
+
}
|
|
42536
|
+
this.subject.publish(this);
|
|
42537
|
+
}
|
|
42538
|
+
setStrokeOpacity(opacity) {
|
|
42539
|
+
this.emit({
|
|
42540
|
+
class: "Drawing",
|
|
42541
|
+
method: "setStrokeOpacity",
|
|
42542
|
+
item: [this.id],
|
|
42543
|
+
opacity
|
|
42544
|
+
});
|
|
42545
|
+
return this;
|
|
42546
|
+
}
|
|
42547
|
+
getStrokeOpacity() {
|
|
42548
|
+
return this.borderOpacity;
|
|
42549
|
+
}
|
|
42550
|
+
setBorderStyle(style2) {
|
|
42551
|
+
this.emit({
|
|
42552
|
+
class: "Drawing",
|
|
42553
|
+
method: "setStrokeStyle",
|
|
42554
|
+
item: [this.id],
|
|
42555
|
+
style: style2
|
|
42556
|
+
});
|
|
42557
|
+
return this;
|
|
42558
|
+
}
|
|
42559
|
+
getBorderStyle() {
|
|
42560
|
+
return this.borderStyle;
|
|
42561
|
+
}
|
|
42562
|
+
setStrokeColor(color2) {
|
|
42563
|
+
this.emit({
|
|
42564
|
+
class: "Drawing",
|
|
42565
|
+
method: "setStrokeColor",
|
|
42566
|
+
item: [this.id],
|
|
42567
|
+
color: color2
|
|
42568
|
+
});
|
|
42569
|
+
return this;
|
|
42570
|
+
}
|
|
42571
|
+
getStrokeColor() {
|
|
42572
|
+
return this.borderColor;
|
|
42573
|
+
}
|
|
42574
|
+
setStrokeWidth(width2) {
|
|
42575
|
+
this.emit({
|
|
42576
|
+
class: "Drawing",
|
|
42577
|
+
method: "setStrokeWidth",
|
|
42578
|
+
item: [this.id],
|
|
42579
|
+
width: width2,
|
|
42580
|
+
prevWidth: this.strokeWidth
|
|
42581
|
+
});
|
|
42582
|
+
return this;
|
|
42613
42583
|
}
|
|
42614
42584
|
getLinkTo() {
|
|
42615
42585
|
return this.linkTo.link;
|
|
42616
42586
|
}
|
|
42617
|
-
|
|
42618
|
-
|
|
42619
|
-
linkElem.href = this.storageLink;
|
|
42620
|
-
linkElem.setAttribute("download", "");
|
|
42621
|
-
linkElem.click();
|
|
42587
|
+
getStrokeWidth() {
|
|
42588
|
+
return this.strokeWidth;
|
|
42622
42589
|
}
|
|
42623
|
-
|
|
42624
|
-
|
|
42625
|
-
|
|
42626
|
-
|
|
42590
|
+
getRichText() {
|
|
42591
|
+
return null;
|
|
42592
|
+
}
|
|
42593
|
+
isPointNearLine(point5, threshold = 10) {
|
|
42594
|
+
const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
42595
|
+
const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
42596
|
+
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
42597
|
+
for (let i = 0;i < this.points.length - 1; i++) {
|
|
42598
|
+
const p1 = this.points[i];
|
|
42599
|
+
const p22 = this.points[i + 1];
|
|
42600
|
+
const distance = getPerpendicularDistance(transformedMouse, p1, p22);
|
|
42601
|
+
if (distance < threshold) {
|
|
42602
|
+
return true;
|
|
42603
|
+
}
|
|
42627
42604
|
}
|
|
42628
|
-
|
|
42605
|
+
return false;
|
|
42606
|
+
}
|
|
42607
|
+
}
|
|
42608
|
+
function getPerpendicularDistance(point5, lineStart, lineEnd) {
|
|
42609
|
+
const { x: px, y: py } = point5;
|
|
42610
|
+
const { x: sx, y: sy } = lineStart;
|
|
42611
|
+
const { x: ex, y: ey } = lineEnd;
|
|
42612
|
+
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
42613
|
+
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
42614
|
+
return numerator / denominator;
|
|
42615
|
+
}
|
|
42616
|
+
function douglasPeucker(points, epsilon2) {
|
|
42617
|
+
if (points.length < 3) {
|
|
42618
|
+
return points;
|
|
42619
|
+
}
|
|
42620
|
+
const start = points[0];
|
|
42621
|
+
const end = points[points.length - 1];
|
|
42622
|
+
let maxDistance = 0;
|
|
42623
|
+
let maxIndex = 0;
|
|
42624
|
+
for (let i = 1;i < points.length - 1; i++) {
|
|
42625
|
+
const distance = getPerpendicularDistance(points[i], start, end);
|
|
42626
|
+
if (distance > maxDistance) {
|
|
42627
|
+
maxDistance = distance;
|
|
42628
|
+
maxIndex = i;
|
|
42629
|
+
}
|
|
42630
|
+
}
|
|
42631
|
+
if (maxDistance > epsilon2) {
|
|
42632
|
+
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
42633
|
+
const rightSubPoints = points.slice(maxIndex);
|
|
42634
|
+
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
42635
|
+
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
42636
|
+
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
42637
|
+
} else {
|
|
42638
|
+
return [start, end];
|
|
42629
42639
|
}
|
|
42630
42640
|
}
|
|
42631
42641
|
// src/Items/Group/Group.ts
|