feat: 裁剪组裁剪跟随选择组移动

This commit is contained in:
bighuixiang
2025-07-14 01:00:23 +08:00
parent 96e13cb22a
commit 24e9ba8ae5
80 changed files with 2052 additions and 4292 deletions

View File

@@ -34,14 +34,10 @@ import SelectionPanel from "./components/SelectionPanel.vue"; // 引入选区面
import { LayerType, OperationType } from "./utils/layerHelper.js";
import { ToolManager } from "./managers/toolManager.js";
import { fabric } from "fabric-with-all";
import {
uploadImageAndCreateLayer,
loadImageUrlToLayer,
loadImage,
} from "./utils/imageHelper.js";
import { uploadImageAndCreateLayer, loadImageUrlToLayer, loadImage } from "./utils/imageHelper.js";
// import MinimapPanel from "./components/MinimapPanel.vue";
const KeyboardShortcutHelp = defineAsyncComponent(() =>
import("./components/KeyboardShortcutHelp.vue")
const KeyboardShortcutHelp = defineAsyncComponent(
() => import("./components/KeyboardShortcutHelp.vue")
);
const emit = defineEmits([
@@ -318,11 +314,7 @@ onMounted(async () => {
await layerManager.initializeLayers();
}
if (
props.enabledRedGreenMode &&
props.clothingImageUrl &&
props.redGreenImageUrl
) {
if (props.enabledRedGreenMode && props.clothingImageUrl && props.redGreenImageUrl) {
canvasManager.canvas.fill = "#fff"; // 设置画布背景色为白色 // 初始化红绿图模式管理器
redGreenModeManager = new RedGreenModeManager({
canvas: canvasManager.canvas,
@@ -369,10 +361,7 @@ onMounted(async () => {
console.error("更换底图失败:", error);
}
canvasManager?.centerBackgroundLayer?.(
canvasManager.canvas.width,
canvasManager.canvas.height
);
canvasManager?.centerBackgroundLayer?.(canvasManager.canvas.width, canvasManager.canvas.height);
}
// // 设置固定图层是否可擦除
@@ -395,7 +384,7 @@ onMounted(async () => {
requestAnimationFrame(() => {
setTimeout(() => {
// 初始状态下生成所有预览图
canvasManager.updateAllThumbnails();
canvasManager?.updateAllThumbnails?.();
}, 300);
});
});
@@ -559,9 +548,7 @@ function moveLayerDown(layerId) {
function removeLayer(layerId) {
// Check if this is the last layer - prevent deletion
if (layers.value.length <= 2) {
console.warn(
"Cannot delete the last layer. At least one layer must remain."
);
console.warn("Cannot delete the last layer. At least one layer must remain.");
return;
}
@@ -667,9 +654,7 @@ function handleLayersReorder(reorderData) {
const success = layerManager.reorderLayers(oldIndex, newIndex, layerId);
if (success) {
console.log(
`图层 ${layerId} 已从位置 ${oldIndex} 移动到位置 ${newIndex}`
);
console.log(`图层 ${layerId} 已从位置 ${oldIndex} 移动到位置 ${newIndex}`);
// 更新画布渲染顺序
if (canvasManager) {
@@ -686,12 +671,7 @@ function handleChildLayersReorder(reorderData) {
const { parentId, oldIndex, newIndex, layerId } = reorderData;
if (layerManager && layerManager.reorderChildLayers) {
const success = layerManager.reorderChildLayers(
parentId,
oldIndex,
newIndex,
layerId
);
const success = layerManager.reorderChildLayers(parentId, oldIndex, newIndex, layerId);
if (success) {
console.log(
@@ -851,8 +831,7 @@ defineExpose({
* @returns {Object} 优化结果统计
*/
optimizeLayerStructure() {
if (!layerManager)
return { removedEmptyLayers: 0, mergedLayers: 0, reorderedLayers: 0 };
if (!layerManager) return { removedEmptyLayers: 0, mergedLayers: 0, reorderedLayers: 0 };
return layerManager.optimizeLayerStructure();
},
@@ -965,10 +944,7 @@ defineExpose({
<!-- <MinimapPanel v-if="minimapEnabled" :minimapManager="minimapManager" /> -->
<!-- 笔刷控制面板 -->
<BrushControlPanel
v-if="canvasManagerLoaded"
:activeTool="activeTool"
/>
<BrushControlPanel v-if="canvasManagerLoaded" :activeTool="activeTool" />
<!-- 文本编辑面板 -->
<TextEditorPanel
@@ -1001,11 +977,7 @@ defineExpose({
<div class="zoom-info">
缩放: {{ currentZoom }}%
<button class="reset-zoom" @click="resetZoom">重置视图</button>
<button
class="help-btn"
@click="toggleShortcutHelp"
title="查看快捷键和触控操作"
>
<button class="help-btn" @click="toggleShortcutHelp" title="查看快捷键和触控操作">
?
</button>
</div>
@@ -1045,11 +1017,7 @@ defineExpose({
</div> -->
<!-- 快捷键帮助模态框 -->
<div
v-if="showShortcutHelp"
class="modal-overlay"
@click="showShortcutHelp = false"
>
<div v-if="showShortcutHelp" class="modal-overlay" @click="showShortcutHelp = false">
<div class="modal-content" @click.stop>
<button class="close-modal" @click="showShortcutHelp = false">×</button>
<KeyboardShortcutHelp />
@@ -1126,30 +1094,20 @@ defineExpose({
--offsetY: 0px;
--size: 8px;
--color: #dedcdc;
background-image: -webkit-linear-gradient(
background-image:
-webkit-linear-gradient(
45deg,
var(--color) 25%,
transparent 0,
transparent 75%,
var(--color) 0
),
-webkit-linear-gradient(45deg, var(--color) 25%, transparent 0, transparent
75%, var(--color) 0);
background-image: linear-gradient(
45deg,
var(--color) 25%,
transparent 0,
transparent 75%,
var(--color) 0
),
linear-gradient(
45deg,
var(--color) 25%,
transparent 0,
transparent 75%,
var(--color) 0
);
background-position: var(--offsetX) var(--offsetY),
-webkit-linear-gradient(45deg, var(--color) 25%, transparent 0, transparent 75%, var(--color) 0);
background-image:
linear-gradient(45deg, var(--color) 25%, transparent 0, transparent 75%, var(--color) 0),
linear-gradient(45deg, var(--color) 25%, transparent 0, transparent 75%, var(--color) 0);
background-position:
var(--offsetX) var(--offsetY),
calc(var(--size) + var(--offsetX)) calc(var(--size) + var(--offsetY));
background-size: calc(var(--size) * 2) calc(var(--size) * 2);
}
@@ -1369,7 +1327,9 @@ button:hover {
// 淡入淡出动画
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s, transform 0.3s;
transition:
opacity 0.3s,
transform 0.3s;
}
.fade-enter-from,
.fade-leave-to {