tidy(ui): naming things

This commit is contained in:
psychedelicious 2024-06-26 21:05:50 +10:00
parent f57df46995
commit d3d0ac7327
7 changed files with 108 additions and 108 deletions

View File

@ -138,13 +138,13 @@ export class KonvaNodeManager {
new CanvasDocumentSizeOverlay(), new CanvasDocumentSizeOverlay(),
new CanvasStagingArea() new CanvasStagingArea()
); );
this.stage.add(this.preview.konvaLayer); this.stage.add(this.preview.layer);
this.background = new CanvasBackground(); this.background = new CanvasBackground();
this.stage.add(this.background.konvaLayer); this.stage.add(this.background.layer);
this.inpaintMask = new CanvasInpaintMask(this.stateApi.getInpaintMaskState(), this.stateApi.onPosChanged); this.inpaintMask = new CanvasInpaintMask(this.stateApi.getInpaintMaskState(), this.stateApi.onPosChanged);
this.stage.add(this.inpaintMask.konvaLayer); this.stage.add(this.inpaintMask.layer);
this.layers = new Map(); this.layers = new Map();
this.regions = new Map(); this.regions = new Map();
@ -167,7 +167,7 @@ export class KonvaNodeManager {
if (!adapter) { if (!adapter) {
adapter = new CanvasLayer(entity, this.stateApi.onPosChanged); adapter = new CanvasLayer(entity, this.stateApi.onPosChanged);
this.layers.set(adapter.id, adapter); this.layers.set(adapter.id, adapter);
this.stage.add(adapter.konvaLayer); this.stage.add(adapter.layer);
} }
adapter.render(entity, toolState.selected); adapter.render(entity, toolState.selected);
} }
@ -192,7 +192,7 @@ export class KonvaNodeManager {
if (!adapter) { if (!adapter) {
adapter = new CanvasRegion(entity, this.stateApi.onPosChanged); adapter = new CanvasRegion(entity, this.stateApi.onPosChanged);
this.regions.set(adapter.id, adapter); this.regions.set(adapter.id, adapter);
this.stage.add(adapter.konvaLayer); this.stage.add(adapter.layer);
} }
adapter.render(entity, toolState.selected, selectedEntity, maskOpacity); adapter.render(entity, toolState.selected, selectedEntity, maskOpacity);
} }
@ -222,7 +222,7 @@ export class KonvaNodeManager {
if (!adapter) { if (!adapter) {
adapter = new CanvasControlAdapter(entity); adapter = new CanvasControlAdapter(entity);
this.controlAdapters.set(adapter.id, adapter); this.controlAdapters.set(adapter.id, adapter);
this.stage.add(adapter.konvaLayer); this.stage.add(adapter.layer);
} }
adapter.render(entity); adapter.render(entity);
} }
@ -234,18 +234,18 @@ export class KonvaNodeManager {
const controlAdapters = getControlAdaptersState().entities; const controlAdapters = getControlAdaptersState().entities;
const regions = getRegionsState().entities; const regions = getRegionsState().entities;
let zIndex = 0; let zIndex = 0;
this.background.konvaLayer.zIndex(++zIndex); this.background.layer.zIndex(++zIndex);
for (const layer of layers) { for (const layer of layers) {
this.layers.get(layer.id)?.konvaLayer.zIndex(++zIndex); this.layers.get(layer.id)?.layer.zIndex(++zIndex);
} }
for (const ca of controlAdapters) { for (const ca of controlAdapters) {
this.controlAdapters.get(ca.id)?.konvaLayer.zIndex(++zIndex); this.controlAdapters.get(ca.id)?.layer.zIndex(++zIndex);
} }
for (const rg of regions) { for (const rg of regions) {
this.regions.get(rg.id)?.konvaLayer.zIndex(++zIndex); this.regions.get(rg.id)?.layer.zIndex(++zIndex);
} }
this.inpaintMask?.konvaLayer.zIndex(++zIndex); this.inpaintMask?.layer.zIndex(++zIndex);
this.preview.konvaLayer.zIndex(++zIndex); this.preview.layer.zIndex(++zIndex);
} }
renderDocumentSizeOverlay() { renderDocumentSizeOverlay() {
@ -297,8 +297,8 @@ export class KonvaNodeManager {
} }
getInpaintMaskLayerClone(): Konva.Layer { getInpaintMaskLayerClone(): Konva.Layer {
const layerClone = this.inpaintMask.konvaLayer.clone(); const layerClone = this.inpaintMask.layer.clone();
const objectGroupClone = this.inpaintMask.konvaObjectGroup.clone(); const objectGroupClone = this.inpaintMask.group.clone();
layerClone.destroyChildren(); layerClone.destroyChildren();
layerClone.add(objectGroupClone); layerClone.add(objectGroupClone);
@ -315,8 +315,8 @@ export class KonvaNodeManager {
const canvasRegion = this.regions.get(id); const canvasRegion = this.regions.get(id);
assert(canvasRegion, `Canvas region with id ${id} not found`); assert(canvasRegion, `Canvas region with id ${id} not found`);
const layerClone = canvasRegion.konvaLayer.clone(); const layerClone = canvasRegion.layer.clone();
const objectGroupClone = canvasRegion.konvaObjectGroup.clone(); const objectGroupClone = canvasRegion.group.clone();
layerClone.destroyChildren(); layerClone.destroyChildren();
layerClone.add(objectGroupClone); layerClone.add(objectGroupClone);

View File

@ -29,14 +29,14 @@ const getGridSpacing = (scale: number): number => {
}; };
export class CanvasBackground { export class CanvasBackground {
konvaLayer: Konva.Layer; layer: Konva.Layer;
constructor() { constructor() {
this.konvaLayer = new Konva.Layer({ listening: false }); this.layer = new Konva.Layer({ listening: false });
} }
renderBackground(stage: Konva.Stage): void { renderBackground(stage: Konva.Stage): void {
this.konvaLayer.zIndex(0); this.layer.zIndex(0);
const scale = stage.scaleX(); const scale = stage.scaleX();
const gridSpacing = getGridSpacing(scale); const gridSpacing = getGridSpacing(scale);
const x = stage.x(); const x = stage.x();
@ -80,11 +80,11 @@ export class CanvasBackground {
let _x = 0; let _x = 0;
let _y = 0; let _y = 0;
this.konvaLayer.destroyChildren(); this.layer.destroyChildren();
for (let i = 0; i < xSteps; i++) { for (let i = 0; i < xSteps; i++) {
_x = gridFullRect.x1 + i * gridSpacing; _x = gridFullRect.x1 + i * gridSpacing;
this.konvaLayer.add( this.layer.add(
new Konva.Line({ new Konva.Line({
x: _x, x: _x,
y: gridFullRect.y1, y: gridFullRect.y1,
@ -97,7 +97,7 @@ export class CanvasBackground {
} }
for (let i = 0; i < ySteps; i++) { for (let i = 0; i < ySteps; i++) {
_y = gridFullRect.y1 + i * gridSpacing; _y = gridFullRect.y1 + i * gridSpacing;
this.konvaLayer.add( this.layer.add(
new Konva.Line({ new Konva.Line({
x: gridFullRect.x1, x: gridFullRect.x1,
y: _y, y: _y,

View File

@ -9,31 +9,31 @@ import { KonvaImage } from './objects';
export class CanvasControlAdapter { export class CanvasControlAdapter {
id: string; id: string;
konvaLayer: Konva.Layer; layer: Konva.Layer;
konvaObjectGroup: Konva.Group; group: Konva.Group;
konvaImageObject: KonvaImage | null; image: KonvaImage | null;
constructor(entity: ControlAdapterEntity) { constructor(entity: ControlAdapterEntity) {
const { id } = entity; const { id } = entity;
this.id = id; this.id = id;
this.konvaLayer = new Konva.Layer({ this.layer = new Konva.Layer({
id, id,
imageSmoothingEnabled: false, imageSmoothingEnabled: false,
listening: false, listening: false,
}); });
this.konvaObjectGroup = new Konva.Group({ this.group = new Konva.Group({
id: getObjectGroupId(this.konvaLayer.id(), uuidv4()), id: getObjectGroupId(this.layer.id(), uuidv4()),
listening: false, listening: false,
}); });
this.konvaLayer.add(this.konvaObjectGroup); this.layer.add(this.group);
this.konvaImageObject = null; this.image = null;
} }
async render(entity: ControlAdapterEntity) { async render(entity: ControlAdapterEntity) {
const imageObject = entity.processedImageObject ?? entity.imageObject; const imageObject = entity.processedImageObject ?? entity.imageObject;
if (!imageObject) { if (!imageObject) {
if (this.konvaImageObject) { if (this.image) {
this.konvaImageObject.destroy(); this.image.destroy();
} }
return; return;
} }
@ -42,8 +42,8 @@ export class CanvasControlAdapter {
const visible = entity.isEnabled; const visible = entity.isEnabled;
const filters = entity.filter === 'LightnessToAlphaFilter' ? [LightnessToAlphaFilter] : []; const filters = entity.filter === 'LightnessToAlphaFilter' ? [LightnessToAlphaFilter] : [];
if (!this.konvaImageObject) { if (!this.image) {
this.konvaImageObject = await new KonvaImage({ this.image = await new KonvaImage({
imageObject, imageObject,
onLoad: (konvaImage) => { onLoad: (konvaImage) => {
konvaImage.filters(filters); konvaImage.filters(filters);
@ -52,25 +52,25 @@ export class CanvasControlAdapter {
konvaImage.visible(visible); konvaImage.visible(visible);
}, },
}); });
this.konvaObjectGroup.add(this.konvaImageObject.konvaImageGroup); this.group.add(this.image.konvaImageGroup);
} }
if (this.konvaImageObject.isLoading || this.konvaImageObject.isError) { if (this.image.isLoading || this.image.isError) {
return; return;
} }
if (this.konvaImageObject.imageName !== imageObject.image.name) { if (this.image.imageName !== imageObject.image.name) {
this.konvaImageObject.updateImageSource(imageObject.image.name); this.image.updateImageSource(imageObject.image.name);
} }
if (this.konvaImageObject.konvaImage) { if (this.image.konvaImage) {
if (!isEqual(this.konvaImageObject.konvaImage.filters(), filters)) { if (!isEqual(this.image.konvaImage.filters(), filters)) {
this.konvaImageObject.konvaImage.filters(filters); this.image.konvaImage.filters(filters);
this.konvaImageObject.konvaImage.cache(); this.image.konvaImage.cache();
} }
this.konvaImageObject.konvaImage.opacity(opacity); this.image.konvaImage.opacity(opacity);
this.konvaImageObject.konvaImage.visible(visible); this.image.konvaImage.visible(visible);
} }
} }
destroy(): void { destroy(): void {
this.konvaLayer.destroy(); this.layer.destroy();
} }
} }

View File

@ -11,15 +11,15 @@ import { v4 as uuidv4 } from 'uuid';
export class CanvasInpaintMask { export class CanvasInpaintMask {
id: string; id: string;
konvaLayer: Konva.Layer; layer: Konva.Layer;
konvaObjectGroup: Konva.Group; group: Konva.Group;
compositingRect: Konva.Rect; compositingRect: Konva.Rect;
objects: Map<string, KonvaBrushLine | KonvaEraserLine | KonvaRect>; objects: Map<string, KonvaBrushLine | KonvaEraserLine | KonvaRect>;
constructor(entity: InpaintMaskEntity, onPosChanged: StateApi['onPosChanged']) { constructor(entity: InpaintMaskEntity, onPosChanged: StateApi['onPosChanged']) {
this.id = entity.id; this.id = entity.id;
this.konvaLayer = new Konva.Layer({ this.layer = new Konva.Layer({
id: entity.id, id: entity.id,
draggable: true, draggable: true,
dragDistance: 0, dragDistance: 0,
@ -27,21 +27,21 @@ export class CanvasInpaintMask {
// When a drag on the layer finishes, update the layer's position in state. During the drag, konva handles changing // When a drag on the layer finishes, update the layer's position in state. During the drag, konva handles changing
// the position - we do not need to call this on the `dragmove` event. // the position - we do not need to call this on the `dragmove` event.
this.konvaLayer.on('dragend', function (e) { this.layer.on('dragend', function (e) {
onPosChanged({ id: entity.id, x: Math.floor(e.target.x()), y: Math.floor(e.target.y()) }, 'inpaint_mask'); onPosChanged({ id: entity.id, x: Math.floor(e.target.x()), y: Math.floor(e.target.y()) }, 'inpaint_mask');
}); });
this.konvaObjectGroup = new Konva.Group({ this.group = new Konva.Group({
id: getObjectGroupId(this.konvaLayer.id(), uuidv4()), id: getObjectGroupId(this.layer.id(), uuidv4()),
listening: false, listening: false,
}); });
this.konvaLayer.add(this.konvaObjectGroup); this.layer.add(this.group);
this.compositingRect = new Konva.Rect({ listening: false }); this.compositingRect = new Konva.Rect({ listening: false });
this.konvaLayer.add(this.compositingRect); this.layer.add(this.compositingRect);
this.objects = new Map(); this.objects = new Map();
} }
destroy(): void { destroy(): void {
this.konvaLayer.destroy(); this.layer.destroy();
} }
async render( async render(
@ -51,7 +51,7 @@ export class CanvasInpaintMask {
maskOpacity: number maskOpacity: number
) { ) {
// Update the layer's position and listening state // Update the layer's position and listening state
this.konvaLayer.setAttrs({ this.layer.setAttrs({
listening: selectedTool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events listening: selectedTool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events
x: Math.floor(inpaintMaskState.x), x: Math.floor(inpaintMaskState.x),
y: Math.floor(inpaintMaskState.y), y: Math.floor(inpaintMaskState.y),
@ -81,7 +81,7 @@ export class CanvasInpaintMask {
if (!brushLine) { if (!brushLine) {
brushLine = new KonvaBrushLine({ brushLine: obj }); brushLine = new KonvaBrushLine({ brushLine: obj });
this.objects.set(brushLine.id, brushLine); this.objects.set(brushLine.id, brushLine);
this.konvaObjectGroup.add(brushLine.konvaLineGroup); this.group.add(brushLine.konvaLineGroup);
groupNeedsCache = true; groupNeedsCache = true;
} }
@ -96,7 +96,7 @@ export class CanvasInpaintMask {
if (!eraserLine) { if (!eraserLine) {
eraserLine = new KonvaEraserLine({ eraserLine: obj }); eraserLine = new KonvaEraserLine({ eraserLine: obj });
this.objects.set(eraserLine.id, eraserLine); this.objects.set(eraserLine.id, eraserLine);
this.konvaObjectGroup.add(eraserLine.konvaLineGroup); this.group.add(eraserLine.konvaLineGroup);
groupNeedsCache = true; groupNeedsCache = true;
} }
@ -111,37 +111,37 @@ export class CanvasInpaintMask {
if (!rect) { if (!rect) {
rect = new KonvaRect({ rectShape: obj }); rect = new KonvaRect({ rectShape: obj });
this.objects.set(rect.id, rect); this.objects.set(rect.id, rect);
this.konvaObjectGroup.add(rect.konvaRect); this.group.add(rect.konvaRect);
groupNeedsCache = true; groupNeedsCache = true;
} }
} }
} }
// Only update layer visibility if it has changed. // Only update layer visibility if it has changed.
if (this.konvaLayer.visible() !== inpaintMaskState.isEnabled) { if (this.layer.visible() !== inpaintMaskState.isEnabled) {
this.konvaLayer.visible(inpaintMaskState.isEnabled); this.layer.visible(inpaintMaskState.isEnabled);
groupNeedsCache = true; groupNeedsCache = true;
} }
if (this.objects.size === 0) { if (this.objects.size === 0) {
// No objects - clear the cache to reset the previous pixel data // No objects - clear the cache to reset the previous pixel data
this.konvaObjectGroup.clearCache(); this.group.clearCache();
return; return;
} }
// We must clear the cache first so Konva will re-draw the group with the new compositing rect // We must clear the cache first so Konva will re-draw the group with the new compositing rect
if (this.konvaObjectGroup.isCached()) { if (this.group.isCached()) {
this.konvaObjectGroup.clearCache(); this.group.clearCache();
} }
// The user is allowed to reduce mask opacity to 0, but we need the opacity for the compositing rect to work // The user is allowed to reduce mask opacity to 0, but we need the opacity for the compositing rect to work
this.konvaObjectGroup.opacity(1); this.group.opacity(1);
this.compositingRect.setAttrs({ this.compositingRect.setAttrs({
// The rect should be the size of the layer - use the fast method if we don't have a pixel-perfect bbox already // The rect should be the size of the layer - use the fast method if we don't have a pixel-perfect bbox already
...(!inpaintMaskState.bboxNeedsUpdate && inpaintMaskState.bbox ...(!inpaintMaskState.bboxNeedsUpdate && inpaintMaskState.bbox
? inpaintMaskState.bbox ? inpaintMaskState.bbox
: getLayerBboxFast(this.konvaLayer)), : getLayerBboxFast(this.layer)),
fill: rgbColor, fill: rgbColor,
opacity: maskOpacity, opacity: maskOpacity,
// Draw this rect only where there are non-transparent pixels under it (e.g. the mask shapes) // Draw this rect only where there are non-transparent pixels under it (e.g. the mask shapes)

View File

@ -9,14 +9,14 @@ import { v4 as uuidv4 } from 'uuid';
export class CanvasLayer { export class CanvasLayer {
id: string; id: string;
konvaLayer: Konva.Layer; layer: Konva.Layer;
konvaObjectGroup: Konva.Group; group: Konva.Group;
objects: Map<string, KonvaBrushLine | KonvaEraserLine | KonvaRect | KonvaImage>; objects: Map<string, KonvaBrushLine | KonvaEraserLine | KonvaRect | KonvaImage>;
constructor(entity: LayerEntity, onPosChanged: StateApi['onPosChanged']) { constructor(entity: LayerEntity, onPosChanged: StateApi['onPosChanged']) {
this.id = entity.id; this.id = entity.id;
this.konvaLayer = new Konva.Layer({ this.layer = new Konva.Layer({
id: entity.id, id: entity.id,
draggable: true, draggable: true,
dragDistance: 0, dragDistance: 0,
@ -24,25 +24,25 @@ export class CanvasLayer {
// When a drag on the layer finishes, update the layer's position in state. During the drag, konva handles changing // When a drag on the layer finishes, update the layer's position in state. During the drag, konva handles changing
// the position - we do not need to call this on the `dragmove` event. // the position - we do not need to call this on the `dragmove` event.
this.konvaLayer.on('dragend', function (e) { this.layer.on('dragend', function (e) {
onPosChanged({ id: entity.id, x: Math.floor(e.target.x()), y: Math.floor(e.target.y()) }, 'layer'); onPosChanged({ id: entity.id, x: Math.floor(e.target.x()), y: Math.floor(e.target.y()) }, 'layer');
}); });
const konvaObjectGroup = new Konva.Group({ const group = new Konva.Group({
id: getObjectGroupId(this.konvaLayer.id(), uuidv4()), id: getObjectGroupId(this.layer.id(), uuidv4()),
listening: false, listening: false,
}); });
this.konvaObjectGroup = konvaObjectGroup; this.group = group;
this.konvaLayer.add(this.konvaObjectGroup); this.layer.add(this.group);
this.objects = new Map(); this.objects = new Map();
} }
destroy(): void { destroy(): void {
this.konvaLayer.destroy(); this.layer.destroy();
} }
async render(layerState: LayerEntity, selectedTool: Tool) { async render(layerState: LayerEntity, selectedTool: Tool) {
// Update the layer's position and listening state // Update the layer's position and listening state
this.konvaLayer.setAttrs({ this.layer.setAttrs({
listening: selectedTool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events listening: selectedTool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events
x: Math.floor(layerState.x), x: Math.floor(layerState.x),
y: Math.floor(layerState.y), y: Math.floor(layerState.y),
@ -65,7 +65,7 @@ export class CanvasLayer {
if (!brushLine) { if (!brushLine) {
brushLine = new KonvaBrushLine({ brushLine: obj }); brushLine = new KonvaBrushLine({ brushLine: obj });
this.objects.set(brushLine.id, brushLine); this.objects.set(brushLine.id, brushLine);
this.konvaObjectGroup.add(brushLine.konvaLineGroup); this.group.add(brushLine.konvaLineGroup);
} }
if (obj.points.length !== brushLine.konvaLine.points().length) { if (obj.points.length !== brushLine.konvaLine.points().length) {
brushLine.konvaLine.points(obj.points); brushLine.konvaLine.points(obj.points);
@ -77,7 +77,7 @@ export class CanvasLayer {
if (!eraserLine) { if (!eraserLine) {
eraserLine = new KonvaEraserLine({ eraserLine: obj }); eraserLine = new KonvaEraserLine({ eraserLine: obj });
this.objects.set(eraserLine.id, eraserLine); this.objects.set(eraserLine.id, eraserLine);
this.konvaObjectGroup.add(eraserLine.konvaLineGroup); this.group.add(eraserLine.konvaLineGroup);
} }
if (obj.points.length !== eraserLine.konvaLine.points().length) { if (obj.points.length !== eraserLine.konvaLine.points().length) {
eraserLine.konvaLine.points(obj.points); eraserLine.konvaLine.points(obj.points);
@ -89,7 +89,7 @@ export class CanvasLayer {
if (!rect) { if (!rect) {
rect = new KonvaRect({ rectShape: obj }); rect = new KonvaRect({ rectShape: obj });
this.objects.set(rect.id, rect); this.objects.set(rect.id, rect);
this.konvaObjectGroup.add(rect.konvaRect); this.group.add(rect.konvaRect);
} }
} else if (obj.type === 'image') { } else if (obj.type === 'image') {
let image = this.objects.get(obj.id); let image = this.objects.get(obj.id);
@ -98,7 +98,7 @@ export class CanvasLayer {
if (!image) { if (!image) {
image = await new KonvaImage({ imageObject: obj }); image = await new KonvaImage({ imageObject: obj });
this.objects.set(image.id, image); this.objects.set(image.id, image);
this.konvaObjectGroup.add(image.konvaImageGroup); this.group.add(image.konvaImageGroup);
} }
if (image.imageName !== obj.image.name) { if (image.imageName !== obj.image.name) {
image.updateImageSource(obj.image.name); image.updateImageSource(obj.image.name);
@ -107,8 +107,8 @@ export class CanvasLayer {
} }
// Only update layer visibility if it has changed. // Only update layer visibility if it has changed.
if (this.konvaLayer.visible() !== layerState.isEnabled) { if (this.layer.visible() !== layerState.isEnabled) {
this.konvaLayer.visible(layerState.isEnabled); this.layer.visible(layerState.isEnabled);
} }
// const bboxRect = konvaLayer.findOne<Konva.Rect>(`.${LAYER_BBOX_NAME}`) ?? createBboxRect(layerState, konvaLayer); // const bboxRect = konvaLayer.findOne<Konva.Rect>(`.${LAYER_BBOX_NAME}`) ?? createBboxRect(layerState, konvaLayer);
@ -127,6 +127,6 @@ export class CanvasLayer {
// } else { // } else {
// bboxRect.visible(false); // bboxRect.visible(false);
// } // }
this.konvaObjectGroup.opacity(layerState.opacity); this.group.opacity(layerState.opacity);
} }
} }

View File

@ -6,7 +6,7 @@ import type { CanvasStagingArea } from './stagingArea';
import type { CanvasTool } from './tool'; import type { CanvasTool } from './tool';
export class CanvasPreview { export class CanvasPreview {
konvaLayer: Konva.Layer; layer: Konva.Layer;
tool: CanvasTool; tool: CanvasTool;
bbox: CanvasBbox; bbox: CanvasBbox;
documentSizeOverlay: CanvasDocumentSizeOverlay; documentSizeOverlay: CanvasDocumentSizeOverlay;
@ -18,18 +18,18 @@ export class CanvasPreview {
documentSizeOverlay: CanvasDocumentSizeOverlay, documentSizeOverlay: CanvasDocumentSizeOverlay,
stagingArea: CanvasStagingArea stagingArea: CanvasStagingArea
) { ) {
this.konvaLayer = new Konva.Layer({ listening: true }); this.layer = new Konva.Layer({ listening: true });
this.bbox = bbox; this.bbox = bbox;
this.konvaLayer.add(this.bbox.group); this.layer.add(this.bbox.group);
this.tool = tool; this.tool = tool;
this.konvaLayer.add(this.tool.group); this.layer.add(this.tool.group);
this.documentSizeOverlay = documentSizeOverlay; this.documentSizeOverlay = documentSizeOverlay;
this.konvaLayer.add(this.documentSizeOverlay.group); this.layer.add(this.documentSizeOverlay.group);
this.stagingArea = stagingArea; this.stagingArea = stagingArea;
this.konvaLayer.add(this.stagingArea.group); this.layer.add(this.stagingArea.group);
} }
} }

View File

@ -11,15 +11,15 @@ import { v4 as uuidv4 } from 'uuid';
export class CanvasRegion { export class CanvasRegion {
id: string; id: string;
konvaLayer: Konva.Layer; layer: Konva.Layer;
konvaObjectGroup: Konva.Group; group: Konva.Group;
compositingRect: Konva.Rect; compositingRect: Konva.Rect;
objects: Map<string, KonvaBrushLine | KonvaEraserLine | KonvaRect>; objects: Map<string, KonvaBrushLine | KonvaEraserLine | KonvaRect>;
constructor(entity: RegionEntity, onPosChanged: StateApi['onPosChanged']) { constructor(entity: RegionEntity, onPosChanged: StateApi['onPosChanged']) {
this.id = entity.id; this.id = entity.id;
this.konvaLayer = new Konva.Layer({ this.layer = new Konva.Layer({
id: entity.id, id: entity.id,
draggable: true, draggable: true,
dragDistance: 0, dragDistance: 0,
@ -27,21 +27,21 @@ export class CanvasRegion {
// When a drag on the layer finishes, update the layer's position in state. During the drag, konva handles changing // When a drag on the layer finishes, update the layer's position in state. During the drag, konva handles changing
// the position - we do not need to call this on the `dragmove` event. // the position - we do not need to call this on the `dragmove` event.
this.konvaLayer.on('dragend', function (e) { this.layer.on('dragend', function (e) {
onPosChanged({ id: entity.id, x: Math.floor(e.target.x()), y: Math.floor(e.target.y()) }, 'regional_guidance'); onPosChanged({ id: entity.id, x: Math.floor(e.target.x()), y: Math.floor(e.target.y()) }, 'regional_guidance');
}); });
this.konvaObjectGroup = new Konva.Group({ this.group = new Konva.Group({
id: getObjectGroupId(this.konvaLayer.id(), uuidv4()), id: getObjectGroupId(this.layer.id(), uuidv4()),
listening: false, listening: false,
}); });
this.konvaLayer.add(this.konvaObjectGroup); this.layer.add(this.group);
this.compositingRect = new Konva.Rect({ listening: false }); this.compositingRect = new Konva.Rect({ listening: false });
this.konvaLayer.add(this.compositingRect); this.layer.add(this.compositingRect);
this.objects = new Map(); this.objects = new Map();
} }
destroy(): void { destroy(): void {
this.konvaLayer.destroy(); this.layer.destroy();
} }
async render( async render(
@ -51,7 +51,7 @@ export class CanvasRegion {
maskOpacity: number maskOpacity: number
) { ) {
// Update the layer's position and listening state // Update the layer's position and listening state
this.konvaLayer.setAttrs({ this.layer.setAttrs({
listening: selectedTool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events listening: selectedTool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events
x: Math.floor(regionState.x), x: Math.floor(regionState.x),
y: Math.floor(regionState.y), y: Math.floor(regionState.y),
@ -81,7 +81,7 @@ export class CanvasRegion {
if (!brushLine) { if (!brushLine) {
brushLine = new KonvaBrushLine({ brushLine: obj }); brushLine = new KonvaBrushLine({ brushLine: obj });
this.objects.set(brushLine.id, brushLine); this.objects.set(brushLine.id, brushLine);
this.konvaObjectGroup.add(brushLine.konvaLineGroup); this.group.add(brushLine.konvaLineGroup);
groupNeedsCache = true; groupNeedsCache = true;
} }
@ -96,7 +96,7 @@ export class CanvasRegion {
if (!eraserLine) { if (!eraserLine) {
eraserLine = new KonvaEraserLine({ eraserLine: obj }); eraserLine = new KonvaEraserLine({ eraserLine: obj });
this.objects.set(eraserLine.id, eraserLine); this.objects.set(eraserLine.id, eraserLine);
this.konvaObjectGroup.add(eraserLine.konvaLineGroup); this.group.add(eraserLine.konvaLineGroup);
groupNeedsCache = true; groupNeedsCache = true;
} }
@ -111,34 +111,34 @@ export class CanvasRegion {
if (!rect) { if (!rect) {
rect = new KonvaRect({ rectShape: obj }); rect = new KonvaRect({ rectShape: obj });
this.objects.set(rect.id, rect); this.objects.set(rect.id, rect);
this.konvaObjectGroup.add(rect.konvaRect); this.group.add(rect.konvaRect);
groupNeedsCache = true; groupNeedsCache = true;
} }
} }
} }
// Only update layer visibility if it has changed. // Only update layer visibility if it has changed.
if (this.konvaLayer.visible() !== regionState.isEnabled) { if (this.layer.visible() !== regionState.isEnabled) {
this.konvaLayer.visible(regionState.isEnabled); this.layer.visible(regionState.isEnabled);
groupNeedsCache = true; groupNeedsCache = true;
} }
if (this.objects.size === 0) { if (this.objects.size === 0) {
// No objects - clear the cache to reset the previous pixel data // No objects - clear the cache to reset the previous pixel data
this.konvaObjectGroup.clearCache(); this.group.clearCache();
return; return;
} }
// We must clear the cache first so Konva will re-draw the group with the new compositing rect // We must clear the cache first so Konva will re-draw the group with the new compositing rect
if (this.konvaObjectGroup.isCached()) { if (this.group.isCached()) {
this.konvaObjectGroup.clearCache(); this.group.clearCache();
} }
// The user is allowed to reduce mask opacity to 0, but we need the opacity for the compositing rect to work // The user is allowed to reduce mask opacity to 0, but we need the opacity for the compositing rect to work
this.konvaObjectGroup.opacity(1); this.group.opacity(1);
this.compositingRect.setAttrs({ this.compositingRect.setAttrs({
// The rect should be the size of the layer - use the fast method if we don't have a pixel-perfect bbox already // The rect should be the size of the layer - use the fast method if we don't have a pixel-perfect bbox already
...(!regionState.bboxNeedsUpdate && regionState.bbox ? regionState.bbox : getLayerBboxFast(this.konvaLayer)), ...(!regionState.bboxNeedsUpdate && regionState.bbox ? regionState.bbox : getLayerBboxFast(this.layer)),
fill: rgbColor, fill: rgbColor,
opacity: maskOpacity, opacity: maskOpacity,
// Draw this rect only where there are non-transparent pixels under it (e.g. the mask shapes) // Draw this rect only where there are non-transparent pixels under it (e.g. the mask shapes)