mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): image loading fallback for raster layers
This commit is contained in:
parent
51de25122a
commit
40cab08133
@ -115,6 +115,7 @@
|
|||||||
"githubLabel": "Github",
|
"githubLabel": "Github",
|
||||||
"goTo": "Go to",
|
"goTo": "Go to",
|
||||||
"hotkeysLabel": "Hotkeys",
|
"hotkeysLabel": "Hotkeys",
|
||||||
|
"loadingImage": "Loading Image",
|
||||||
"imageFailedToLoad": "Unable to Load Image",
|
"imageFailedToLoad": "Unable to Load Image",
|
||||||
"img2img": "Image To Image",
|
"img2img": "Image To Image",
|
||||||
"inpaint": "inpaint",
|
"inpaint": "inpaint",
|
||||||
|
@ -2,6 +2,7 @@ import { rgbaColorToString } from 'features/canvas/util/colorToString';
|
|||||||
import { getObjectGroupId } from 'features/controlLayers/konva/naming';
|
import { getObjectGroupId } from 'features/controlLayers/konva/naming';
|
||||||
import type { BrushLine, EraserLine, ImageObject, RectShape } from 'features/controlLayers/store/types';
|
import type { BrushLine, EraserLine, ImageObject, RectShape } from 'features/controlLayers/store/types';
|
||||||
import { DEFAULT_RGBA_COLOR } from 'features/controlLayers/store/types';
|
import { DEFAULT_RGBA_COLOR } from 'features/controlLayers/store/types';
|
||||||
|
import { t } from 'i18next';
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import { getImageDTO } from 'services/api/endpoints/images';
|
import { getImageDTO } from 'services/api/endpoints/images';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
@ -81,16 +82,58 @@ export const createRectShape = (rectShape: RectShape, layerObjectGroup: Konva.Gr
|
|||||||
return konvaRect;
|
return konvaRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createImageObject = async (
|
const createImagePlaceholderGroup = (
|
||||||
|
imageObject: ImageObject
|
||||||
|
): { konvaPlaceholderGroup: Konva.Group; onError: () => void; onLoading: () => void; onLoaded: () => void } => {
|
||||||
|
const { width, height } = imageObject.image;
|
||||||
|
const konvaPlaceholderGroup = new Konva.Group({ name: 'image-placeholder', listening: false });
|
||||||
|
const konvaPlaceholderRect = new Konva.Rect({
|
||||||
|
fill: 'hsl(220 12% 45% / 1)', // 'base.500'
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
|
const konvaPlaceholderText = new Konva.Text({
|
||||||
|
name: 'image-placeholder-text',
|
||||||
|
fill: 'hsl(220 12% 10% / 1)', // 'base.900'
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
align: 'center',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
fontFamily: '"Inter Variable", sans-serif',
|
||||||
|
fontSize: width / 16,
|
||||||
|
fontStyle: '600',
|
||||||
|
text: 'Loading Image',
|
||||||
|
listening: false,
|
||||||
|
});
|
||||||
|
konvaPlaceholderGroup.add(konvaPlaceholderRect);
|
||||||
|
konvaPlaceholderGroup.add(konvaPlaceholderText);
|
||||||
|
|
||||||
|
const onError = () => {
|
||||||
|
konvaPlaceholderText.text(t('common.imageFailedToLoad', 'Image Failed to Load'));
|
||||||
|
};
|
||||||
|
const onLoading = () => {
|
||||||
|
konvaPlaceholderText.text(t('common.loadingImage', 'Loading Image'));
|
||||||
|
};
|
||||||
|
const onLoaded = () => {
|
||||||
|
konvaPlaceholderGroup.destroy();
|
||||||
|
};
|
||||||
|
return { konvaPlaceholderGroup, onError, onLoading, onLoaded };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createImageObjectGroup = async (
|
||||||
imageObject: ImageObject,
|
imageObject: ImageObject,
|
||||||
layerObjectGroup: Konva.Group,
|
layerObjectGroup: Konva.Group,
|
||||||
name: string
|
name: string
|
||||||
): Promise<Konva.Image | null> => {
|
): Promise<Konva.Group> => {
|
||||||
const imageDTO = await getImageDTO(imageObject.image.name);
|
const konvaImageGroup = new Konva.Group({ id: imageObject.id, name, listening: false });
|
||||||
if (!imageDTO) {
|
const placeholder = createImagePlaceholderGroup(imageObject);
|
||||||
return null;
|
konvaImageGroup.add(placeholder.konvaPlaceholderGroup);
|
||||||
}
|
layerObjectGroup.add(konvaImageGroup);
|
||||||
return new Promise((resolve) => {
|
getImageDTO(imageObject.image.name).then((imageDTO) => {
|
||||||
|
if (!imageDTO) {
|
||||||
|
placeholder.onError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const imageEl = new Image();
|
const imageEl = new Image();
|
||||||
imageEl.onload = () => {
|
imageEl.onload = () => {
|
||||||
const konvaImage = new Konva.Image({
|
const konvaImage = new Konva.Image({
|
||||||
@ -99,15 +142,16 @@ export const createImageObject = async (
|
|||||||
listening: false,
|
listening: false,
|
||||||
image: imageEl,
|
image: imageEl,
|
||||||
});
|
});
|
||||||
layerObjectGroup.add(konvaImage);
|
placeholder.onLoaded();
|
||||||
resolve(konvaImage);
|
konvaImageGroup.add(konvaImage);
|
||||||
};
|
};
|
||||||
imageEl.onerror = () => {
|
imageEl.onerror = () => {
|
||||||
resolve(null);
|
placeholder.onError();
|
||||||
};
|
};
|
||||||
imageEl.id = imageObject.id;
|
imageEl.id = imageObject.id;
|
||||||
imageEl.src = imageDTO.image_url;
|
imageEl.src = imageDTO.image_url;
|
||||||
});
|
});
|
||||||
|
return konvaImageGroup;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Creates a konva group for a layer's objects.
|
* Creates a konva group for a layer's objects.
|
||||||
|
@ -9,14 +9,13 @@ import {
|
|||||||
import {
|
import {
|
||||||
createBrushLine,
|
createBrushLine,
|
||||||
createEraserLine,
|
createEraserLine,
|
||||||
createImageObject,
|
createImageObjectGroup,
|
||||||
createObjectGroup,
|
createObjectGroup,
|
||||||
createRectShape,
|
createRectShape,
|
||||||
} from 'features/controlLayers/konva/renderers/objects';
|
} from 'features/controlLayers/konva/renderers/objects';
|
||||||
import { getScaledFlooredCursorPosition, mapId, selectRasterObjects } from 'features/controlLayers/konva/util';
|
import { getScaledFlooredCursorPosition, mapId, selectRasterObjects } from 'features/controlLayers/konva/util';
|
||||||
import type { RasterLayer, Tool } from 'features/controlLayers/store/types';
|
import type { RasterLayer, Tool } from 'features/controlLayers/store/types';
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import { assert } from 'tsafe';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logic for creating and rendering raster layers.
|
* Logic for creating and rendering raster layers.
|
||||||
@ -109,10 +108,7 @@ export const renderRasterLayer = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < layerState.objects.length; i++) {
|
for (const obj of layerState.objects) {
|
||||||
const obj = layerState.objects[i];
|
|
||||||
assert(obj);
|
|
||||||
const zIndex = layerState.objects.length - i;
|
|
||||||
if (obj.type === 'brush_line') {
|
if (obj.type === 'brush_line') {
|
||||||
const konvaBrushLine =
|
const konvaBrushLine =
|
||||||
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
||||||
@ -121,7 +117,6 @@ export const renderRasterLayer = async (
|
|||||||
if (konvaBrushLine.points().length !== obj.points.length) {
|
if (konvaBrushLine.points().length !== obj.points.length) {
|
||||||
konvaBrushLine.points(obj.points);
|
konvaBrushLine.points(obj.points);
|
||||||
}
|
}
|
||||||
konvaBrushLine.zIndex(zIndex);
|
|
||||||
} else if (obj.type === 'eraser_line') {
|
} else if (obj.type === 'eraser_line') {
|
||||||
const konvaEraserLine =
|
const konvaEraserLine =
|
||||||
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
||||||
@ -130,17 +125,14 @@ export const renderRasterLayer = async (
|
|||||||
if (konvaEraserLine.points().length !== obj.points.length) {
|
if (konvaEraserLine.points().length !== obj.points.length) {
|
||||||
konvaEraserLine.points(obj.points);
|
konvaEraserLine.points(obj.points);
|
||||||
}
|
}
|
||||||
konvaEraserLine.zIndex(zIndex);
|
|
||||||
} else if (obj.type === 'rect_shape') {
|
} else if (obj.type === 'rect_shape') {
|
||||||
const konvaRect =
|
if (!konvaObjectGroup.findOne<Konva.Rect>(`#${obj.id}`)) {
|
||||||
konvaObjectGroup.findOne<Konva.Rect>(`#${obj.id}`) ??
|
|
||||||
createRectShape(obj, konvaObjectGroup, RASTER_LAYER_RECT_SHAPE_NAME);
|
createRectShape(obj, konvaObjectGroup, RASTER_LAYER_RECT_SHAPE_NAME);
|
||||||
konvaRect.zIndex(zIndex);
|
}
|
||||||
} else if (obj.type === 'image') {
|
} else if (obj.type === 'image') {
|
||||||
const konvaImage =
|
if (!konvaObjectGroup.findOne<Konva.Group>(`#${obj.id}`)) {
|
||||||
konvaObjectGroup.findOne<Konva.Image>(`#${obj.id}`) ??
|
createImageObjectGroup(obj, konvaObjectGroup, RASTER_LAYER_IMAGE_NAME);
|
||||||
(await createImageObject(obj, konvaObjectGroup, RASTER_LAYER_IMAGE_NAME));
|
}
|
||||||
konvaImage?.zIndex(zIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user