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