画布loading

This commit is contained in:
李志鹏
2026-02-06 13:07:06 +08:00
parent b50dbbc246
commit 13024cdd99
8 changed files with 1709 additions and 1726 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,6 @@ import {
isGroupLayer,
OperationType,
OperationTypes,
findLayer,
createLayer,
LayerType,
SpecialLayerId,
@@ -20,7 +19,6 @@ import { AnimationManager } from "./animation/AnimationManager";
import { createCanvas } from "../utils/canvasFactory";
import { CanvasEventManager } from "./events/CanvasEventManager";
import CanvasConfig from "../config/canvasConfig";
import { RedGreenModeManager } from "./RedGreenModeManager";
import { EraserStateManager } from "./EraserStateManager";
import {
deepClone,
@@ -1337,7 +1335,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
}
}
loadJSON(json, calllBack) {
this.canvas.loading.value = true;
// 确保传入的json是字符串格式
if (typeof json === "object") {
json = JSON.stringify(json);
@@ -1509,7 +1507,6 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
*/
async createOtherLayers(otherData) {
if (!otherData) return console.warn("otherData 为空不需要添加");
this.canvas.loading.value = true;
let resolve = ()=>{};
this.awaitCanvasRun = ()=>(new Promise((v) => resolve = v))
const otherData_ = JSON.parse(JSON.stringify(otherData));
@@ -1557,7 +1554,6 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
console.log("==========创建其他图层成功");
resolve();
this.awaitCanvasRun = null;
this.canvas.loading.value = false;
}
// 设置画布对象的裁剪信息

View File

@@ -1580,7 +1580,7 @@ export class LayerManager {
/**
* 排序图层,确保图层顺序: 普通图层 > 固定图层 > 背景图层
*/
sortLayers() {
async sortLayers() {
// 对图层进行排序:背景图层在最底层(数组最后),固定图层在中间
this.layers.value.sort((a, b) => {
// 如果a是背景图层它应该排在后面最底层
@@ -1604,17 +1604,17 @@ export class LayerManager {
});
// 更新画布对象顺序
this._rearrangeObjects();
await this._rearrangeObjects();
}
/**
* 重新排列画布上的对象以匹配图层顺序
* @private
*/
_rearrangeObjects() {
async _rearrangeObjects() {
if (this.layerSort) {
// 使用LayerSort的高级排序
this.layerSort.rearrangeObjects();
await this.layerSort.rearrangeObjects();
return;
}

View File

@@ -90,16 +90,17 @@ export class PartManager {
if (toolId === OperationType.PART_ERASER) {
this.setEraserTool();
} else if (toolId === OperationType.PART || toolId === OperationType.PART_RECTANGLE) {
this.clearPointData();
this.resetPartObject();
}
if (toolId === OperationType.PART_ERASER || toolId === OperationType.PART_BRUSH) {
if (this.pointList.length > 0) {
this.clearPointData();
this.resetPartObject();
}
}
}
// else if (toolId === OperationType.PART || toolId === OperationType.PART_RECTANGLE) {
// this.clearPointData();
// this.resetPartObject();
// }
// if (toolId === OperationType.PART_ERASER || toolId === OperationType.PART_BRUSH) {
// if (this.pointList.length > 0) {
// this.clearPointData();
// this.resetPartObject();
// }
// }
// 如果从非选区工具切换到选区工具,初始化事件
if (!wasActive && this.isActive) {
@@ -380,7 +381,8 @@ export class PartManager {
box: [...this.pointList],
});
const image = await this.loadImageToObject(url);
const canvas = getObjectAlphaToCanvas(image, null, 0, this.rgba);
const data = this.partCanvas?.getContext("2d")?.getImageData(0, 0, this.partCanvas.width, this.partCanvas.height);
const canvas = getObjectAlphaToCanvas(image, data, 0, this.rgba, !!data);
this.partDrawCommand(canvas);
}
/** 获取分隔后图片 */

View File

@@ -30,27 +30,30 @@ export class LayerSort {
if (canvasObjects.length === 0) return;
// 使用画布渲染优化
await optimizeCanvasRendering(this.canvas, () => {
// 计算每个对象应该在的 z-index 位置
const objectZIndexMap = this.calculateObjectZIndexes();
await new Promise((resolve) => {
optimizeCanvasRendering(this.canvas, () => {
// 计算每个对象应该在的 z-index 位置
const objectZIndexMap = this.calculateObjectZIndexes();
// 按照新的 z-index 排序对象
const sortedObjects = canvasObjects
.map((obj) => ({
object: obj,
targetZIndex: objectZIndexMap.get(obj.id) ?? -1,
}))
.filter((item) => item.targetZIndex >= 0) // 过滤掉无效对象
.sort((a, b) => a.targetZIndex - b.targetZIndex);
// 按照新的 z-index 排序对象
const sortedObjects = canvasObjects
.map((obj) => ({
object: obj,
targetZIndex: objectZIndexMap.get(obj.id) ?? -1,
}))
.filter((item) => item.targetZIndex >= 0) // 过滤掉无效对象
.sort((a, b) => a.targetZIndex - b.targetZIndex);
// 使用 fabric.js 的 moveTo 方法重新排序
sortedObjects.forEach((item, index) => {
const currentIndex = this.canvas.getObjects().indexOf(item.object);
if (currentIndex !== index && currentIndex !== -1) {
// 将对象移动到正确的位置
this.canvas.moveTo(item.object, index);
}
});
// 使用 fabric.js 的 moveTo 方法重新排序
sortedObjects.forEach((item, index) => {
const currentIndex = this.canvas.getObjects().indexOf(item.object);
if (currentIndex !== index && currentIndex !== -1) {
// 将对象移动到正确的位置
this.canvas.moveTo(item.object, index);
}
});
resolve();
});
});
}

View File

@@ -65,9 +65,10 @@ export async function restoreFabricObject(serializedObject, canvas) {
* @param {ImageData} revData - 相反的ImageData白通道的相同位置是否为透明revData为白色为透明黑色为不透明
* @param {number} diff - 差值,默认 25
* @param {Object} rgba - 自定义 rgba 值,默认 { r: 255, g: 255, b: 255, a: 255 }
* @param {boolean} isMerge - 是否合并true=合并revDatafalse=反转revData
* @returns {HTMLCanvasElement|null} 包含黑白通道的画布,或 null 如果失败
*/
export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 255, g: 255, b: 255, a: 255 }) {
export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 255, g: 255, b: 255, a: 255 }, isMerge = false) {
const image = object.getElement();
if (image.nodeName !== "IMG" && image.nodeName !== "CANVAS") {
console.warn("对象不是图片");
@@ -93,18 +94,20 @@ export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 2
const revG = revData?.data[i + 1] || 0;
const revB = revData?.data[i + 2] || 0;
const revA = revData?.data[i + 3] || 0;
let isHave = false;
if (r || g || b || a) {
if (revR > diff || revG > diff || revB > diff || revA > diff) {
data.data[i + 0] = 0;
data.data[i + 1] = 0;
data.data[i + 2] = 0;
data.data[i + 3] = 0;
isHave = false;
} else {
data.data[i + 0] = rgba.r;
data.data[i + 1] = rgba.g;
data.data[i + 2] = rgba.b;
data.data[i + 3] = rgba.a;
isHave = true;
}
}
if (isMerge && (revR || revG || revB || revA)) isHave = true;
if (isHave) {
data.data[i + 0] = rgba.r;
data.data[i + 1] = rgba.g;
data.data[i + 2] = rgba.b;
data.data[i + 3] = rgba.a;
} else {
data.data[i + 0] = 0;
data.data[i + 1] = 0;

View File

@@ -333,6 +333,7 @@
]);
const canvasLoadJsonSuccess = () => {
console.log("画布加载JSON成功");
return;
canvasEditor.value?.updateOtherLayers({
color: { rgba: { r: 255, g: 0, b: 0, a: 1 } },
printObject: {

View File

@@ -51,9 +51,9 @@
</div>
</div>
<div class="mark_loading" v-show="isShowMark">
<!-- <div class="mark_loading" v-show="isShowMark">
<a-spin size="large" />
</div>
</div> -->
</div>
</template>