Skip to content

Commit 9b93a21

Browse files
committed
refactor(Stage): 优化图片插入和缩放计算逻辑
将单张图片插入逻辑重构为支持批量插入,并改进缩放计算以适应多元素场景
1 parent 8c76c9b commit 9b93a21

File tree

5 files changed

+67
-38
lines changed

5 files changed

+67
-38
lines changed

src/modules/stage/StageEvent.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,25 +110,13 @@ export default class StageEvent extends EventEmitter implements IStageEvent {
110110
*
111111
* @param imageDataList
112112
*/
113-
private _createImages(imageDataList: ImageData[]): void {
113+
private async _createImages(imageDataList: ImageData[]): Promise<void> {
114114
if (imageDataList && imageDataList.length) {
115-
let taskQueue = new TaskQueue();
116-
imageDataList.forEach((imageData, index) => {
117-
taskQueue.add(
118-
new QueueTask(async () => {
119-
await new Promise(resolve => {
120-
this.emit("pasteImage", imageData, async () => {
121-
await TimeUtils.wait(100);
122-
resolve(true);
123-
});
124-
});
125-
if (index === imageDataList.length - 1) {
126-
await taskQueue.destroy();
127-
taskQueue = null;
128-
}
129-
}),
130-
);
131-
});
115+
return new Promise((resolve) => {
116+
this.emit("pasteImages", imageDataList, async () => {
117+
resolve();
118+
});
119+
})
132120
}
133121
}
134122

@@ -317,7 +305,7 @@ export default class StageEvent extends EventEmitter implements IStageEvent {
317305
async onImagesUpload(images: File[]): Promise<void> {
318306
if (images.length) {
319307
const imageDataList = await FileUtils.getImageDataFromFiles(images);
320-
this._createImages(imageDataList);
308+
await this._createImages(imageDataList);
321309
}
322310
}
323311
}

src/modules/stage/StageShield.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ export default class StageShield extends DrawerBase implements IStageShield, ISt
14981498
this.event.on("scaleIncrease", this._handleScaleIncrease.bind(this));
14991499
this.event.on("scaleAutoFit", this._handleScaleAutoFit.bind(this));
15001500
this.event.on("scale100", this._handleScale100.bind(this));
1501-
this.event.on("pasteImage", this._handleImagePasted.bind(this));
1501+
this.event.on("pasteImages", this._handleImagesPasted.bind(this));
15021502
this.event.on("deleteSelects", this._handleSelectsDelete.bind(this));
15031503
this.event.on("selectAll", this.selectAll.bind(this));
15041504
this.event.on("selectCopy", this._handleSelectCopy.bind(this));
@@ -2642,6 +2642,17 @@ export default class StageShield extends DrawerBase implements IStageShield, ISt
26422642
*/
26432643
calcScaleAutoFitValueByBox(box: IPoint[]): number {
26442644
const { width, height } = CommonUtils.calcRectangleSize(box);
2645+
return this.calcScaleAutoFitValueBySize(width, height);
2646+
}
2647+
2648+
/**
2649+
* 给定尺寸计算自动适应缩放值
2650+
*
2651+
* @param width
2652+
* @param height
2653+
* @returns
2654+
*/
2655+
calcScaleAutoFitValueBySize(width: number, height: number): number {
26452656
let scale = MathUtils.precise(CommonUtils.calcScale(this.stageRect, { width, height }, AutoFitPadding * this.stageScale), 2);
26462657
scale = clamp(scale, 0.02, 1);
26472658
return scale;
@@ -2653,18 +2664,18 @@ export default class StageShield extends DrawerBase implements IStageShield, ISt
26532664
* @returns
26542665
*/
26552666
calcScaleAutoFitValue(): number {
2656-
const elementsBox = CommonUtils.getBoxByPoints(this.store.visibleElements.map(element => element.maxOutlineBoxCoords).flat());
2657-
return this.calcScaleAutoFitValueByBox(elementsBox);
2667+
return this.calcElementsAutoFitValue(this.store.visibleElements);
26582668
}
26592669

26602670
/**
2661-
* 计算某个组件的自动适应缩放值
2671+
* 计算给定组件的自动适应缩放值
26622672
*
2663-
* @param element
2664-
* @returns
2673+
* @param elements
2674+
* @returns
26652675
*/
2666-
calcElementAutoFitValue(element: IElement): number {
2667-
return this.calcScaleAutoFitValueByBox(element.maxOutlineBoxCoords);
2676+
calcElementsAutoFitValue(elements: IElement[]): number {
2677+
const elementsBox = CommonUtils.getBoxByPoints(elements.map(element => element.maxOutlineBoxCoords).flat());
2678+
return this.calcScaleAutoFitValueByBox(elementsBox);
26682679
}
26692680

26702681
/**
@@ -2739,14 +2750,14 @@ export default class StageShield extends DrawerBase implements IStageShield, ISt
27392750
* @param imageData
27402751
* @param callback
27412752
*/
2742-
async _handleImagePasted(imageData: ImageData, callback?: Function): Promise<void> {
2753+
async _handleImagesPasted(imageDatas: ImageData[], callback?: Function): Promise<void> {
27432754
this._clearSelects();
2744-
const element = await this.store.insertImageElement(imageData);
2745-
const nextScale = this.calcElementAutoFitValue(element);
2755+
const elements = await this.store.insertImageElements(imageDatas);
2756+
const nextScale = this.calcElementsAutoFitValue(elements);
27462757
if (this.stageScale > nextScale) {
27472758
await this.setScale(nextScale);
27482759
}
2749-
await this._tryAddAddedCommand([element]);
2760+
await this._tryAddAddedCommand(elements);
27502761
callback && callback();
27512762
}
27522763

src/modules/stage/StageStore.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import { observable, reaction } from "mobx";
3232
import TextElementUtils from "@/modules/elements/utils/TextElementUtils";
3333
import { ElementActionTypes, ElementsActionParam, ElementActionCallback } from "@/types/ICommand";
3434
import GlobalConfig from "@/config";
35+
import { TaskQueue } from "@/modules/render/RenderQueue";
36+
import { QueueTask } from "../render/RenderTask";
3537

3638
/**
3739
* 调整组件层级
@@ -2240,21 +2242,49 @@ export default class StageStore implements IStageStore {
22402242
}
22412243

22422244
/**
2243-
* 创建并插入图片组件
2244-
*
2245-
* @param image
2245+
* 插入图片
2246+
*
2247+
* @param image
2248+
* @returns
22462249
*/
2247-
async insertImageElement(image: HTMLImageElement | ImageData): Promise<IElement> {
2250+
async _insertImage(image: HTMLImageElement | ImageData): Promise<IElement> {
22482251
let colorSpace;
22492252
if (image instanceof ImageData) {
22502253
colorSpace = image.colorSpace;
22512254
image = ImageUtils.createImageFromImageData(image);
22522255
await ImageUtils.waitForImageLoad(image);
22532256
}
2254-
const model = await this.createImageElementModel(image, { colorSpace });
2257+
const model = await this.createImageElementModel(image, { colorSpace: colorSpace });
22552258
return this.insertAfterElementByModel(model);
22562259
}
22572260

2261+
/**
2262+
* 创建并插入图片组件
2263+
*
2264+
* @param images
2265+
* @returns IElement[] 返回插入的组件列表
2266+
*/
2267+
async insertImageElements(images: (HTMLImageElement[] | ImageData[])): Promise<IElement[]> {
2268+
const result: IElement[] = [];
2269+
await new Promise((resolve) => {
2270+
let taskQueue = new TaskQueue();
2271+
images.forEach((imageData, index) => {
2272+
taskQueue.add(
2273+
new QueueTask(async () => {
2274+
const element = await this._insertImage(imageData);
2275+
result.push(element);
2276+
if (index === images.length - 1) {
2277+
resolve(null);
2278+
await taskQueue.destroy();
2279+
taskQueue = null;
2280+
}
2281+
}),
2282+
);
2283+
});
2284+
});
2285+
return result;
2286+
}
2287+
22582288
/**
22592289
* 创建并插入文本组件
22602290
*

src/types/IStageShield.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export default interface IStageShield extends IStageDrawer, IStageSetter {
8989
// 计算自动缩放值
9090
calcScaleAutoFitValue(): number;
9191
// 计算组件自动缩放值
92-
calcElementAutoFitValue(element: IElement): number;
92+
calcElementsAutoFitValue(elements: IElement[]): number;
9393
// 设置缩放
9494
setScale(value: number): void;
9595
// 设置缩放100%

src/types/IStageStore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export default interface IStageStore extends IStageSetter {
152152
// 创建图片组件的数据模型
153153
createImageElementModel(image: HTMLImageElement | ImageData, options: Partial<ImageData>): Promise<ElementObject>;
154154
// 插入图片组件
155-
insertImageElement(image: HTMLImageElement | ImageData): Promise<IElement>;
155+
insertImageElements(images: (HTMLImageElement[] | ImageData[])): Promise<IElement[]>;
156156
// 插入文本组件
157157
insertTextElement(text: string, fontStyle: FontStyle, coords?: IPoint[]): IElement;
158158
// 删除选中组件

0 commit comments

Comments
 (0)