@leapfrog/interactive-canvas 2.0.25-beta-8 → 2.0.25-beta-9
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/abstract-interactive-canvas.d.ts +1 -0
- package/dist/interactive-canvas.es.js +111 -26
- package/dist/interactive-canvas.js +111 -26
- package/dist/layout/advanced-layout-manager.d.ts +1 -0
- package/dist/layout/standard-layout-manager.d.ts +1 -0
- package/dist/object/impl/text.d.ts +2 -0
- package/package.json +1 -1
|
@@ -340,6 +340,7 @@ export declare abstract class AbstractInteractiveCanvas implements IInteractiveC
|
|
|
340
340
|
* @inheritDoc
|
|
341
341
|
*/
|
|
342
342
|
cloneObject(sourceObject: FabricObject, objectData: CanvasObjectData): Promise<void>;
|
|
343
|
+
private redrawScheduled;
|
|
343
344
|
/**
|
|
344
345
|
* Redraw the canvas.
|
|
345
346
|
*/
|
|
@@ -232,9 +232,15 @@ class ResizeCanvasLayoutFunction {
|
|
|
232
232
|
const targetHeight = increase.withSize(increase.width, baseDimensions.height + increase.height);
|
|
233
233
|
if (currentDimensions.height !== targetHeight.height) {
|
|
234
234
|
canvas.setDimensions(targetHeight);
|
|
235
|
+
canvas.getObjectsInternal().forEach((object) => {
|
|
236
|
+
var _a;
|
|
237
|
+
const canvasObj = canvas.getObjectsByTypeInternal(object.type).find(o => o.getId() === object.getId());
|
|
238
|
+
if (canvasObj && (((_a = canvasObj.isPinToBottom) === null || _a === void 0 ? void 0 : _a.call(canvasObj)) || object.top > currentDimensions.heightPx * 0.5)) {
|
|
239
|
+
object.setCoords();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
canvas.redraw();
|
|
235
243
|
}
|
|
236
|
-
canvas.getObjectsInternal().forEach((object) => object.setCoords());
|
|
237
|
-
canvas.redraw();
|
|
238
244
|
}
|
|
239
245
|
}
|
|
240
246
|
|
|
@@ -262,13 +268,21 @@ class AdvancedLayoutManager extends AbstractLayoutManager {
|
|
|
262
268
|
this.repositionCutoffs = new RepositionCutoffsLayoutFunction();
|
|
263
269
|
this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
|
|
264
270
|
this.resizeCanvas = new ResizeCanvasLayoutFunction();
|
|
271
|
+
this.dimensionsLayoutScheduled = false;
|
|
265
272
|
}
|
|
266
273
|
onCanvasDimensionsChange() {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
this.
|
|
271
|
-
|
|
274
|
+
if (this.dimensionsLayoutScheduled) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
this.dimensionsLayoutScheduled = true;
|
|
278
|
+
Promise.resolve().then(() => {
|
|
279
|
+
this.pinToBottom.execute(this.canvas);
|
|
280
|
+
this.repositionCutoffs.execute(this.canvas);
|
|
281
|
+
this.repositionBorders.execute(this.canvas);
|
|
282
|
+
this.repositionBackgrounds.execute(this.canvas);
|
|
283
|
+
this.redrawAll.execute(this.canvas);
|
|
284
|
+
this.dimensionsLayoutScheduled = false;
|
|
285
|
+
});
|
|
272
286
|
}
|
|
273
287
|
onTextChange() {
|
|
274
288
|
this.resizeCanvas.execute(this.canvas);
|
|
@@ -296,7 +310,7 @@ class StackObjectsLayoutFunction {
|
|
|
296
310
|
const footerObjects = objects[0];
|
|
297
311
|
const bodyObjects = objects[1];
|
|
298
312
|
const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
|
|
299
|
-
canvas.redraw();
|
|
313
|
+
// canvas.redraw();
|
|
300
314
|
//Make one pass and set the widths of all elements. This will force objects with dynamic heights (like text) to take on their necessary height before trying to lay them out.
|
|
301
315
|
this.applyWidths(allObjects, bodyWidth);
|
|
302
316
|
const bodyRows = this.getRows(bodyObjects);
|
|
@@ -383,7 +397,12 @@ class StackObjectsLayoutFunction {
|
|
|
383
397
|
object.setPosition({
|
|
384
398
|
width: actualWidth
|
|
385
399
|
});
|
|
386
|
-
object.updateDimensions();
|
|
400
|
+
//object.updateDimensions();
|
|
401
|
+
_(objects).forEach((object) => {
|
|
402
|
+
if (object.getType() !== ObjectType.VERTICAL_RULE) {
|
|
403
|
+
object.updateDimensions();
|
|
404
|
+
}
|
|
405
|
+
});
|
|
387
406
|
});
|
|
388
407
|
}
|
|
389
408
|
adjustCanvasSize(canvas, requiredHeight) {
|
|
@@ -456,6 +475,7 @@ class StandardLayoutManager extends AbstractLayoutManager {
|
|
|
456
475
|
this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
|
|
457
476
|
this.stackObjects = new StackObjectsLayoutFunction();
|
|
458
477
|
this.updateObjectDimensions = new UpdateObjectDimensionsLayoutFunction();
|
|
478
|
+
this.layoutBatchScheduled = false;
|
|
459
479
|
}
|
|
460
480
|
/**
|
|
461
481
|
* @override
|
|
@@ -497,12 +517,19 @@ class StandardLayoutManager extends AbstractLayoutManager {
|
|
|
497
517
|
this.stackAndRedraw();
|
|
498
518
|
}
|
|
499
519
|
stackAndRedraw() {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
this.
|
|
504
|
-
|
|
505
|
-
|
|
520
|
+
if (this.layoutBatchScheduled) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
this.layoutBatchScheduled = true;
|
|
524
|
+
Promise.resolve().then(() => {
|
|
525
|
+
this.stackObjects.execute(this.canvas);
|
|
526
|
+
this.repositionCutoffs.execute(this.canvas);
|
|
527
|
+
this.repositionBorders.execute(this.canvas);
|
|
528
|
+
this.repositionBackgrounds.execute(this.canvas);
|
|
529
|
+
this.updateObjectDimensions.execute(this.canvas);
|
|
530
|
+
this.redrawAll.execute(this.canvas);
|
|
531
|
+
this.layoutBatchScheduled = false;
|
|
532
|
+
});
|
|
506
533
|
}
|
|
507
534
|
}
|
|
508
535
|
|
|
@@ -1780,15 +1807,43 @@ var ObjectType;
|
|
|
1780
1807
|
class Text extends AbstractCanvasObject {
|
|
1781
1808
|
constructor(canvas, fabricObject, persistedField) {
|
|
1782
1809
|
super(ObjectType.TEXT, canvas, fabricObject, persistedField);
|
|
1810
|
+
this.notifyCanvasTimeout = null;
|
|
1811
|
+
this.NOTIFY_DELAY_MS = 150;
|
|
1783
1812
|
this.canvas = canvas;
|
|
1784
1813
|
this.fontLibrary = canvas.getFontLibrary();
|
|
1785
1814
|
this.baseComponentHeight = this.fabricObject.height;
|
|
1786
1815
|
this.text$ = new BehaviorSubject(this.fabricObject.text);
|
|
1787
1816
|
this.data.userText = this.fabricObject.text;
|
|
1788
1817
|
this.textSelection$ = new BehaviorSubject(new TextSelection(this.fabricObject, this.fontLibrary));
|
|
1789
|
-
this.fabricObject.set({
|
|
1818
|
+
//this.fabricObject.set({strokeWidth: 0});
|
|
1819
|
+
this.fabricObject.set({
|
|
1820
|
+
strokeWidth: 0,
|
|
1821
|
+
perPixelTargetFind: false // Disable per-pixel detection for this object
|
|
1822
|
+
});
|
|
1790
1823
|
this.fabricObject.on("changed", () => this.onTextChange());
|
|
1791
1824
|
this.fabricObject.on("selection:changed", () => this.onSelectionChange());
|
|
1825
|
+
this.fabricObject.containsPoint.bind(this.fabricObject);
|
|
1826
|
+
this.fabricObject.containsPoint = function (point) {
|
|
1827
|
+
const coords = this.getCoords();
|
|
1828
|
+
if (coords.length !== 4)
|
|
1829
|
+
return false;
|
|
1830
|
+
let inside = false;
|
|
1831
|
+
for (let i = 0, j = coords.length - 1; i < coords.length; j = i++) {
|
|
1832
|
+
const xi = coords[i].x, yi = coords[i].y;
|
|
1833
|
+
const xj = coords[j].x, yj = coords[j].y;
|
|
1834
|
+
const intersect = ((yi > point.y) !== (yj > point.y))
|
|
1835
|
+
&& (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi);
|
|
1836
|
+
if (intersect)
|
|
1837
|
+
inside = !inside;
|
|
1838
|
+
}
|
|
1839
|
+
return inside;
|
|
1840
|
+
};
|
|
1841
|
+
this.fabricObject.on("mousedown", (e) => {
|
|
1842
|
+
var _a;
|
|
1843
|
+
if (!this.fabricObject.isEditing) {
|
|
1844
|
+
(_a = e.e) === null || _a === void 0 ? void 0 : _a.preventDefault();
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1792
1847
|
this.applyBulletListMonkeyPatches();
|
|
1793
1848
|
}
|
|
1794
1849
|
/**
|
|
@@ -2508,9 +2563,16 @@ class Text extends AbstractCanvasObject {
|
|
|
2508
2563
|
const profile = this.canvas.getProfile();
|
|
2509
2564
|
const allowManualPositioning = !this.canvas.getLayoutManager().isEnforcedPositioning;
|
|
2510
2565
|
this.fabricObject.set({
|
|
2566
|
+
lockMovementX: false,
|
|
2567
|
+
lockMovementY: false,
|
|
2511
2568
|
lockScalingY: true,
|
|
2512
2569
|
lockScalingX: this.isPinToBottom(),
|
|
2513
|
-
lockScalingFlip: true
|
|
2570
|
+
lockScalingFlip: true,
|
|
2571
|
+
lockRotation: true,
|
|
2572
|
+
selectable: true,
|
|
2573
|
+
editable: false, // Only enable on double-click
|
|
2574
|
+
hoverCursor: "move", // Show move cursor by default
|
|
2575
|
+
moveCursor: "move",
|
|
2514
2576
|
});
|
|
2515
2577
|
this.fabricObject.setControlsVisibility({
|
|
2516
2578
|
tl: false,
|
|
@@ -2520,35 +2582,49 @@ class Text extends AbstractCanvasObject {
|
|
|
2520
2582
|
ml: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
|
|
2521
2583
|
mt: false,
|
|
2522
2584
|
mr: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
|
|
2523
|
-
mb: false
|
|
2585
|
+
mb: false,
|
|
2586
|
+
mtr: false
|
|
2524
2587
|
});
|
|
2525
2588
|
this.redraw();
|
|
2526
2589
|
}
|
|
2527
2590
|
onTextChange() {
|
|
2528
2591
|
this.data.userText = this.fabricObject.text;
|
|
2529
2592
|
this.text$.next(this.fabricObject.text);
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2593
|
+
const currentLeft = this.fabricObject.left || 0;
|
|
2594
|
+
const canvasWidth = this.canvas.getDimensions().widthPx;
|
|
2595
|
+
// Skip expensive getBoundingBox if object is clearly within bounds
|
|
2596
|
+
if (currentLeft + (this.fabricObject.width || 0) > canvasWidth * 0.9) {
|
|
2597
|
+
if (this.getBoundingBox().width > canvasWidth) {
|
|
2598
|
+
this.fabricObject.set({ left: 0, width: canvasWidth });
|
|
2599
|
+
this.redraw();
|
|
2600
|
+
}
|
|
2533
2601
|
}
|
|
2534
2602
|
}
|
|
2535
2603
|
onDelete() {
|
|
2536
2604
|
this.removeBullets();
|
|
2537
2605
|
}
|
|
2538
2606
|
onSelectionChange() {
|
|
2539
|
-
this.updateTextSelection();
|
|
2607
|
+
this.updateTextSelection(false);
|
|
2540
2608
|
}
|
|
2541
2609
|
hasTextSelection() {
|
|
2542
2610
|
return this.canvas.getSelection().isText && this.textSelection$.value.length > 0;
|
|
2543
2611
|
}
|
|
2544
|
-
updateTextSelection() {
|
|
2612
|
+
updateTextSelection(notifyCanvas = true) {
|
|
2545
2613
|
if (this.canvas.headless)
|
|
2546
2614
|
return;
|
|
2547
2615
|
this.textSelection$.next(new TextSelection(this.fabricObject, this.fontLibrary));
|
|
2548
|
-
|
|
2616
|
+
if (notifyCanvas) {
|
|
2617
|
+
this.notifyCanvasOfTextChanges();
|
|
2618
|
+
}
|
|
2549
2619
|
}
|
|
2550
2620
|
notifyCanvasOfTextChanges() {
|
|
2551
|
-
this.
|
|
2621
|
+
if (this.notifyCanvasTimeout) {
|
|
2622
|
+
clearTimeout(this.notifyCanvasTimeout);
|
|
2623
|
+
}
|
|
2624
|
+
this.notifyCanvasTimeout = setTimeout(() => {
|
|
2625
|
+
this.canvas.notifyTextChanged();
|
|
2626
|
+
this.notifyCanvasTimeout = null;
|
|
2627
|
+
}, this.NOTIFY_DELAY_MS);
|
|
2552
2628
|
}
|
|
2553
2629
|
}
|
|
2554
2630
|
Text.NEW_LINE = "\n";
|
|
@@ -2714,6 +2790,7 @@ class AbstractInteractiveCanvas {
|
|
|
2714
2790
|
this.devicePixelRatio = devicePixelRatio;
|
|
2715
2791
|
this.fontLibrary = new FontLibrary();
|
|
2716
2792
|
this.dimensionChangeRejections$ = new Subject();
|
|
2793
|
+
this.redrawScheduled = false;
|
|
2717
2794
|
this.IMAGE_CAPTURE_COEFFICIENT = this.calculateImageCaptureCoefficient();
|
|
2718
2795
|
/**
|
|
2719
2796
|
* Fabric defaults to only 2 decimal places when saving, which causes havoc on the scaling of large images.
|
|
@@ -3132,6 +3209,7 @@ class AbstractInteractiveCanvas {
|
|
|
3132
3209
|
targetFindTolerance: 4,
|
|
3133
3210
|
splitByGrapheme: true,
|
|
3134
3211
|
editable: false, // Only enable on double-click
|
|
3212
|
+
editingBorderColor: '#2196F3',
|
|
3135
3213
|
padding: 0,
|
|
3136
3214
|
cornerSize: 8,
|
|
3137
3215
|
touchCornerSize: 12
|
|
@@ -3583,7 +3661,14 @@ class AbstractInteractiveCanvas {
|
|
|
3583
3661
|
* Redraw the canvas.
|
|
3584
3662
|
*/
|
|
3585
3663
|
redraw() {
|
|
3586
|
-
this.
|
|
3664
|
+
if (this.redrawScheduled) {
|
|
3665
|
+
return;
|
|
3666
|
+
}
|
|
3667
|
+
this.redrawScheduled = true;
|
|
3668
|
+
requestAnimationFrame(() => {
|
|
3669
|
+
this.fabricCanvas.requestRenderAll();
|
|
3670
|
+
this.redrawScheduled = false;
|
|
3671
|
+
});
|
|
3587
3672
|
}
|
|
3588
3673
|
syncObjectList() {
|
|
3589
3674
|
const newObjectList = _(this.fabricCanvas.getObjects())
|
|
@@ -253,9 +253,15 @@ class ResizeCanvasLayoutFunction {
|
|
|
253
253
|
const targetHeight = increase.withSize(increase.width, baseDimensions.height + increase.height);
|
|
254
254
|
if (currentDimensions.height !== targetHeight.height) {
|
|
255
255
|
canvas.setDimensions(targetHeight);
|
|
256
|
+
canvas.getObjectsInternal().forEach((object) => {
|
|
257
|
+
var _a;
|
|
258
|
+
const canvasObj = canvas.getObjectsByTypeInternal(object.type).find(o => o.getId() === object.getId());
|
|
259
|
+
if (canvasObj && (((_a = canvasObj.isPinToBottom) === null || _a === void 0 ? void 0 : _a.call(canvasObj)) || object.top > currentDimensions.heightPx * 0.5)) {
|
|
260
|
+
object.setCoords();
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
canvas.redraw();
|
|
256
264
|
}
|
|
257
|
-
canvas.getObjectsInternal().forEach((object) => object.setCoords());
|
|
258
|
-
canvas.redraw();
|
|
259
265
|
}
|
|
260
266
|
}
|
|
261
267
|
|
|
@@ -283,13 +289,21 @@ class AdvancedLayoutManager extends AbstractLayoutManager {
|
|
|
283
289
|
this.repositionCutoffs = new RepositionCutoffsLayoutFunction();
|
|
284
290
|
this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
|
|
285
291
|
this.resizeCanvas = new ResizeCanvasLayoutFunction();
|
|
292
|
+
this.dimensionsLayoutScheduled = false;
|
|
286
293
|
}
|
|
287
294
|
onCanvasDimensionsChange() {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.
|
|
292
|
-
|
|
295
|
+
if (this.dimensionsLayoutScheduled) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
this.dimensionsLayoutScheduled = true;
|
|
299
|
+
Promise.resolve().then(() => {
|
|
300
|
+
this.pinToBottom.execute(this.canvas);
|
|
301
|
+
this.repositionCutoffs.execute(this.canvas);
|
|
302
|
+
this.repositionBorders.execute(this.canvas);
|
|
303
|
+
this.repositionBackgrounds.execute(this.canvas);
|
|
304
|
+
this.redrawAll.execute(this.canvas);
|
|
305
|
+
this.dimensionsLayoutScheduled = false;
|
|
306
|
+
});
|
|
293
307
|
}
|
|
294
308
|
onTextChange() {
|
|
295
309
|
this.resizeCanvas.execute(this.canvas);
|
|
@@ -317,7 +331,7 @@ class StackObjectsLayoutFunction {
|
|
|
317
331
|
const footerObjects = objects[0];
|
|
318
332
|
const bodyObjects = objects[1];
|
|
319
333
|
const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
|
|
320
|
-
canvas.redraw();
|
|
334
|
+
// canvas.redraw();
|
|
321
335
|
//Make one pass and set the widths of all elements. This will force objects with dynamic heights (like text) to take on their necessary height before trying to lay them out.
|
|
322
336
|
this.applyWidths(allObjects, bodyWidth);
|
|
323
337
|
const bodyRows = this.getRows(bodyObjects);
|
|
@@ -404,7 +418,12 @@ class StackObjectsLayoutFunction {
|
|
|
404
418
|
object.setPosition({
|
|
405
419
|
width: actualWidth
|
|
406
420
|
});
|
|
407
|
-
object.updateDimensions();
|
|
421
|
+
//object.updateDimensions();
|
|
422
|
+
_(objects).forEach((object) => {
|
|
423
|
+
if (object.getType() !== exports.ObjectType.VERTICAL_RULE) {
|
|
424
|
+
object.updateDimensions();
|
|
425
|
+
}
|
|
426
|
+
});
|
|
408
427
|
});
|
|
409
428
|
}
|
|
410
429
|
adjustCanvasSize(canvas, requiredHeight) {
|
|
@@ -477,6 +496,7 @@ class StandardLayoutManager extends AbstractLayoutManager {
|
|
|
477
496
|
this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
|
|
478
497
|
this.stackObjects = new StackObjectsLayoutFunction();
|
|
479
498
|
this.updateObjectDimensions = new UpdateObjectDimensionsLayoutFunction();
|
|
499
|
+
this.layoutBatchScheduled = false;
|
|
480
500
|
}
|
|
481
501
|
/**
|
|
482
502
|
* @override
|
|
@@ -518,12 +538,19 @@ class StandardLayoutManager extends AbstractLayoutManager {
|
|
|
518
538
|
this.stackAndRedraw();
|
|
519
539
|
}
|
|
520
540
|
stackAndRedraw() {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
this.
|
|
525
|
-
|
|
526
|
-
|
|
541
|
+
if (this.layoutBatchScheduled) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
this.layoutBatchScheduled = true;
|
|
545
|
+
Promise.resolve().then(() => {
|
|
546
|
+
this.stackObjects.execute(this.canvas);
|
|
547
|
+
this.repositionCutoffs.execute(this.canvas);
|
|
548
|
+
this.repositionBorders.execute(this.canvas);
|
|
549
|
+
this.repositionBackgrounds.execute(this.canvas);
|
|
550
|
+
this.updateObjectDimensions.execute(this.canvas);
|
|
551
|
+
this.redrawAll.execute(this.canvas);
|
|
552
|
+
this.layoutBatchScheduled = false;
|
|
553
|
+
});
|
|
527
554
|
}
|
|
528
555
|
}
|
|
529
556
|
|
|
@@ -1801,15 +1828,43 @@ exports.ObjectType = void 0;
|
|
|
1801
1828
|
class Text extends AbstractCanvasObject {
|
|
1802
1829
|
constructor(canvas, fabricObject, persistedField) {
|
|
1803
1830
|
super(exports.ObjectType.TEXT, canvas, fabricObject, persistedField);
|
|
1831
|
+
this.notifyCanvasTimeout = null;
|
|
1832
|
+
this.NOTIFY_DELAY_MS = 150;
|
|
1804
1833
|
this.canvas = canvas;
|
|
1805
1834
|
this.fontLibrary = canvas.getFontLibrary();
|
|
1806
1835
|
this.baseComponentHeight = this.fabricObject.height;
|
|
1807
1836
|
this.text$ = new rxjs.BehaviorSubject(this.fabricObject.text);
|
|
1808
1837
|
this.data.userText = this.fabricObject.text;
|
|
1809
1838
|
this.textSelection$ = new rxjs.BehaviorSubject(new TextSelection(this.fabricObject, this.fontLibrary));
|
|
1810
|
-
this.fabricObject.set({
|
|
1839
|
+
//this.fabricObject.set({strokeWidth: 0});
|
|
1840
|
+
this.fabricObject.set({
|
|
1841
|
+
strokeWidth: 0,
|
|
1842
|
+
perPixelTargetFind: false // Disable per-pixel detection for this object
|
|
1843
|
+
});
|
|
1811
1844
|
this.fabricObject.on("changed", () => this.onTextChange());
|
|
1812
1845
|
this.fabricObject.on("selection:changed", () => this.onSelectionChange());
|
|
1846
|
+
this.fabricObject.containsPoint.bind(this.fabricObject);
|
|
1847
|
+
this.fabricObject.containsPoint = function (point) {
|
|
1848
|
+
const coords = this.getCoords();
|
|
1849
|
+
if (coords.length !== 4)
|
|
1850
|
+
return false;
|
|
1851
|
+
let inside = false;
|
|
1852
|
+
for (let i = 0, j = coords.length - 1; i < coords.length; j = i++) {
|
|
1853
|
+
const xi = coords[i].x, yi = coords[i].y;
|
|
1854
|
+
const xj = coords[j].x, yj = coords[j].y;
|
|
1855
|
+
const intersect = ((yi > point.y) !== (yj > point.y))
|
|
1856
|
+
&& (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi);
|
|
1857
|
+
if (intersect)
|
|
1858
|
+
inside = !inside;
|
|
1859
|
+
}
|
|
1860
|
+
return inside;
|
|
1861
|
+
};
|
|
1862
|
+
this.fabricObject.on("mousedown", (e) => {
|
|
1863
|
+
var _a;
|
|
1864
|
+
if (!this.fabricObject.isEditing) {
|
|
1865
|
+
(_a = e.e) === null || _a === void 0 ? void 0 : _a.preventDefault();
|
|
1866
|
+
}
|
|
1867
|
+
});
|
|
1813
1868
|
this.applyBulletListMonkeyPatches();
|
|
1814
1869
|
}
|
|
1815
1870
|
/**
|
|
@@ -2529,9 +2584,16 @@ class Text extends AbstractCanvasObject {
|
|
|
2529
2584
|
const profile = this.canvas.getProfile();
|
|
2530
2585
|
const allowManualPositioning = !this.canvas.getLayoutManager().isEnforcedPositioning;
|
|
2531
2586
|
this.fabricObject.set({
|
|
2587
|
+
lockMovementX: false,
|
|
2588
|
+
lockMovementY: false,
|
|
2532
2589
|
lockScalingY: true,
|
|
2533
2590
|
lockScalingX: this.isPinToBottom(),
|
|
2534
|
-
lockScalingFlip: true
|
|
2591
|
+
lockScalingFlip: true,
|
|
2592
|
+
lockRotation: true,
|
|
2593
|
+
selectable: true,
|
|
2594
|
+
editable: false, // Only enable on double-click
|
|
2595
|
+
hoverCursor: "move", // Show move cursor by default
|
|
2596
|
+
moveCursor: "move",
|
|
2535
2597
|
});
|
|
2536
2598
|
this.fabricObject.setControlsVisibility({
|
|
2537
2599
|
tl: false,
|
|
@@ -2541,35 +2603,49 @@ class Text extends AbstractCanvasObject {
|
|
|
2541
2603
|
ml: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
|
|
2542
2604
|
mt: false,
|
|
2543
2605
|
mr: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
|
|
2544
|
-
mb: false
|
|
2606
|
+
mb: false,
|
|
2607
|
+
mtr: false
|
|
2545
2608
|
});
|
|
2546
2609
|
this.redraw();
|
|
2547
2610
|
}
|
|
2548
2611
|
onTextChange() {
|
|
2549
2612
|
this.data.userText = this.fabricObject.text;
|
|
2550
2613
|
this.text$.next(this.fabricObject.text);
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2614
|
+
const currentLeft = this.fabricObject.left || 0;
|
|
2615
|
+
const canvasWidth = this.canvas.getDimensions().widthPx;
|
|
2616
|
+
// Skip expensive getBoundingBox if object is clearly within bounds
|
|
2617
|
+
if (currentLeft + (this.fabricObject.width || 0) > canvasWidth * 0.9) {
|
|
2618
|
+
if (this.getBoundingBox().width > canvasWidth) {
|
|
2619
|
+
this.fabricObject.set({ left: 0, width: canvasWidth });
|
|
2620
|
+
this.redraw();
|
|
2621
|
+
}
|
|
2554
2622
|
}
|
|
2555
2623
|
}
|
|
2556
2624
|
onDelete() {
|
|
2557
2625
|
this.removeBullets();
|
|
2558
2626
|
}
|
|
2559
2627
|
onSelectionChange() {
|
|
2560
|
-
this.updateTextSelection();
|
|
2628
|
+
this.updateTextSelection(false);
|
|
2561
2629
|
}
|
|
2562
2630
|
hasTextSelection() {
|
|
2563
2631
|
return this.canvas.getSelection().isText && this.textSelection$.value.length > 0;
|
|
2564
2632
|
}
|
|
2565
|
-
updateTextSelection() {
|
|
2633
|
+
updateTextSelection(notifyCanvas = true) {
|
|
2566
2634
|
if (this.canvas.headless)
|
|
2567
2635
|
return;
|
|
2568
2636
|
this.textSelection$.next(new TextSelection(this.fabricObject, this.fontLibrary));
|
|
2569
|
-
|
|
2637
|
+
if (notifyCanvas) {
|
|
2638
|
+
this.notifyCanvasOfTextChanges();
|
|
2639
|
+
}
|
|
2570
2640
|
}
|
|
2571
2641
|
notifyCanvasOfTextChanges() {
|
|
2572
|
-
this.
|
|
2642
|
+
if (this.notifyCanvasTimeout) {
|
|
2643
|
+
clearTimeout(this.notifyCanvasTimeout);
|
|
2644
|
+
}
|
|
2645
|
+
this.notifyCanvasTimeout = setTimeout(() => {
|
|
2646
|
+
this.canvas.notifyTextChanged();
|
|
2647
|
+
this.notifyCanvasTimeout = null;
|
|
2648
|
+
}, this.NOTIFY_DELAY_MS);
|
|
2573
2649
|
}
|
|
2574
2650
|
}
|
|
2575
2651
|
Text.NEW_LINE = "\n";
|
|
@@ -2735,6 +2811,7 @@ class AbstractInteractiveCanvas {
|
|
|
2735
2811
|
this.devicePixelRatio = devicePixelRatio;
|
|
2736
2812
|
this.fontLibrary = new FontLibrary();
|
|
2737
2813
|
this.dimensionChangeRejections$ = new rxjs.Subject();
|
|
2814
|
+
this.redrawScheduled = false;
|
|
2738
2815
|
this.IMAGE_CAPTURE_COEFFICIENT = this.calculateImageCaptureCoefficient();
|
|
2739
2816
|
/**
|
|
2740
2817
|
* Fabric defaults to only 2 decimal places when saving, which causes havoc on the scaling of large images.
|
|
@@ -3153,6 +3230,7 @@ class AbstractInteractiveCanvas {
|
|
|
3153
3230
|
targetFindTolerance: 4,
|
|
3154
3231
|
splitByGrapheme: true,
|
|
3155
3232
|
editable: false, // Only enable on double-click
|
|
3233
|
+
editingBorderColor: '#2196F3',
|
|
3156
3234
|
padding: 0,
|
|
3157
3235
|
cornerSize: 8,
|
|
3158
3236
|
touchCornerSize: 12
|
|
@@ -3604,7 +3682,14 @@ class AbstractInteractiveCanvas {
|
|
|
3604
3682
|
* Redraw the canvas.
|
|
3605
3683
|
*/
|
|
3606
3684
|
redraw() {
|
|
3607
|
-
this.
|
|
3685
|
+
if (this.redrawScheduled) {
|
|
3686
|
+
return;
|
|
3687
|
+
}
|
|
3688
|
+
this.redrawScheduled = true;
|
|
3689
|
+
requestAnimationFrame(() => {
|
|
3690
|
+
this.fabricCanvas.requestRenderAll();
|
|
3691
|
+
this.redrawScheduled = false;
|
|
3692
|
+
});
|
|
3608
3693
|
}
|
|
3609
3694
|
syncObjectList() {
|
|
3610
3695
|
const newObjectList = _(this.fabricCanvas.getObjects())
|
|
@@ -9,6 +9,7 @@ export declare class AdvancedLayoutManager extends AbstractLayoutManager {
|
|
|
9
9
|
private repositionCutoffs;
|
|
10
10
|
private repositionBackgrounds;
|
|
11
11
|
private resizeCanvas;
|
|
12
|
+
private dimensionsLayoutScheduled;
|
|
12
13
|
constructor(canvas: IInteractiveCanvas);
|
|
13
14
|
onCanvasDimensionsChange(): void;
|
|
14
15
|
onTextChange(): void;
|
|
@@ -63,6 +63,8 @@ export declare class Text extends AbstractCanvasObject<ExtendedFabricTextbox> im
|
|
|
63
63
|
private readonly text$;
|
|
64
64
|
private readonly textSelection$;
|
|
65
65
|
static readonly NEW_LINE: string;
|
|
66
|
+
private notifyCanvasTimeout;
|
|
67
|
+
private readonly NOTIFY_DELAY_MS;
|
|
66
68
|
constructor(canvas: IInteractiveCanvas, fabricObject: fabric.Textbox, persistedField?: CanvasObjectData);
|
|
67
69
|
/**
|
|
68
70
|
* @override
|