microboard-temp 0.4.41 → 0.4.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/browser.js +619 -609
- package/dist/cjs/index.js +619 -609
- package/dist/cjs/node.js +619 -609
- package/dist/esm/browser.js +619 -609
- package/dist/esm/index.js +619 -609
- package/dist/esm/node.js +619 -609
- package/package.json +1 -1
package/dist/esm/node.js
CHANGED
|
@@ -22020,433 +22020,6 @@ class NoOpCommand {
|
|
|
22020
22020
|
}
|
|
22021
22021
|
}
|
|
22022
22022
|
|
|
22023
|
-
// src/isSafari.ts
|
|
22024
|
-
function isSafari() {
|
|
22025
|
-
if (typeof navigator === "undefined") {
|
|
22026
|
-
return false;
|
|
22027
|
-
}
|
|
22028
|
-
const agent = navigator.userAgent;
|
|
22029
|
-
const vendor = navigator.vendor;
|
|
22030
|
-
const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
22031
|
-
return is;
|
|
22032
|
-
}
|
|
22033
|
-
|
|
22034
|
-
// src/Items/Drawing/Drawing.ts
|
|
22035
|
-
class Drawing extends BaseItem {
|
|
22036
|
-
points;
|
|
22037
|
-
events;
|
|
22038
|
-
itemType = "Drawing";
|
|
22039
|
-
parent = "Board";
|
|
22040
|
-
transformation;
|
|
22041
|
-
path2d = new conf.path2DFactory;
|
|
22042
|
-
subject = new Subject;
|
|
22043
|
-
untransformedMbr = new Mbr;
|
|
22044
|
-
lines = [];
|
|
22045
|
-
linkTo;
|
|
22046
|
-
strokeWidth = 1;
|
|
22047
|
-
borderStyle = "solid";
|
|
22048
|
-
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
22049
|
-
borderOpacity = 1;
|
|
22050
|
-
transformationRenderBlock = undefined;
|
|
22051
|
-
constructor(board, points, events, id = "") {
|
|
22052
|
-
super(board, id);
|
|
22053
|
-
this.points = points;
|
|
22054
|
-
this.events = events;
|
|
22055
|
-
this.transformation = new Transformation(id, events);
|
|
22056
|
-
this.linkTo = new LinkTo(this.id, this.events);
|
|
22057
|
-
this.transformation.subject.subscribe(() => {
|
|
22058
|
-
this.updateMbr();
|
|
22059
|
-
this.updateLines();
|
|
22060
|
-
this.subject.publish(this);
|
|
22061
|
-
});
|
|
22062
|
-
this.linkTo.subject.subscribe(() => {
|
|
22063
|
-
this.updateMbr();
|
|
22064
|
-
this.updateLines();
|
|
22065
|
-
this.subject.publish(this);
|
|
22066
|
-
});
|
|
22067
|
-
this.updateLines();
|
|
22068
|
-
}
|
|
22069
|
-
serialize() {
|
|
22070
|
-
this.optimizePoints();
|
|
22071
|
-
const points = [];
|
|
22072
|
-
for (const point3 of this.points) {
|
|
22073
|
-
points.push({ x: point3.x, y: point3.y });
|
|
22074
|
-
}
|
|
22075
|
-
return {
|
|
22076
|
-
itemType: "Drawing",
|
|
22077
|
-
points,
|
|
22078
|
-
transformation: this.transformation.serialize(),
|
|
22079
|
-
strokeStyle: this.borderColor,
|
|
22080
|
-
strokeWidth: this.strokeWidth,
|
|
22081
|
-
linkTo: this.linkTo.serialize()
|
|
22082
|
-
};
|
|
22083
|
-
}
|
|
22084
|
-
deserialize(data) {
|
|
22085
|
-
this.points = [];
|
|
22086
|
-
for (const point3 of data.points) {
|
|
22087
|
-
this.points.push(new Point(point3.x, point3.y));
|
|
22088
|
-
}
|
|
22089
|
-
this.linkTo.deserialize(data.linkTo);
|
|
22090
|
-
this.optimizePoints();
|
|
22091
|
-
this.transformation.deserialize(data.transformation);
|
|
22092
|
-
this.borderColor = data.strokeStyle;
|
|
22093
|
-
this.strokeWidth = data.strokeWidth;
|
|
22094
|
-
this.updateGeometry();
|
|
22095
|
-
return this;
|
|
22096
|
-
}
|
|
22097
|
-
updateGeometry() {
|
|
22098
|
-
this.updatePath2d();
|
|
22099
|
-
this.updateLines();
|
|
22100
|
-
this.updateMbr();
|
|
22101
|
-
}
|
|
22102
|
-
updateMbr() {
|
|
22103
|
-
const offset = this.getStrokeWidth() / 2;
|
|
22104
|
-
const untransformedMbr = this.untransformedMbr.copy();
|
|
22105
|
-
untransformedMbr.left -= offset;
|
|
22106
|
-
untransformedMbr.top -= offset;
|
|
22107
|
-
untransformedMbr.right += offset;
|
|
22108
|
-
untransformedMbr.bottom += offset;
|
|
22109
|
-
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
22110
|
-
this.left = mbr.left;
|
|
22111
|
-
this.top = mbr.top;
|
|
22112
|
-
this.right = mbr.right;
|
|
22113
|
-
this.bottom = mbr.bottom;
|
|
22114
|
-
}
|
|
22115
|
-
updatePath2d() {
|
|
22116
|
-
this.path2d = new conf.path2DFactory;
|
|
22117
|
-
const context = this.path2d;
|
|
22118
|
-
const points = this.points;
|
|
22119
|
-
if (points.length < 3) {
|
|
22120
|
-
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
22121
|
-
context.closePath();
|
|
22122
|
-
} else {
|
|
22123
|
-
context.moveTo(points[0].x, points[0].y);
|
|
22124
|
-
let j = 1;
|
|
22125
|
-
for (;j < points.length - 2; j++) {
|
|
22126
|
-
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
22127
|
-
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
22128
|
-
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
22129
|
-
}
|
|
22130
|
-
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
22131
|
-
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
22132
|
-
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
22133
|
-
}
|
|
22134
|
-
let left = Number.MAX_SAFE_INTEGER;
|
|
22135
|
-
let right = Number.MIN_SAFE_INTEGER;
|
|
22136
|
-
let top = Number.MAX_SAFE_INTEGER;
|
|
22137
|
-
let bottom = Number.MIN_SAFE_INTEGER;
|
|
22138
|
-
for (const { x, y } of this.points) {
|
|
22139
|
-
if (x < left) {
|
|
22140
|
-
left = x;
|
|
22141
|
-
}
|
|
22142
|
-
if (x > right) {
|
|
22143
|
-
right = x;
|
|
22144
|
-
}
|
|
22145
|
-
if (y < top) {
|
|
22146
|
-
top = y;
|
|
22147
|
-
}
|
|
22148
|
-
if (y > bottom) {
|
|
22149
|
-
bottom = y;
|
|
22150
|
-
}
|
|
22151
|
-
}
|
|
22152
|
-
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
22153
|
-
}
|
|
22154
|
-
updateLines() {
|
|
22155
|
-
this.lines = [];
|
|
22156
|
-
const matrix = this.transformation.matrix;
|
|
22157
|
-
if (this.points.length < 2) {
|
|
22158
|
-
return;
|
|
22159
|
-
}
|
|
22160
|
-
for (let i = 0;i < this.points.length - 2; i++) {
|
|
22161
|
-
const p1 = this.points[i];
|
|
22162
|
-
const p2 = this.points[i + 1];
|
|
22163
|
-
const line = new Line(p1.copy(), p2.copy());
|
|
22164
|
-
line.transform(matrix);
|
|
22165
|
-
this.lines.push(line);
|
|
22166
|
-
}
|
|
22167
|
-
}
|
|
22168
|
-
optimizePoints() {
|
|
22169
|
-
const dp = douglasPeucker(this.points, 1);
|
|
22170
|
-
dp.push(this.points[this.points.length - 1]);
|
|
22171
|
-
this.points = dp;
|
|
22172
|
-
}
|
|
22173
|
-
addPoint(point3) {
|
|
22174
|
-
const previous2 = this.points[this.points.length - 1];
|
|
22175
|
-
if (previous2) {
|
|
22176
|
-
const distance = point3.getDistance(previous2);
|
|
22177
|
-
if (distance >= 2) {
|
|
22178
|
-
this.points.push(point3);
|
|
22179
|
-
}
|
|
22180
|
-
} else {
|
|
22181
|
-
this.points.push(point3);
|
|
22182
|
-
}
|
|
22183
|
-
this.updateGeometry();
|
|
22184
|
-
}
|
|
22185
|
-
setId(id) {
|
|
22186
|
-
this.id = id;
|
|
22187
|
-
this.transformation.setId(id);
|
|
22188
|
-
this.linkTo.setId(id);
|
|
22189
|
-
return this;
|
|
22190
|
-
}
|
|
22191
|
-
getId() {
|
|
22192
|
-
return this.id;
|
|
22193
|
-
}
|
|
22194
|
-
render(context) {
|
|
22195
|
-
if (this.transformationRenderBlock) {
|
|
22196
|
-
return;
|
|
22197
|
-
}
|
|
22198
|
-
const ctx = context.ctx;
|
|
22199
|
-
ctx.save();
|
|
22200
|
-
ctx.strokeStyle = this.borderColor;
|
|
22201
|
-
ctx.lineWidth = this.strokeWidth;
|
|
22202
|
-
ctx.lineCap = "round";
|
|
22203
|
-
ctx.setLineDash(this.linePattern);
|
|
22204
|
-
this.transformation.matrix.applyToContext(ctx);
|
|
22205
|
-
ctx.stroke(this.path2d.nativePath);
|
|
22206
|
-
ctx.restore();
|
|
22207
|
-
if (this.getLinkTo()) {
|
|
22208
|
-
const { top, right } = this.getMbr();
|
|
22209
|
-
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
22210
|
-
}
|
|
22211
|
-
}
|
|
22212
|
-
renderHTML(documentFactory) {
|
|
22213
|
-
const div = documentFactory.createElement("drawing-item");
|
|
22214
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
22215
|
-
const mbr = this.getMbr();
|
|
22216
|
-
const width = mbr.getWidth();
|
|
22217
|
-
const height = mbr.getHeight();
|
|
22218
|
-
const unscaledWidth = width / scaleX;
|
|
22219
|
-
const unscaledHeight = height / scaleY;
|
|
22220
|
-
const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
22221
|
-
svg.setAttribute("width", `${unscaledWidth}px`);
|
|
22222
|
-
svg.setAttribute("height", `${unscaledHeight}px`);
|
|
22223
|
-
svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
22224
|
-
svg.setAttribute("style", "position: absolute; overflow: visible;");
|
|
22225
|
-
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
22226
|
-
pathElement.setAttribute("d", this.getPathData());
|
|
22227
|
-
pathElement.setAttribute("stroke", this.borderColor);
|
|
22228
|
-
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
22229
|
-
pathElement.setAttribute("fill", "none");
|
|
22230
|
-
svg.appendChild(pathElement);
|
|
22231
|
-
div.appendChild(svg);
|
|
22232
|
-
div.id = this.getId();
|
|
22233
|
-
div.style.width = unscaledWidth + "px";
|
|
22234
|
-
div.style.height = unscaledHeight + "px";
|
|
22235
|
-
div.style.transformOrigin = "left top";
|
|
22236
|
-
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
22237
|
-
div.style.position = "absolute";
|
|
22238
|
-
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
22239
|
-
if (this.getLinkTo()) {
|
|
22240
|
-
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
22241
|
-
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
22242
|
-
translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
22243
|
-
div.appendChild(linkElement);
|
|
22244
|
-
}
|
|
22245
|
-
return div;
|
|
22246
|
-
}
|
|
22247
|
-
getPathData() {
|
|
22248
|
-
const points = this.points;
|
|
22249
|
-
if (points.length < 2) {
|
|
22250
|
-
return "";
|
|
22251
|
-
}
|
|
22252
|
-
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
22253
|
-
if (points.length < 3) {
|
|
22254
|
-
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
22255
|
-
} else {
|
|
22256
|
-
let j = 1;
|
|
22257
|
-
for (;j < points.length - 2; j++) {
|
|
22258
|
-
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
22259
|
-
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
22260
|
-
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
22261
|
-
}
|
|
22262
|
-
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
22263
|
-
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
22264
|
-
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
22265
|
-
}
|
|
22266
|
-
return pathData;
|
|
22267
|
-
}
|
|
22268
|
-
getPath() {
|
|
22269
|
-
const { left, top, right, bottom } = this.getMbr();
|
|
22270
|
-
const leftTop = new Point(left, top);
|
|
22271
|
-
const rightTop = new Point(right, top);
|
|
22272
|
-
const rightBottom = new Point(right, bottom);
|
|
22273
|
-
const leftBottom = new Point(left, bottom);
|
|
22274
|
-
return new Path([
|
|
22275
|
-
new Line(leftTop, rightTop),
|
|
22276
|
-
new Line(rightTop, rightBottom),
|
|
22277
|
-
new Line(rightBottom, leftBottom),
|
|
22278
|
-
new Line(leftBottom, leftTop)
|
|
22279
|
-
], true);
|
|
22280
|
-
}
|
|
22281
|
-
getSnapAnchorPoints() {
|
|
22282
|
-
const mbr = this.getMbr();
|
|
22283
|
-
const width = mbr.getWidth();
|
|
22284
|
-
const height = mbr.getHeight();
|
|
22285
|
-
return [
|
|
22286
|
-
new Point(mbr.left + width / 2, mbr.top),
|
|
22287
|
-
new Point(mbr.left + width / 2, mbr.bottom),
|
|
22288
|
-
new Point(mbr.left, mbr.top + height / 2),
|
|
22289
|
-
new Point(mbr.right, mbr.top + height / 2)
|
|
22290
|
-
];
|
|
22291
|
-
}
|
|
22292
|
-
getLines() {
|
|
22293
|
-
return this.lines;
|
|
22294
|
-
}
|
|
22295
|
-
isClosed() {
|
|
22296
|
-
return true;
|
|
22297
|
-
}
|
|
22298
|
-
isEnclosedOrCrossedBy(rect) {
|
|
22299
|
-
for (const line of this.lines) {
|
|
22300
|
-
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
22301
|
-
return true;
|
|
22302
|
-
}
|
|
22303
|
-
}
|
|
22304
|
-
return false;
|
|
22305
|
-
}
|
|
22306
|
-
emit(operation) {
|
|
22307
|
-
if (this.events) {
|
|
22308
|
-
const command = new DrawingCommand([this], operation);
|
|
22309
|
-
command.apply();
|
|
22310
|
-
this.events.emit(operation, command);
|
|
22311
|
-
} else {
|
|
22312
|
-
this.apply(operation);
|
|
22313
|
-
}
|
|
22314
|
-
}
|
|
22315
|
-
apply(op) {
|
|
22316
|
-
switch (op.class) {
|
|
22317
|
-
case "Drawing":
|
|
22318
|
-
switch (op.method) {
|
|
22319
|
-
case "setStrokeColor":
|
|
22320
|
-
this.borderColor = op.color;
|
|
22321
|
-
break;
|
|
22322
|
-
case "setStrokeWidth":
|
|
22323
|
-
this.strokeWidth = op.width;
|
|
22324
|
-
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
22325
|
-
break;
|
|
22326
|
-
case "setStrokeOpacity":
|
|
22327
|
-
this.borderOpacity = op.opacity;
|
|
22328
|
-
break;
|
|
22329
|
-
case "setStrokeStyle":
|
|
22330
|
-
this.borderStyle = op.style;
|
|
22331
|
-
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
22332
|
-
break;
|
|
22333
|
-
}
|
|
22334
|
-
this.updateMbr();
|
|
22335
|
-
break;
|
|
22336
|
-
case "Transformation":
|
|
22337
|
-
this.transformation.apply(op);
|
|
22338
|
-
break;
|
|
22339
|
-
case "LinkTo":
|
|
22340
|
-
this.linkTo.apply(op);
|
|
22341
|
-
break;
|
|
22342
|
-
default:
|
|
22343
|
-
return;
|
|
22344
|
-
}
|
|
22345
|
-
this.subject.publish(this);
|
|
22346
|
-
}
|
|
22347
|
-
setStrokeOpacity(opacity) {
|
|
22348
|
-
this.emit({
|
|
22349
|
-
class: "Drawing",
|
|
22350
|
-
method: "setStrokeOpacity",
|
|
22351
|
-
item: [this.id],
|
|
22352
|
-
opacity
|
|
22353
|
-
});
|
|
22354
|
-
return this;
|
|
22355
|
-
}
|
|
22356
|
-
getStrokeOpacity() {
|
|
22357
|
-
return this.borderOpacity;
|
|
22358
|
-
}
|
|
22359
|
-
setBorderStyle(style) {
|
|
22360
|
-
this.emit({
|
|
22361
|
-
class: "Drawing",
|
|
22362
|
-
method: "setStrokeStyle",
|
|
22363
|
-
item: [this.id],
|
|
22364
|
-
style
|
|
22365
|
-
});
|
|
22366
|
-
return this;
|
|
22367
|
-
}
|
|
22368
|
-
getBorderStyle() {
|
|
22369
|
-
return this.borderStyle;
|
|
22370
|
-
}
|
|
22371
|
-
setStrokeColor(color) {
|
|
22372
|
-
this.emit({
|
|
22373
|
-
class: "Drawing",
|
|
22374
|
-
method: "setStrokeColor",
|
|
22375
|
-
item: [this.id],
|
|
22376
|
-
color
|
|
22377
|
-
});
|
|
22378
|
-
return this;
|
|
22379
|
-
}
|
|
22380
|
-
getStrokeColor() {
|
|
22381
|
-
return this.borderColor;
|
|
22382
|
-
}
|
|
22383
|
-
setStrokeWidth(width) {
|
|
22384
|
-
this.emit({
|
|
22385
|
-
class: "Drawing",
|
|
22386
|
-
method: "setStrokeWidth",
|
|
22387
|
-
item: [this.id],
|
|
22388
|
-
width,
|
|
22389
|
-
prevWidth: this.strokeWidth
|
|
22390
|
-
});
|
|
22391
|
-
return this;
|
|
22392
|
-
}
|
|
22393
|
-
getLinkTo() {
|
|
22394
|
-
return this.linkTo.link;
|
|
22395
|
-
}
|
|
22396
|
-
getStrokeWidth() {
|
|
22397
|
-
return this.strokeWidth;
|
|
22398
|
-
}
|
|
22399
|
-
getRichText() {
|
|
22400
|
-
return null;
|
|
22401
|
-
}
|
|
22402
|
-
isPointNearLine(point3, threshold = 10) {
|
|
22403
|
-
const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
22404
|
-
const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
22405
|
-
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
22406
|
-
for (let i = 0;i < this.points.length - 1; i++) {
|
|
22407
|
-
const p1 = this.points[i];
|
|
22408
|
-
const p2 = this.points[i + 1];
|
|
22409
|
-
const distance = getPerpendicularDistance(transformedMouse, p1, p2);
|
|
22410
|
-
if (distance < threshold) {
|
|
22411
|
-
return true;
|
|
22412
|
-
}
|
|
22413
|
-
}
|
|
22414
|
-
return false;
|
|
22415
|
-
}
|
|
22416
|
-
}
|
|
22417
|
-
function getPerpendicularDistance(point3, lineStart, lineEnd) {
|
|
22418
|
-
const { x: px, y: py } = point3;
|
|
22419
|
-
const { x: sx, y: sy } = lineStart;
|
|
22420
|
-
const { x: ex, y: ey } = lineEnd;
|
|
22421
|
-
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
22422
|
-
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
22423
|
-
return numerator / denominator;
|
|
22424
|
-
}
|
|
22425
|
-
function douglasPeucker(points, epsilon2) {
|
|
22426
|
-
if (points.length < 3) {
|
|
22427
|
-
return points;
|
|
22428
|
-
}
|
|
22429
|
-
const start = points[0];
|
|
22430
|
-
const end = points[points.length - 1];
|
|
22431
|
-
let maxDistance = 0;
|
|
22432
|
-
let maxIndex = 0;
|
|
22433
|
-
for (let i = 1;i < points.length - 1; i++) {
|
|
22434
|
-
const distance = getPerpendicularDistance(points[i], start, end);
|
|
22435
|
-
if (distance > maxDistance) {
|
|
22436
|
-
maxDistance = distance;
|
|
22437
|
-
maxIndex = i;
|
|
22438
|
-
}
|
|
22439
|
-
}
|
|
22440
|
-
if (maxDistance > epsilon2) {
|
|
22441
|
-
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
22442
|
-
const rightSubPoints = points.slice(maxIndex);
|
|
22443
|
-
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
22444
|
-
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
22445
|
-
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
22446
|
-
} else {
|
|
22447
|
-
return [start, end];
|
|
22448
|
-
}
|
|
22449
|
-
}
|
|
22450
22023
|
// src/SpatialIndex/LayeredIndex/Layers.ts
|
|
22451
22024
|
class Layers {
|
|
22452
22025
|
getNewLayer;
|
|
@@ -23614,6 +23187,7 @@ class SpatialIndex {
|
|
|
23614
23187
|
}
|
|
23615
23188
|
});
|
|
23616
23189
|
});
|
|
23190
|
+
console.log([...items, ...children]);
|
|
23617
23191
|
return [...items, ...children];
|
|
23618
23192
|
}
|
|
23619
23193
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -23628,6 +23202,7 @@ class SpatialIndex {
|
|
|
23628
23202
|
}
|
|
23629
23203
|
});
|
|
23630
23204
|
});
|
|
23205
|
+
console.log([...items, ...children]);
|
|
23631
23206
|
return [...items, ...children];
|
|
23632
23207
|
}
|
|
23633
23208
|
getUnderPoint(point3, tolerance = 5) {
|
|
@@ -23641,6 +23216,7 @@ class SpatialIndex {
|
|
|
23641
23216
|
}
|
|
23642
23217
|
});
|
|
23643
23218
|
});
|
|
23219
|
+
console.log([...items, ...children]);
|
|
23644
23220
|
return [...items, ...children];
|
|
23645
23221
|
}
|
|
23646
23222
|
getRectsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -23655,6 +23231,7 @@ class SpatialIndex {
|
|
|
23655
23231
|
}
|
|
23656
23232
|
});
|
|
23657
23233
|
});
|
|
23234
|
+
console.log([...items, ...children]);
|
|
23658
23235
|
return [...items, ...children];
|
|
23659
23236
|
}
|
|
23660
23237
|
getItemsEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -23674,9 +23251,11 @@ class SpatialIndex {
|
|
|
23674
23251
|
distance: point3.getDistance(item.getMbr().getCenter())
|
|
23675
23252
|
})).filter(({ distance }) => distance <= maxDistance);
|
|
23676
23253
|
withDistance.sort((a, b) => a.distance - b.distance);
|
|
23254
|
+
console.log(withDistance.slice(0, maxItems).map(({ item }) => item));
|
|
23677
23255
|
return withDistance.slice(0, maxItems).map(({ item }) => item);
|
|
23678
23256
|
}
|
|
23679
23257
|
list() {
|
|
23258
|
+
console.log("list", this.getItemsWithIncludedChildren(this.itemsArray).concat());
|
|
23680
23259
|
return this.getItemsWithIncludedChildren(this.itemsArray).concat();
|
|
23681
23260
|
}
|
|
23682
23261
|
getZIndex(item) {
|
|
@@ -23769,12 +23348,12 @@ class Items {
|
|
|
23769
23348
|
if (enclosed.length === 0) {
|
|
23770
23349
|
enclosed = underPointer;
|
|
23771
23350
|
}
|
|
23772
|
-
if (underPointer.some((item) => item
|
|
23351
|
+
if (underPointer.some((item) => item.itemType === "Drawing")) {
|
|
23773
23352
|
enclosed = [...underPointer, ...enclosed];
|
|
23774
23353
|
}
|
|
23775
23354
|
const { nearest } = enclosed.reduce((acc, item) => {
|
|
23776
23355
|
const area = item.getMbr().getHeight() * item.getMbr().getWidth();
|
|
23777
|
-
if (item
|
|
23356
|
+
if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
|
|
23778
23357
|
return acc;
|
|
23779
23358
|
}
|
|
23780
23359
|
const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
|
|
@@ -24047,6 +23626,7 @@ class SimpleSpatialIndex {
|
|
|
24047
23626
|
items.push(item);
|
|
24048
23627
|
}
|
|
24049
23628
|
});
|
|
23629
|
+
console.log("simple", items);
|
|
24050
23630
|
return items;
|
|
24051
23631
|
}
|
|
24052
23632
|
getEnclosedOrCrossed(left, top, right, bottom) {
|
|
@@ -24057,6 +23637,7 @@ class SimpleSpatialIndex {
|
|
|
24057
23637
|
items.push(item);
|
|
24058
23638
|
}
|
|
24059
23639
|
});
|
|
23640
|
+
console.log("simple", items);
|
|
24060
23641
|
return items;
|
|
24061
23642
|
}
|
|
24062
23643
|
getUnderPoint(point3, tolerace = 5) {
|
|
@@ -24066,12 +23647,14 @@ class SimpleSpatialIndex {
|
|
|
24066
23647
|
items.push(item);
|
|
24067
23648
|
}
|
|
24068
23649
|
});
|
|
23650
|
+
console.log("simple", items);
|
|
24069
23651
|
return items;
|
|
24070
23652
|
}
|
|
24071
23653
|
getMbr() {
|
|
24072
23654
|
return this.Mbr;
|
|
24073
23655
|
}
|
|
24074
23656
|
list() {
|
|
23657
|
+
console.log("simple list", this.itemsArray.concat());
|
|
24075
23658
|
return this.itemsArray.concat();
|
|
24076
23659
|
}
|
|
24077
23660
|
getZIndex(item) {
|
|
@@ -44660,202 +44243,455 @@ class Placeholder extends BaseItem {
|
|
|
44660
44243
|
renderHTML(documentFactory) {
|
|
44661
44244
|
return documentFactory.createElement("div");
|
|
44662
44245
|
}
|
|
44663
|
-
getLinkTo() {
|
|
44664
|
-
return;
|
|
44246
|
+
getLinkTo() {
|
|
44247
|
+
return;
|
|
44248
|
+
}
|
|
44249
|
+
getRichText() {
|
|
44250
|
+
return null;
|
|
44251
|
+
}
|
|
44252
|
+
}
|
|
44253
|
+
// src/Items/Image/Image.ts
|
|
44254
|
+
function getPlaceholderImage(board, imageDimension) {
|
|
44255
|
+
const placeholderCanvas = conf.documentFactory.createElement("canvas");
|
|
44256
|
+
const placeholderContext = placeholderCanvas.getContext("2d");
|
|
44257
|
+
const context = new DrawingContext(board.camera, placeholderContext);
|
|
44258
|
+
const placeholder = new Placeholder(board);
|
|
44259
|
+
if (imageDimension) {
|
|
44260
|
+
placeholderCanvas.width = imageDimension.width;
|
|
44261
|
+
placeholderCanvas.height = imageDimension.height;
|
|
44262
|
+
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
44263
|
+
} else {
|
|
44264
|
+
placeholderCanvas.width = 250;
|
|
44265
|
+
placeholderCanvas.height = 50;
|
|
44266
|
+
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
44267
|
+
}
|
|
44268
|
+
const placeholderImage = new Image;
|
|
44269
|
+
placeholderImage.src = placeholderCanvas.toDataURL();
|
|
44270
|
+
return placeholderImage;
|
|
44271
|
+
}
|
|
44272
|
+
|
|
44273
|
+
class ImageItem extends BaseItem {
|
|
44274
|
+
events;
|
|
44275
|
+
itemType = "Image";
|
|
44276
|
+
parent = "Board";
|
|
44277
|
+
image;
|
|
44278
|
+
transformation;
|
|
44279
|
+
linkTo;
|
|
44280
|
+
subject = new Subject;
|
|
44281
|
+
loadCallbacks = [];
|
|
44282
|
+
beforeLoadCallbacks = [];
|
|
44283
|
+
transformationRenderBlock = undefined;
|
|
44284
|
+
storageLink;
|
|
44285
|
+
imageDimension;
|
|
44286
|
+
board;
|
|
44287
|
+
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
44288
|
+
super(board, id);
|
|
44289
|
+
this.events = events;
|
|
44290
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
44291
|
+
this.board = board;
|
|
44292
|
+
this.setStorageLink(storageLink);
|
|
44293
|
+
this.imageDimension = imageDimension;
|
|
44294
|
+
this.transformation = new Transformation(id, events);
|
|
44295
|
+
this.image = new Image;
|
|
44296
|
+
this.image.crossOrigin = "anonymous";
|
|
44297
|
+
this.image.onload = this.onLoad;
|
|
44298
|
+
this.image.onerror = this.onError;
|
|
44299
|
+
if (typeof base64 === "string") {
|
|
44300
|
+
this.image.src = base64;
|
|
44301
|
+
}
|
|
44302
|
+
this.linkTo.subject.subscribe(() => {
|
|
44303
|
+
this.updateMbr();
|
|
44304
|
+
this.subject.publish(this);
|
|
44305
|
+
});
|
|
44306
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
44307
|
+
}
|
|
44308
|
+
setStorageLink(link2) {
|
|
44309
|
+
try {
|
|
44310
|
+
const url = new URL(link2);
|
|
44311
|
+
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
44312
|
+
} catch (_) {}
|
|
44313
|
+
}
|
|
44314
|
+
getStorageId() {
|
|
44315
|
+
return this.storageLink.split("/").pop();
|
|
44316
|
+
}
|
|
44317
|
+
handleError = () => {
|
|
44318
|
+
console.error("Invalid dataUrl or image failed to load.");
|
|
44319
|
+
this.image = getPlaceholderImage(this.board);
|
|
44320
|
+
this.updateMbr();
|
|
44321
|
+
this.subject.publish(this);
|
|
44322
|
+
this.shootLoadCallbacks();
|
|
44323
|
+
};
|
|
44324
|
+
onLoad = async () => {
|
|
44325
|
+
this.shootBeforeLoadCallbacks();
|
|
44326
|
+
this.updateMbr();
|
|
44327
|
+
this.subject.publish(this);
|
|
44328
|
+
this.shootLoadCallbacks();
|
|
44329
|
+
};
|
|
44330
|
+
onError = (_error) => {
|
|
44331
|
+
this.image = getPlaceholderImage(this.board);
|
|
44332
|
+
this.updateMbr();
|
|
44333
|
+
this.subject.publish(this);
|
|
44334
|
+
this.shootLoadCallbacks();
|
|
44335
|
+
};
|
|
44336
|
+
onTransform = () => {
|
|
44337
|
+
this.updateMbr();
|
|
44338
|
+
this.subject.publish(this);
|
|
44339
|
+
};
|
|
44340
|
+
updateMbr() {
|
|
44341
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44342
|
+
this.left = translateX;
|
|
44343
|
+
this.top = translateY;
|
|
44344
|
+
this.right = this.left + this.image.width * scaleX;
|
|
44345
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
44346
|
+
}
|
|
44347
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
44348
|
+
this.loadCallbacks.push(callback);
|
|
44349
|
+
};
|
|
44350
|
+
doOnceOnLoad = (callback) => {
|
|
44351
|
+
this.loadCallbacks.push(callback);
|
|
44352
|
+
};
|
|
44353
|
+
setId(id) {
|
|
44354
|
+
this.id = id;
|
|
44355
|
+
this.transformation.setId(id);
|
|
44356
|
+
this.linkTo.setId(id);
|
|
44357
|
+
return this;
|
|
44358
|
+
}
|
|
44359
|
+
getId() {
|
|
44360
|
+
return this.id;
|
|
44361
|
+
}
|
|
44362
|
+
serialize() {
|
|
44363
|
+
return {
|
|
44364
|
+
itemType: "Image",
|
|
44365
|
+
storageLink: this.storageLink,
|
|
44366
|
+
imageDimension: this.imageDimension,
|
|
44367
|
+
transformation: this.transformation.serialize(),
|
|
44368
|
+
linkTo: this.linkTo.serialize()
|
|
44369
|
+
};
|
|
44370
|
+
}
|
|
44371
|
+
setCoordinates() {
|
|
44372
|
+
this.left = this.transformation.matrix.translateX;
|
|
44373
|
+
this.top = this.transformation.matrix.translateY;
|
|
44374
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
44375
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
44376
|
+
this.subject.publish(this);
|
|
44377
|
+
}
|
|
44378
|
+
shootBeforeLoadCallbacks() {
|
|
44379
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
44380
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
44381
|
+
}
|
|
44382
|
+
}
|
|
44383
|
+
shootLoadCallbacks() {
|
|
44384
|
+
while (this.loadCallbacks.length > 0) {
|
|
44385
|
+
this.loadCallbacks.shift()(this);
|
|
44386
|
+
}
|
|
44387
|
+
}
|
|
44388
|
+
deserialize(data) {
|
|
44389
|
+
if (data.transformation) {
|
|
44390
|
+
this.transformation.deserialize(data.transformation);
|
|
44391
|
+
}
|
|
44392
|
+
this.linkTo.deserialize(data.linkTo);
|
|
44393
|
+
this.image.onload = () => {
|
|
44394
|
+
this.setCoordinates();
|
|
44395
|
+
this.shootLoadCallbacks();
|
|
44396
|
+
};
|
|
44397
|
+
if (data.storageLink) {
|
|
44398
|
+
this.setStorageLink(data.storageLink);
|
|
44399
|
+
}
|
|
44400
|
+
if (this.image.src) {
|
|
44401
|
+
return this;
|
|
44402
|
+
}
|
|
44403
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
44404
|
+
const storageImage = new Image;
|
|
44405
|
+
storageImage.onload = () => {
|
|
44406
|
+
this.image = storageImage;
|
|
44407
|
+
this.onLoad();
|
|
44408
|
+
};
|
|
44409
|
+
storageImage.onerror = this.onError;
|
|
44410
|
+
storageImage.src = this.storageLink;
|
|
44411
|
+
return this;
|
|
44412
|
+
}
|
|
44413
|
+
emit(operation) {
|
|
44414
|
+
if (this.events) {
|
|
44415
|
+
const command = new ImageCommand([this], operation);
|
|
44416
|
+
command.apply();
|
|
44417
|
+
this.events.emit(operation, command);
|
|
44418
|
+
} else {
|
|
44419
|
+
this.apply(operation);
|
|
44420
|
+
}
|
|
44421
|
+
}
|
|
44422
|
+
setDimensions(dim) {
|
|
44423
|
+
this.imageDimension = dim;
|
|
44424
|
+
}
|
|
44425
|
+
apply(op) {
|
|
44426
|
+
switch (op.class) {
|
|
44427
|
+
case "Transformation":
|
|
44428
|
+
this.transformation.apply(op);
|
|
44429
|
+
break;
|
|
44430
|
+
case "LinkTo":
|
|
44431
|
+
this.linkTo.apply(op);
|
|
44432
|
+
break;
|
|
44433
|
+
case "Image":
|
|
44434
|
+
if (op.data.base64) {
|
|
44435
|
+
this.image.src = op.data.base64;
|
|
44436
|
+
}
|
|
44437
|
+
this.setStorageLink(op.data.storageLink);
|
|
44438
|
+
this.setDimensions(op.data.imageDimension);
|
|
44439
|
+
this.subject.publish(this);
|
|
44440
|
+
break;
|
|
44441
|
+
}
|
|
44442
|
+
}
|
|
44443
|
+
render(context) {
|
|
44444
|
+
if (this.transformationRenderBlock) {
|
|
44445
|
+
return;
|
|
44446
|
+
}
|
|
44447
|
+
const ctx = context.ctx;
|
|
44448
|
+
ctx.save();
|
|
44449
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
44450
|
+
ctx.drawImage(this.image, 0, 0);
|
|
44451
|
+
ctx.restore();
|
|
44452
|
+
if (this.getLinkTo()) {
|
|
44453
|
+
const { top, right } = this.getMbr();
|
|
44454
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
44455
|
+
}
|
|
44456
|
+
}
|
|
44457
|
+
renderHTML(documentFactory) {
|
|
44458
|
+
const div = documentFactory.createElement("image-item");
|
|
44459
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44460
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
44461
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
44462
|
+
div.id = this.getId();
|
|
44463
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
44464
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
44465
|
+
div.style.transformOrigin = "top left";
|
|
44466
|
+
div.style.transform = transform;
|
|
44467
|
+
div.style.position = "absolute";
|
|
44468
|
+
div.style.backgroundSize = "cover";
|
|
44469
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
44470
|
+
if (this.getLinkTo()) {
|
|
44471
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
44472
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
44473
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
44474
|
+
div.appendChild(linkElement);
|
|
44475
|
+
}
|
|
44476
|
+
return div;
|
|
44477
|
+
}
|
|
44478
|
+
getPath() {
|
|
44479
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
44480
|
+
const leftTop = new Point(left, top);
|
|
44481
|
+
const rightTop = new Point(right, top);
|
|
44482
|
+
const rightBottom = new Point(right, bottom);
|
|
44483
|
+
const leftBottom = new Point(left, bottom);
|
|
44484
|
+
return new Path([
|
|
44485
|
+
new Line(leftTop, rightTop),
|
|
44486
|
+
new Line(rightTop, rightBottom),
|
|
44487
|
+
new Line(rightBottom, leftBottom),
|
|
44488
|
+
new Line(leftBottom, leftTop)
|
|
44489
|
+
], true);
|
|
44490
|
+
}
|
|
44491
|
+
getSnapAnchorPoints() {
|
|
44492
|
+
const mbr = this.getMbr();
|
|
44493
|
+
const width2 = mbr.getWidth();
|
|
44494
|
+
const height2 = mbr.getHeight();
|
|
44495
|
+
return [
|
|
44496
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
44497
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
44498
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
44499
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
44500
|
+
];
|
|
44501
|
+
}
|
|
44502
|
+
isClosed() {
|
|
44503
|
+
return true;
|
|
44665
44504
|
}
|
|
44666
44505
|
getRichText() {
|
|
44667
44506
|
return null;
|
|
44668
44507
|
}
|
|
44508
|
+
getLinkTo() {
|
|
44509
|
+
return this.linkTo.link;
|
|
44510
|
+
}
|
|
44511
|
+
download() {
|
|
44512
|
+
const linkElem = document.createElement("a");
|
|
44513
|
+
linkElem.href = this.storageLink;
|
|
44514
|
+
linkElem.setAttribute("download", "");
|
|
44515
|
+
linkElem.click();
|
|
44516
|
+
}
|
|
44517
|
+
onRemove() {
|
|
44518
|
+
const storageId = this.getStorageId();
|
|
44519
|
+
if (storageId) {
|
|
44520
|
+
conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
|
|
44521
|
+
}
|
|
44522
|
+
super.onRemove();
|
|
44523
|
+
}
|
|
44669
44524
|
}
|
|
44670
|
-
// src/
|
|
44671
|
-
function
|
|
44672
|
-
|
|
44673
|
-
|
|
44674
|
-
const context = new DrawingContext(board.camera, placeholderContext);
|
|
44675
|
-
const placeholder = new Placeholder(board);
|
|
44676
|
-
if (imageDimension) {
|
|
44677
|
-
placeholderCanvas.width = imageDimension.width;
|
|
44678
|
-
placeholderCanvas.height = imageDimension.height;
|
|
44679
|
-
placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
|
|
44680
|
-
} else {
|
|
44681
|
-
placeholderCanvas.width = 250;
|
|
44682
|
-
placeholderCanvas.height = 50;
|
|
44683
|
-
placeholder.transformation.scaleTo(250 / 100, 50 / 100);
|
|
44525
|
+
// src/isSafari.ts
|
|
44526
|
+
function isSafari() {
|
|
44527
|
+
if (typeof navigator === "undefined") {
|
|
44528
|
+
return false;
|
|
44684
44529
|
}
|
|
44685
|
-
const
|
|
44686
|
-
|
|
44687
|
-
|
|
44530
|
+
const agent = navigator.userAgent;
|
|
44531
|
+
const vendor = navigator.vendor;
|
|
44532
|
+
const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
|
|
44533
|
+
return is2;
|
|
44688
44534
|
}
|
|
44689
44535
|
|
|
44690
|
-
|
|
44536
|
+
// src/Items/Drawing/Drawing.ts
|
|
44537
|
+
class Drawing extends BaseItem {
|
|
44538
|
+
points;
|
|
44691
44539
|
events;
|
|
44692
|
-
itemType = "
|
|
44540
|
+
itemType = "Drawing";
|
|
44693
44541
|
parent = "Board";
|
|
44694
|
-
image;
|
|
44695
44542
|
transformation;
|
|
44696
|
-
|
|
44543
|
+
path2d = new conf.path2DFactory;
|
|
44697
44544
|
subject = new Subject;
|
|
44698
|
-
|
|
44699
|
-
|
|
44545
|
+
untransformedMbr = new Mbr;
|
|
44546
|
+
lines = [];
|
|
44547
|
+
linkTo;
|
|
44548
|
+
strokeWidth = 1;
|
|
44549
|
+
borderStyle = "solid";
|
|
44550
|
+
linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
44551
|
+
borderOpacity = 1;
|
|
44700
44552
|
transformationRenderBlock = undefined;
|
|
44701
|
-
|
|
44702
|
-
imageDimension;
|
|
44703
|
-
board;
|
|
44704
|
-
constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
|
|
44553
|
+
constructor(board, points, events, id = "") {
|
|
44705
44554
|
super(board, id);
|
|
44555
|
+
this.points = points;
|
|
44706
44556
|
this.events = events;
|
|
44707
|
-
this.linkTo = new LinkTo(this.id, events);
|
|
44708
|
-
this.board = board;
|
|
44709
|
-
this.setStorageLink(storageLink);
|
|
44710
|
-
this.imageDimension = imageDimension;
|
|
44711
44557
|
this.transformation = new Transformation(id, events);
|
|
44712
|
-
this.
|
|
44713
|
-
this.
|
|
44714
|
-
|
|
44715
|
-
|
|
44716
|
-
|
|
44717
|
-
|
|
44718
|
-
}
|
|
44558
|
+
this.linkTo = new LinkTo(this.id, this.events);
|
|
44559
|
+
this.transformation.subject.subscribe(() => {
|
|
44560
|
+
this.updateMbr();
|
|
44561
|
+
this.updateLines();
|
|
44562
|
+
this.subject.publish(this);
|
|
44563
|
+
});
|
|
44719
44564
|
this.linkTo.subject.subscribe(() => {
|
|
44720
44565
|
this.updateMbr();
|
|
44566
|
+
this.updateLines();
|
|
44721
44567
|
this.subject.publish(this);
|
|
44722
44568
|
});
|
|
44723
|
-
this.
|
|
44724
|
-
}
|
|
44725
|
-
setStorageLink(link2) {
|
|
44726
|
-
try {
|
|
44727
|
-
const url = new URL(link2);
|
|
44728
|
-
this.storageLink = `${window?.location.origin}${url.pathname}`;
|
|
44729
|
-
} catch (_) {}
|
|
44730
|
-
}
|
|
44731
|
-
getStorageId() {
|
|
44732
|
-
return this.storageLink.split("/").pop();
|
|
44733
|
-
}
|
|
44734
|
-
handleError = () => {
|
|
44735
|
-
console.error("Invalid dataUrl or image failed to load.");
|
|
44736
|
-
this.image = getPlaceholderImage(this.board);
|
|
44737
|
-
this.updateMbr();
|
|
44738
|
-
this.subject.publish(this);
|
|
44739
|
-
this.shootLoadCallbacks();
|
|
44740
|
-
};
|
|
44741
|
-
onLoad = async () => {
|
|
44742
|
-
this.shootBeforeLoadCallbacks();
|
|
44743
|
-
this.updateMbr();
|
|
44744
|
-
this.subject.publish(this);
|
|
44745
|
-
this.shootLoadCallbacks();
|
|
44746
|
-
};
|
|
44747
|
-
onError = (_error) => {
|
|
44748
|
-
this.image = getPlaceholderImage(this.board);
|
|
44749
|
-
this.updateMbr();
|
|
44750
|
-
this.subject.publish(this);
|
|
44751
|
-
this.shootLoadCallbacks();
|
|
44752
|
-
};
|
|
44753
|
-
onTransform = () => {
|
|
44754
|
-
this.updateMbr();
|
|
44755
|
-
this.subject.publish(this);
|
|
44756
|
-
};
|
|
44757
|
-
updateMbr() {
|
|
44758
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44759
|
-
this.left = translateX;
|
|
44760
|
-
this.top = translateY;
|
|
44761
|
-
this.right = this.left + this.image.width * scaleX;
|
|
44762
|
-
this.bottom = this.top + this.image.height * scaleY;
|
|
44763
|
-
}
|
|
44764
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
44765
|
-
this.loadCallbacks.push(callback);
|
|
44766
|
-
};
|
|
44767
|
-
doOnceOnLoad = (callback) => {
|
|
44768
|
-
this.loadCallbacks.push(callback);
|
|
44769
|
-
};
|
|
44770
|
-
setId(id) {
|
|
44771
|
-
this.id = id;
|
|
44772
|
-
this.transformation.setId(id);
|
|
44773
|
-
this.linkTo.setId(id);
|
|
44774
|
-
return this;
|
|
44775
|
-
}
|
|
44776
|
-
getId() {
|
|
44777
|
-
return this.id;
|
|
44569
|
+
this.updateLines();
|
|
44778
44570
|
}
|
|
44779
44571
|
serialize() {
|
|
44572
|
+
this.optimizePoints();
|
|
44573
|
+
const points = [];
|
|
44574
|
+
for (const point5 of this.points) {
|
|
44575
|
+
points.push({ x: point5.x, y: point5.y });
|
|
44576
|
+
}
|
|
44780
44577
|
return {
|
|
44781
|
-
itemType: "
|
|
44782
|
-
|
|
44783
|
-
imageDimension: this.imageDimension,
|
|
44578
|
+
itemType: "Drawing",
|
|
44579
|
+
points,
|
|
44784
44580
|
transformation: this.transformation.serialize(),
|
|
44581
|
+
strokeStyle: this.borderColor,
|
|
44582
|
+
strokeWidth: this.strokeWidth,
|
|
44785
44583
|
linkTo: this.linkTo.serialize()
|
|
44786
44584
|
};
|
|
44787
44585
|
}
|
|
44788
|
-
|
|
44789
|
-
this.
|
|
44790
|
-
|
|
44791
|
-
|
|
44792
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
44793
|
-
this.subject.publish(this);
|
|
44794
|
-
}
|
|
44795
|
-
shootBeforeLoadCallbacks() {
|
|
44796
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
44797
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
44586
|
+
deserialize(data) {
|
|
44587
|
+
this.points = [];
|
|
44588
|
+
for (const point5 of data.points) {
|
|
44589
|
+
this.points.push(new Point(point5.x, point5.y));
|
|
44798
44590
|
}
|
|
44591
|
+
this.linkTo.deserialize(data.linkTo);
|
|
44592
|
+
this.optimizePoints();
|
|
44593
|
+
this.transformation.deserialize(data.transformation);
|
|
44594
|
+
this.borderColor = data.strokeStyle;
|
|
44595
|
+
this.strokeWidth = data.strokeWidth;
|
|
44596
|
+
this.updateGeometry();
|
|
44597
|
+
return this;
|
|
44799
44598
|
}
|
|
44800
|
-
|
|
44801
|
-
|
|
44802
|
-
|
|
44803
|
-
|
|
44599
|
+
updateGeometry() {
|
|
44600
|
+
this.updatePath2d();
|
|
44601
|
+
this.updateLines();
|
|
44602
|
+
this.updateMbr();
|
|
44804
44603
|
}
|
|
44805
|
-
|
|
44806
|
-
|
|
44807
|
-
|
|
44604
|
+
updateMbr() {
|
|
44605
|
+
const offset = this.getStrokeWidth() / 2;
|
|
44606
|
+
const untransformedMbr = this.untransformedMbr.copy();
|
|
44607
|
+
untransformedMbr.left -= offset;
|
|
44608
|
+
untransformedMbr.top -= offset;
|
|
44609
|
+
untransformedMbr.right += offset;
|
|
44610
|
+
untransformedMbr.bottom += offset;
|
|
44611
|
+
const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
|
|
44612
|
+
this.left = mbr.left;
|
|
44613
|
+
this.top = mbr.top;
|
|
44614
|
+
this.right = mbr.right;
|
|
44615
|
+
this.bottom = mbr.bottom;
|
|
44616
|
+
}
|
|
44617
|
+
updatePath2d() {
|
|
44618
|
+
this.path2d = new conf.path2DFactory;
|
|
44619
|
+
const context = this.path2d;
|
|
44620
|
+
const points = this.points;
|
|
44621
|
+
if (points.length < 3) {
|
|
44622
|
+
context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
|
|
44623
|
+
context.closePath();
|
|
44624
|
+
} else {
|
|
44625
|
+
context.moveTo(points[0].x, points[0].y);
|
|
44626
|
+
let j = 1;
|
|
44627
|
+
for (;j < points.length - 2; j++) {
|
|
44628
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
44629
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
44630
|
+
context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
|
|
44631
|
+
}
|
|
44632
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
44633
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
44634
|
+
context.quadraticCurveTo(points[j].x, points[j].y, x, y);
|
|
44808
44635
|
}
|
|
44809
|
-
|
|
44810
|
-
|
|
44811
|
-
|
|
44812
|
-
|
|
44813
|
-
}
|
|
44814
|
-
|
|
44815
|
-
|
|
44636
|
+
let left = Number.MAX_SAFE_INTEGER;
|
|
44637
|
+
let right = Number.MIN_SAFE_INTEGER;
|
|
44638
|
+
let top = Number.MAX_SAFE_INTEGER;
|
|
44639
|
+
let bottom = Number.MIN_SAFE_INTEGER;
|
|
44640
|
+
for (const { x, y } of this.points) {
|
|
44641
|
+
if (x < left) {
|
|
44642
|
+
left = x;
|
|
44643
|
+
}
|
|
44644
|
+
if (x > right) {
|
|
44645
|
+
right = x;
|
|
44646
|
+
}
|
|
44647
|
+
if (y < top) {
|
|
44648
|
+
top = y;
|
|
44649
|
+
}
|
|
44650
|
+
if (y > bottom) {
|
|
44651
|
+
bottom = y;
|
|
44652
|
+
}
|
|
44816
44653
|
}
|
|
44817
|
-
|
|
44818
|
-
|
|
44654
|
+
this.untransformedMbr = new Mbr(left, top, right, bottom);
|
|
44655
|
+
}
|
|
44656
|
+
updateLines() {
|
|
44657
|
+
this.lines = [];
|
|
44658
|
+
const matrix = this.transformation.matrix;
|
|
44659
|
+
if (this.points.length < 2) {
|
|
44660
|
+
return;
|
|
44661
|
+
}
|
|
44662
|
+
for (let i = 0;i < this.points.length - 2; i++) {
|
|
44663
|
+
const p1 = this.points[i];
|
|
44664
|
+
const p22 = this.points[i + 1];
|
|
44665
|
+
const line = new Line(p1.copy(), p22.copy());
|
|
44666
|
+
line.transform(matrix);
|
|
44667
|
+
this.lines.push(line);
|
|
44819
44668
|
}
|
|
44820
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
44821
|
-
const storageImage = new Image;
|
|
44822
|
-
storageImage.onload = () => {
|
|
44823
|
-
this.image = storageImage;
|
|
44824
|
-
this.onLoad();
|
|
44825
|
-
};
|
|
44826
|
-
storageImage.onerror = this.onError;
|
|
44827
|
-
storageImage.src = this.storageLink;
|
|
44828
|
-
return this;
|
|
44829
44669
|
}
|
|
44830
|
-
|
|
44831
|
-
|
|
44832
|
-
|
|
44833
|
-
|
|
44834
|
-
|
|
44670
|
+
optimizePoints() {
|
|
44671
|
+
const dp = douglasPeucker(this.points, 1);
|
|
44672
|
+
dp.push(this.points[this.points.length - 1]);
|
|
44673
|
+
this.points = dp;
|
|
44674
|
+
}
|
|
44675
|
+
addPoint(point5) {
|
|
44676
|
+
const previous2 = this.points[this.points.length - 1];
|
|
44677
|
+
if (previous2) {
|
|
44678
|
+
const distance = point5.getDistance(previous2);
|
|
44679
|
+
if (distance >= 2) {
|
|
44680
|
+
this.points.push(point5);
|
|
44681
|
+
}
|
|
44835
44682
|
} else {
|
|
44836
|
-
this.
|
|
44683
|
+
this.points.push(point5);
|
|
44837
44684
|
}
|
|
44685
|
+
this.updateGeometry();
|
|
44838
44686
|
}
|
|
44839
|
-
|
|
44840
|
-
this.
|
|
44687
|
+
setId(id) {
|
|
44688
|
+
this.id = id;
|
|
44689
|
+
this.transformation.setId(id);
|
|
44690
|
+
this.linkTo.setId(id);
|
|
44691
|
+
return this;
|
|
44841
44692
|
}
|
|
44842
|
-
|
|
44843
|
-
|
|
44844
|
-
case "Transformation":
|
|
44845
|
-
this.transformation.apply(op);
|
|
44846
|
-
break;
|
|
44847
|
-
case "LinkTo":
|
|
44848
|
-
this.linkTo.apply(op);
|
|
44849
|
-
break;
|
|
44850
|
-
case "Image":
|
|
44851
|
-
if (op.data.base64) {
|
|
44852
|
-
this.image.src = op.data.base64;
|
|
44853
|
-
}
|
|
44854
|
-
this.setStorageLink(op.data.storageLink);
|
|
44855
|
-
this.setDimensions(op.data.imageDimension);
|
|
44856
|
-
this.subject.publish(this);
|
|
44857
|
-
break;
|
|
44858
|
-
}
|
|
44693
|
+
getId() {
|
|
44694
|
+
return this.id;
|
|
44859
44695
|
}
|
|
44860
44696
|
render(context) {
|
|
44861
44697
|
if (this.transformationRenderBlock) {
|
|
@@ -44863,8 +44699,12 @@ class ImageItem extends BaseItem {
|
|
|
44863
44699
|
}
|
|
44864
44700
|
const ctx = context.ctx;
|
|
44865
44701
|
ctx.save();
|
|
44702
|
+
ctx.strokeStyle = this.borderColor;
|
|
44703
|
+
ctx.lineWidth = this.strokeWidth;
|
|
44704
|
+
ctx.lineCap = "round";
|
|
44705
|
+
ctx.setLineDash(this.linePattern);
|
|
44866
44706
|
this.transformation.matrix.applyToContext(ctx);
|
|
44867
|
-
ctx.
|
|
44707
|
+
ctx.stroke(this.path2d.nativePath);
|
|
44868
44708
|
ctx.restore();
|
|
44869
44709
|
if (this.getLinkTo()) {
|
|
44870
44710
|
const { top, right } = this.getMbr();
|
|
@@ -44872,26 +44712,61 @@ class ImageItem extends BaseItem {
|
|
|
44872
44712
|
}
|
|
44873
44713
|
}
|
|
44874
44714
|
renderHTML(documentFactory) {
|
|
44875
|
-
const div = documentFactory.createElement("
|
|
44715
|
+
const div = documentFactory.createElement("drawing-item");
|
|
44876
44716
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
44877
|
-
const
|
|
44878
|
-
|
|
44717
|
+
const mbr = this.getMbr();
|
|
44718
|
+
const width2 = mbr.getWidth();
|
|
44719
|
+
const height2 = mbr.getHeight();
|
|
44720
|
+
const unscaledWidth = width2 / scaleX;
|
|
44721
|
+
const unscaledHeight = height2 / scaleY;
|
|
44722
|
+
const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
44723
|
+
svg3.setAttribute("width", `${unscaledWidth}px`);
|
|
44724
|
+
svg3.setAttribute("height", `${unscaledHeight}px`);
|
|
44725
|
+
svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
|
44726
|
+
svg3.setAttribute("style", "position: absolute; overflow: visible;");
|
|
44727
|
+
const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
44728
|
+
pathElement.setAttribute("d", this.getPathData());
|
|
44729
|
+
pathElement.setAttribute("stroke", this.borderColor);
|
|
44730
|
+
pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
|
|
44731
|
+
pathElement.setAttribute("fill", "none");
|
|
44732
|
+
svg3.appendChild(pathElement);
|
|
44733
|
+
div.appendChild(svg3);
|
|
44879
44734
|
div.id = this.getId();
|
|
44880
|
-
div.style.width =
|
|
44881
|
-
div.style.height =
|
|
44882
|
-
div.style.transformOrigin = "top
|
|
44883
|
-
div.style.transform =
|
|
44735
|
+
div.style.width = unscaledWidth + "px";
|
|
44736
|
+
div.style.height = unscaledHeight + "px";
|
|
44737
|
+
div.style.transformOrigin = "left top";
|
|
44738
|
+
div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
44884
44739
|
div.style.position = "absolute";
|
|
44885
|
-
div.style.backgroundSize = "cover";
|
|
44886
44740
|
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
44887
44741
|
if (this.getLinkTo()) {
|
|
44888
44742
|
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
44889
44743
|
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
44890
|
-
translateElementBy(linkElement, (
|
|
44744
|
+
translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
44891
44745
|
div.appendChild(linkElement);
|
|
44892
44746
|
}
|
|
44893
44747
|
return div;
|
|
44894
44748
|
}
|
|
44749
|
+
getPathData() {
|
|
44750
|
+
const points = this.points;
|
|
44751
|
+
if (points.length < 2) {
|
|
44752
|
+
return "";
|
|
44753
|
+
}
|
|
44754
|
+
let pathData = `M ${points[0].x} ${points[0].y}`;
|
|
44755
|
+
if (points.length < 3) {
|
|
44756
|
+
pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
|
|
44757
|
+
} else {
|
|
44758
|
+
let j = 1;
|
|
44759
|
+
for (;j < points.length - 2; j++) {
|
|
44760
|
+
const cx = (points[j].x + points[j + 1].x) / 2;
|
|
44761
|
+
const cy = (points[j].y + points[j + 1].y) / 2;
|
|
44762
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
|
|
44763
|
+
}
|
|
44764
|
+
const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
|
|
44765
|
+
const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
|
|
44766
|
+
pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
|
|
44767
|
+
}
|
|
44768
|
+
return pathData;
|
|
44769
|
+
}
|
|
44895
44770
|
getPath() {
|
|
44896
44771
|
const { left, top, right, bottom } = this.getMbr();
|
|
44897
44772
|
const leftTop = new Point(left, top);
|
|
@@ -44916,27 +44791,162 @@ class ImageItem extends BaseItem {
|
|
|
44916
44791
|
new Point(mbr.right, mbr.top + height2 / 2)
|
|
44917
44792
|
];
|
|
44918
44793
|
}
|
|
44794
|
+
getLines() {
|
|
44795
|
+
return this.lines;
|
|
44796
|
+
}
|
|
44919
44797
|
isClosed() {
|
|
44920
44798
|
return true;
|
|
44921
44799
|
}
|
|
44922
|
-
|
|
44923
|
-
|
|
44800
|
+
isEnclosedOrCrossedBy(rect) {
|
|
44801
|
+
for (const line of this.lines) {
|
|
44802
|
+
if (line.isEnclosedOrCrossedBy(rect)) {
|
|
44803
|
+
return true;
|
|
44804
|
+
}
|
|
44805
|
+
}
|
|
44806
|
+
return false;
|
|
44807
|
+
}
|
|
44808
|
+
emit(operation) {
|
|
44809
|
+
if (this.events) {
|
|
44810
|
+
const command = new DrawingCommand([this], operation);
|
|
44811
|
+
command.apply();
|
|
44812
|
+
this.events.emit(operation, command);
|
|
44813
|
+
} else {
|
|
44814
|
+
this.apply(operation);
|
|
44815
|
+
}
|
|
44816
|
+
}
|
|
44817
|
+
apply(op) {
|
|
44818
|
+
switch (op.class) {
|
|
44819
|
+
case "Drawing":
|
|
44820
|
+
switch (op.method) {
|
|
44821
|
+
case "setStrokeColor":
|
|
44822
|
+
this.borderColor = op.color;
|
|
44823
|
+
break;
|
|
44824
|
+
case "setStrokeWidth":
|
|
44825
|
+
this.strokeWidth = op.width;
|
|
44826
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
44827
|
+
break;
|
|
44828
|
+
case "setStrokeOpacity":
|
|
44829
|
+
this.borderOpacity = op.opacity;
|
|
44830
|
+
break;
|
|
44831
|
+
case "setStrokeStyle":
|
|
44832
|
+
this.borderStyle = op.style;
|
|
44833
|
+
this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
|
|
44834
|
+
break;
|
|
44835
|
+
}
|
|
44836
|
+
this.updateMbr();
|
|
44837
|
+
break;
|
|
44838
|
+
case "Transformation":
|
|
44839
|
+
this.transformation.apply(op);
|
|
44840
|
+
break;
|
|
44841
|
+
case "LinkTo":
|
|
44842
|
+
this.linkTo.apply(op);
|
|
44843
|
+
break;
|
|
44844
|
+
default:
|
|
44845
|
+
return;
|
|
44846
|
+
}
|
|
44847
|
+
this.subject.publish(this);
|
|
44848
|
+
}
|
|
44849
|
+
setStrokeOpacity(opacity) {
|
|
44850
|
+
this.emit({
|
|
44851
|
+
class: "Drawing",
|
|
44852
|
+
method: "setStrokeOpacity",
|
|
44853
|
+
item: [this.id],
|
|
44854
|
+
opacity
|
|
44855
|
+
});
|
|
44856
|
+
return this;
|
|
44857
|
+
}
|
|
44858
|
+
getStrokeOpacity() {
|
|
44859
|
+
return this.borderOpacity;
|
|
44860
|
+
}
|
|
44861
|
+
setBorderStyle(style2) {
|
|
44862
|
+
this.emit({
|
|
44863
|
+
class: "Drawing",
|
|
44864
|
+
method: "setStrokeStyle",
|
|
44865
|
+
item: [this.id],
|
|
44866
|
+
style: style2
|
|
44867
|
+
});
|
|
44868
|
+
return this;
|
|
44869
|
+
}
|
|
44870
|
+
getBorderStyle() {
|
|
44871
|
+
return this.borderStyle;
|
|
44872
|
+
}
|
|
44873
|
+
setStrokeColor(color2) {
|
|
44874
|
+
this.emit({
|
|
44875
|
+
class: "Drawing",
|
|
44876
|
+
method: "setStrokeColor",
|
|
44877
|
+
item: [this.id],
|
|
44878
|
+
color: color2
|
|
44879
|
+
});
|
|
44880
|
+
return this;
|
|
44881
|
+
}
|
|
44882
|
+
getStrokeColor() {
|
|
44883
|
+
return this.borderColor;
|
|
44884
|
+
}
|
|
44885
|
+
setStrokeWidth(width2) {
|
|
44886
|
+
this.emit({
|
|
44887
|
+
class: "Drawing",
|
|
44888
|
+
method: "setStrokeWidth",
|
|
44889
|
+
item: [this.id],
|
|
44890
|
+
width: width2,
|
|
44891
|
+
prevWidth: this.strokeWidth
|
|
44892
|
+
});
|
|
44893
|
+
return this;
|
|
44924
44894
|
}
|
|
44925
44895
|
getLinkTo() {
|
|
44926
44896
|
return this.linkTo.link;
|
|
44927
44897
|
}
|
|
44928
|
-
|
|
44929
|
-
|
|
44930
|
-
linkElem.href = this.storageLink;
|
|
44931
|
-
linkElem.setAttribute("download", "");
|
|
44932
|
-
linkElem.click();
|
|
44898
|
+
getStrokeWidth() {
|
|
44899
|
+
return this.strokeWidth;
|
|
44933
44900
|
}
|
|
44934
|
-
|
|
44935
|
-
|
|
44936
|
-
|
|
44937
|
-
|
|
44901
|
+
getRichText() {
|
|
44902
|
+
return null;
|
|
44903
|
+
}
|
|
44904
|
+
isPointNearLine(point5, threshold = 10) {
|
|
44905
|
+
const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
|
|
44906
|
+
const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
|
|
44907
|
+
const transformedMouse = new Point(transformedMouseX, transformedMouseY);
|
|
44908
|
+
for (let i = 0;i < this.points.length - 1; i++) {
|
|
44909
|
+
const p1 = this.points[i];
|
|
44910
|
+
const p22 = this.points[i + 1];
|
|
44911
|
+
const distance = getPerpendicularDistance(transformedMouse, p1, p22);
|
|
44912
|
+
if (distance < threshold) {
|
|
44913
|
+
return true;
|
|
44914
|
+
}
|
|
44938
44915
|
}
|
|
44939
|
-
|
|
44916
|
+
return false;
|
|
44917
|
+
}
|
|
44918
|
+
}
|
|
44919
|
+
function getPerpendicularDistance(point5, lineStart, lineEnd) {
|
|
44920
|
+
const { x: px, y: py } = point5;
|
|
44921
|
+
const { x: sx, y: sy } = lineStart;
|
|
44922
|
+
const { x: ex, y: ey } = lineEnd;
|
|
44923
|
+
const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
|
|
44924
|
+
const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
|
|
44925
|
+
return numerator / denominator;
|
|
44926
|
+
}
|
|
44927
|
+
function douglasPeucker(points, epsilon2) {
|
|
44928
|
+
if (points.length < 3) {
|
|
44929
|
+
return points;
|
|
44930
|
+
}
|
|
44931
|
+
const start = points[0];
|
|
44932
|
+
const end = points[points.length - 1];
|
|
44933
|
+
let maxDistance = 0;
|
|
44934
|
+
let maxIndex = 0;
|
|
44935
|
+
for (let i = 1;i < points.length - 1; i++) {
|
|
44936
|
+
const distance = getPerpendicularDistance(points[i], start, end);
|
|
44937
|
+
if (distance > maxDistance) {
|
|
44938
|
+
maxDistance = distance;
|
|
44939
|
+
maxIndex = i;
|
|
44940
|
+
}
|
|
44941
|
+
}
|
|
44942
|
+
if (maxDistance > epsilon2) {
|
|
44943
|
+
const leftSubPoints = points.slice(0, maxIndex + 1);
|
|
44944
|
+
const rightSubPoints = points.slice(maxIndex);
|
|
44945
|
+
const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
|
|
44946
|
+
const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
|
|
44947
|
+
return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
|
|
44948
|
+
} else {
|
|
44949
|
+
return [start, end];
|
|
44940
44950
|
}
|
|
44941
44951
|
}
|
|
44942
44952
|
// src/Items/Group/Group.ts
|