Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ type CanvasCacheModuleConfig = {

const DEFAULT_CONFIG: CanvasCacheModuleConfig = {
imageNameCacheSize: 1000,
imageDataCacheSize: 32,
imageDataCacheSize: 64,
transparencyCalculationCacheSize: 1000,
canvasElementCacheSize: 32,
canvasElementCacheSize: 128,
generationModeCacheSize: 100,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ export abstract class CanvasEntityAdapterBase<T extends CanvasEntityState, U ext
*/
selectPosition = createSelector(this.selectState, (entity) => entity?.position);

syncIsOnscreen = () => {
syncIsOnscreen = rafThrottle(() => {
const stageRect = this.manager.stage.getScaledStageRect();
const isOnScreen = this.checkIntersection(stageRect);
const prevIsOnScreen = this.$isOnScreen.get();
Expand All @@ -334,17 +334,17 @@ export abstract class CanvasEntityAdapterBase<T extends CanvasEntityState, U ext
this.log.trace(`Moved ${isOnScreen ? 'on-screen' : 'off-screen'}`);
}
this.syncVisibility();
};
});

syncIntersectsBbox = () => {
syncIntersectsBbox = rafThrottle(() => {
const bboxRect = this.manager.stateApi.getBbox().rect;
const intersectsBbox = this.checkIntersection(bboxRect);
const prevIntersectsBbox = this.$intersectsBbox.get();
this.$intersectsBbox.set(intersectsBbox);
if (prevIntersectsBbox !== intersectsBbox) {
this.log.trace(`Moved ${intersectsBbox ? 'into bbox' : 'out of bbox'}`);
}
};
});

checkIntersection = (rect: Rect): boolean => {
const entityRect = this.transformer.$pixelRect.get();
Expand Down Expand Up @@ -526,8 +526,13 @@ export abstract class CanvasEntityAdapterBase<T extends CanvasEntityState, U ext
return;
}
this.log.trace(isVisible ? 'Showing' : 'Hiding');
this.konva.layer.visible(isVisible);
if (isVisible) {
// Re-attach the layer to the stage before making it visible. The layer was detached from the DOM when hidden
// to free browser compositing resources (each Konva.Layer is a separate <canvas> element).
if (!this.konva.layer.getParent()) {
this.manager.stage.addLayer(this.konva.layer);
}
this.konva.layer.visible(true);
/**
* When a layer is created and initially not visible, its compositing rect won't be set up properly. Then, when
* we show it in this method, it the layer will not render as it should.
Expand All @@ -543,6 +548,13 @@ export abstract class CanvasEntityAdapterBase<T extends CanvasEntityState, U ext
this.renderer.updateCompositingRectPosition();
this.renderer.updateCompositingRectFill();
this.renderer.updateOpacity();
// Restore correct z-order after re-attaching
this.manager.entityRenderer.arrangeEntities(this.manager.stateApi.runSelector(selectCanvasSlice), null);
} else {
this.konva.layer.visible(false);
// Detach the layer from the stage to remove its <canvas> element from the DOM. This frees browser compositing
// resources. The layer object is kept alive and can be re-attached when shown again.
this.konva.layer.remove();
}
this.renderer.syncKonvaCache();
};
Expand Down
Loading