mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-12 19:45:10 -05:00
fix(ui): wonky stage sizing on first visibility
This commit is contained in:
@@ -154,36 +154,36 @@ export class CanvasStageModule extends CanvasModuleBase {
|
||||
// If the stage _had_ no size just before this function was called, that means we've just mounted the stage or
|
||||
// maybe un-hidden it. In that case, the user is about to see the stage for the first time, so we should fit the
|
||||
// layers to the stage. If we don't do this, the layers will not be centered.
|
||||
const shouldFitLayersAfterFittingStage = this.konva.stage.width() === 0 || this.konva.stage.height() === 0;
|
||||
if (this.konva.stage.width() === 0 || this.konva.stage.height() === 0) {
|
||||
// This fit must happen before the stage size is set, else we can end up with a brief flash of an incorrectly
|
||||
// sized and scaled stage.
|
||||
this.fitLayersToStage({ animate: false, targetWidth: containerWidth, targetHeight: containerHeight });
|
||||
}
|
||||
|
||||
this.konva.stage.width(containerWidth);
|
||||
this.konva.stage.height(containerHeight);
|
||||
this.syncStageAttrs();
|
||||
|
||||
if (shouldFitLayersAfterFittingStage) {
|
||||
this.fitLayersToStage();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fits the bbox to the stage. This will center the bbox and scale it to fit the stage with some padding.
|
||||
*/
|
||||
fitBboxToStage = (): void => {
|
||||
fitBboxToStage = (options?: { animate?: boolean; targetWidth?: number; targetHeight?: number }): void => {
|
||||
const { rect } = this.manager.stateApi.getBbox();
|
||||
this.log.trace({ rect }, 'Fitting bbox to stage');
|
||||
this.fitRect(rect);
|
||||
this.fitRect(rect, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fits the visible canvas to the stage. This will center the canvas and scale it to fit the stage with some padding.
|
||||
*/
|
||||
fitLayersToStage = (): void => {
|
||||
fitLayersToStage = (options?: { animate?: boolean; targetWidth?: number; targetHeight?: number }): void => {
|
||||
const rect = this.manager.compositor.getVisibleRectOfType();
|
||||
if (rect.width === 0 || rect.height === 0) {
|
||||
this.fitBboxToStage();
|
||||
this.fitBboxToStage(options);
|
||||
} else {
|
||||
this.log.trace({ rect }, 'Fitting layers to stage');
|
||||
this.fitRect(rect);
|
||||
this.fitRect(rect, options);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -191,12 +191,12 @@ export class CanvasStageModule extends CanvasModuleBase {
|
||||
* Fits the bbox and layers to the stage. The union of the bbox and the visible layers will be centered and scaled
|
||||
* to fit the stage with some padding.
|
||||
*/
|
||||
fitBboxAndLayersToStage = (): void => {
|
||||
fitBboxAndLayersToStage = (options?: { animate?: boolean; targetWidth?: number; targetHeight?: number }): void => {
|
||||
const layersRect = this.manager.compositor.getVisibleRectOfType();
|
||||
const bboxRect = this.manager.stateApi.getBbox().rect;
|
||||
const unionRect = getRectUnion(layersRect, bboxRect);
|
||||
this.log.trace({ bboxRect, layersRect, unionRect }, 'Fitting bbox and layers to stage');
|
||||
this.fitRect(unionRect);
|
||||
this.fitRect(unionRect, options);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -204,16 +204,22 @@ export class CanvasStageModule extends CanvasModuleBase {
|
||||
*
|
||||
* The max scale is 1, but the stage can be scaled down to fit the rect.
|
||||
*/
|
||||
fitRect = (rect: Rect): void => {
|
||||
const { width, height } = this.getSize();
|
||||
fitRect = (rect: Rect, options?: { animate?: boolean; targetWidth?: number; targetHeight?: number }): void => {
|
||||
const size = this.getSize();
|
||||
const { animate, targetWidth, targetHeight } = {
|
||||
animate: true,
|
||||
targetWidth: size.width,
|
||||
targetHeight: size.height,
|
||||
...options,
|
||||
};
|
||||
|
||||
// If the stage has no size, we can't fit anything to it
|
||||
if (width === 0 || height === 0) {
|
||||
if (targetWidth === 0 || targetHeight === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const availableWidth = width - this.config.FIT_LAYERS_TO_STAGE_PADDING_PX * 2;
|
||||
const availableHeight = height - this.config.FIT_LAYERS_TO_STAGE_PADDING_PX * 2;
|
||||
const availableWidth = targetWidth - this.config.FIT_LAYERS_TO_STAGE_PADDING_PX * 2;
|
||||
const availableHeight = targetHeight - this.config.FIT_LAYERS_TO_STAGE_PADDING_PX * 2;
|
||||
|
||||
// Make sure we don't accidentally set the scale to something nonsensical, like a negative number, 0 or something
|
||||
// outside the valid range
|
||||
@@ -231,23 +237,33 @@ export class CanvasStageModule extends CanvasModuleBase {
|
||||
this._intendedScale = scale;
|
||||
this._activeSnapPoint = null;
|
||||
|
||||
const tween = new Konva.Tween({
|
||||
node: this.konva.stage,
|
||||
duration: 0.15,
|
||||
x,
|
||||
y,
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
easing: Konva.Easings.EaseInOut,
|
||||
onUpdate: () => {
|
||||
this.syncStageAttrs();
|
||||
},
|
||||
onFinish: () => {
|
||||
this.syncStageAttrs();
|
||||
tween.destroy();
|
||||
},
|
||||
});
|
||||
tween.play();
|
||||
if (animate) {
|
||||
const tween = new Konva.Tween({
|
||||
node: this.konva.stage,
|
||||
duration: 0.15,
|
||||
x,
|
||||
y,
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
easing: Konva.Easings.EaseInOut,
|
||||
onUpdate: () => {
|
||||
this.syncStageAttrs();
|
||||
},
|
||||
onFinish: () => {
|
||||
this.syncStageAttrs();
|
||||
tween.destroy();
|
||||
},
|
||||
});
|
||||
tween.play();
|
||||
} else {
|
||||
this.konva.stage.setAttrs({
|
||||
x,
|
||||
y,
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
});
|
||||
this.syncStageAttrs();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user