深度画布
This commit is contained in:
@@ -1,23 +1,25 @@
|
||||
<template>
|
||||
<transition name="fade">
|
||||
<div v-if="show" class="ai-selectbox-panel">
|
||||
<div>
|
||||
<span class="icon"><svg-icon name="dc-add" size="16" /></span>
|
||||
<span class="label">Add</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="icon"><svg-icon name="dc-remove" size="16" /></span>
|
||||
<span class="label">Remove</span>
|
||||
<div
|
||||
v-for="item in list"
|
||||
:key="item.type"
|
||||
:class="{ active: item.name === props.currentTool }"
|
||||
>
|
||||
<span class="icon"><svg-icon :name="item.name" size="16" /></span>
|
||||
<span class="label">{{ item.label }}</span>
|
||||
</div>
|
||||
<button>创建</button>
|
||||
</div>
|
||||
</transition>
|
||||
<brush-control-panel :currentTool="show ? 'draw' : ''" style="top: 14rem" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, inject, computed, watch } from 'vue'
|
||||
import depthSlider from './tools/depth-slider.vue'
|
||||
import { OperationType } from '../tools/layerHelper'
|
||||
import { OperationType, AI_SELECTBOX_TYPE } from '../tools/layerHelper'
|
||||
|
||||
const props = defineProps({
|
||||
currentTool: { required: true, type: [String, null] }
|
||||
})
|
||||
@@ -25,6 +27,28 @@
|
||||
const toolManager = inject('toolManager') as any
|
||||
const showTools = [OperationType.SELECTBOX]
|
||||
const show = computed(() => showTools.includes(props.currentTool))
|
||||
const list = ref([
|
||||
{
|
||||
type: AI_SELECTBOX_TYPE.ADD,
|
||||
name: 'dc-add_sb',
|
||||
label: 'Add'
|
||||
},
|
||||
{
|
||||
type: AI_SELECTBOX_TYPE.REMOVE,
|
||||
name: 'dc-remove_sb',
|
||||
label: 'Remove'
|
||||
},
|
||||
{
|
||||
type: AI_SELECTBOX_TYPE.DRAW,
|
||||
name: 'dc-brush_sb',
|
||||
label: 'Brush'
|
||||
},
|
||||
{
|
||||
type: AI_SELECTBOX_TYPE.ERASER,
|
||||
name: 'dc-erase_sb',
|
||||
label: 'Erase'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// 淡入淡出动画
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
watch(brushState, (value) => {
|
||||
if (value) updateBrushState()
|
||||
})
|
||||
watch(
|
||||
() => props.currentTool,
|
||||
(value) => updateBrushState()
|
||||
)
|
||||
const brushSize = ref(40)
|
||||
const brushOpacity = ref(100)
|
||||
const brushColor = ref('#000000')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { fabric } from 'fabric-with-all'
|
||||
import { OperationType } from '../tools/layerHelper'
|
||||
import { OperationType, AI_SELECTBOX_TYPE } from '../tools/layerHelper'
|
||||
import { getObjectAlphaToCanvas, traceImageContour } from '../tools/canvasMethod'
|
||||
|
||||
/** 智能框选工具管理器 */
|
||||
@@ -20,6 +20,15 @@ export class AISelectboxToolManager {
|
||||
this.layerManager = options.layerManager
|
||||
this.toolManager = options.toolManager
|
||||
}
|
||||
/** 处理切换工具 */
|
||||
handleToolChange(oldTool: string, newTool: string) {
|
||||
if (newTool === OperationType.SELECTBOX) {
|
||||
// 切换到智能框选工具
|
||||
} else {
|
||||
// 切换到普通框选工具
|
||||
|
||||
}
|
||||
}
|
||||
mouseDownEvent(e) {
|
||||
this.isDragging = true
|
||||
this.startX = e.absolutePointer.x
|
||||
@@ -65,7 +74,7 @@ export class AISelectboxToolManager {
|
||||
this.canvasManager.canvas.remove(this.demoObject)
|
||||
this.canvasManager.canvas.renderAll()
|
||||
|
||||
this.createSelectbox()
|
||||
// this.createSelectbox()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -142,9 +142,9 @@ export class CanvasManager {
|
||||
|
||||
this.resetZoom(false, true)// 画布居中
|
||||
|
||||
this.stateManager.toolManager.setTool(OperationType.SELECT)
|
||||
this.layerManager.updateLayers()
|
||||
this.stateManager.recordState()
|
||||
// this.stateManager.toolManager.setTool(OperationType.RECTANGLE)
|
||||
}
|
||||
/** 画布添加对象 */
|
||||
async add(obj: any, isRecord = true) {
|
||||
@@ -293,7 +293,7 @@ export class CanvasManager {
|
||||
async handleDrawImage(fabricImage: fabric.Object) {
|
||||
const activeID = this.stateManager.layerManager.activeID.value
|
||||
const activeLayer = this.getObjectById(activeID)
|
||||
if (activeLayer) {
|
||||
if (activeLayer && activeLayer.fill?.repeat !== "repeat") {
|
||||
this.layerManager.imageMergeToLayer(activeLayer, fabricImage)
|
||||
} else {
|
||||
const emptyLayer = await this.layerManager.createEmptyLayer(false);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ref } from 'vue'
|
||||
import { fabric } from 'fabric-with-all'
|
||||
import { createId } from '../../tools/tools'
|
||||
import { exportObjectsToImage, exportObjectToThumbnail } from '../tools/exportMethod'
|
||||
import { OperationType } from '../tools/layerHelper'
|
||||
import { OperationType, BlendMode } from '../tools/layerHelper'
|
||||
import { getArrowPath, cloneObjects, getStarArr } from '../tools/canvasMethod'
|
||||
|
||||
export class LayerManager {
|
||||
@@ -18,7 +18,12 @@ export class LayerManager {
|
||||
}
|
||||
onMounted() { }
|
||||
setActiveID(id: string, isActive = true) {
|
||||
this.activeID.value = id
|
||||
const layer = this.getLayerById(id)
|
||||
if (layer?.type === "group") {
|
||||
this.activeID.value = ""
|
||||
} else {
|
||||
this.activeID.value = id
|
||||
}
|
||||
if (isActive) {
|
||||
this.canvasManager.setActiveObjectById(id)
|
||||
this.stateManager.toolManager.setTool(OperationType.SELECT)
|
||||
@@ -399,9 +404,15 @@ export class LayerManager {
|
||||
})
|
||||
const index = this.canvasManager.getObjects().indexOf(targetLayer);
|
||||
this.deleteLayerById(targetLayer.info.id, false)
|
||||
this.setActiveID(mergedImage.info.id, false)
|
||||
|
||||
const nid = mergedImage.info.id
|
||||
await this.canvasManager.add(mergedImage, false);
|
||||
this.setActiveID(nid, false)
|
||||
this.canvasManager.canvas.moveTo(mergedImage, index);
|
||||
|
||||
// this.stateManager.objectManager.setBlendMode(nid, BlendMode.MULTIPLY)
|
||||
// this.stateManager.objectManager.setFillRepeat(nid, false)
|
||||
|
||||
this.canvasManager.renderAll()
|
||||
this.updateLayers()
|
||||
this.stateManager.recordState()
|
||||
|
||||
@@ -87,7 +87,7 @@ export class ObjectManager {
|
||||
}
|
||||
|
||||
/** 设置平铺状态 */
|
||||
setFillRepeat(id: string) {
|
||||
setFillRepeat(id: string, isRecord = true) {
|
||||
const object = this.canvasManager.getObjectById(id)
|
||||
if (!object) return console.warn('设置平铺状态失败,对象不存在ID:', id)
|
||||
if (object.type !== 'image') return console.warn('设置平铺状态失败,对象不是图片类型:', id)
|
||||
@@ -133,7 +133,7 @@ export class ObjectManager {
|
||||
});
|
||||
rect.set("fill", pattern)
|
||||
this.canvasManager.canvas.remove(object)
|
||||
this.canvasManager.add(rect)
|
||||
this.canvasManager.add(rect, isRecord)
|
||||
}
|
||||
/** 获取填充对象 */
|
||||
getFillRepeatObject(id: string) {
|
||||
|
||||
@@ -38,6 +38,7 @@ export class StateManager {
|
||||
brushManager: any
|
||||
keyEventManager: any
|
||||
objectManager: any
|
||||
aiSelectboxToolManager: any
|
||||
// 设置管理器
|
||||
setManager(options) {
|
||||
options.eventManager && (this.eventManager = options.eventManager)
|
||||
@@ -47,6 +48,7 @@ export class StateManager {
|
||||
options.brushManager && (this.brushManager = options.brushManager)
|
||||
options.keyEventManager && (this.keyEventManager = options.keyEventManager)
|
||||
options.objectManager && (this.objectManager = options.objectManager)
|
||||
options.aiSelectboxToolManager && (this.aiSelectboxToolManager = options.aiSelectboxToolManager)
|
||||
}
|
||||
constructor(options) {
|
||||
this.mxHistory = ref(50)
|
||||
|
||||
@@ -101,6 +101,7 @@ export class ToolManager {
|
||||
setTool(value: string) {
|
||||
const tool = this.tools.find((t) => t.name === value)
|
||||
if (!tool) return console.warn(`工具${tool}不存在`)
|
||||
const oldTool = this.currentTool.value
|
||||
this.currentTool.value = tool.name
|
||||
this.canvasManager.canvas.defaultCursor = tool.cursor
|
||||
this.setCanvasEvented(!!tool.selection)
|
||||
@@ -110,6 +111,7 @@ export class ToolManager {
|
||||
|
||||
if (tool.setup) tool.setup()
|
||||
|
||||
this.stateManager?.aiSelectboxToolManager?.handleToolChange?.(oldTool, tool.name)
|
||||
setTimeout(() => {
|
||||
this.canvasManager.renderAll()
|
||||
});
|
||||
@@ -142,13 +144,16 @@ export class ToolManager {
|
||||
const brushStore = this.brushManager?.brushStore
|
||||
if (brushStore) {
|
||||
// 同步基本属性
|
||||
this.brushManager.setBrushSize(brushStore.state.size);
|
||||
this.brushManager.setBrushColor(brushStore.state.color);
|
||||
this.brushManager.setBrushOpacity(brushStore.state.opacity);
|
||||
// this.brushManager.setBrushSize(brushStore.state.size);
|
||||
// this.brushManager.setBrushColor(brushStore.state.color);
|
||||
// this.brushManager.setBrushOpacity(brushStore.state.opacity);
|
||||
|
||||
// 同步笔刷类型 - 修复方法名,使用正确的setBrushType方法
|
||||
this.brushManager.setBrushType("pencil");
|
||||
}
|
||||
this.brushManager.setBrushSize(5);
|
||||
this.brushManager.setBrushColor("#000");
|
||||
this.brushManager.setBrushOpacity(1);
|
||||
|
||||
// 更新应用到画布
|
||||
this.brushManager.updateBrush();
|
||||
@@ -168,6 +173,7 @@ export class ToolManager {
|
||||
this.brushManager.createEraser();
|
||||
}
|
||||
|
||||
this.brushManager.setBrushSize(5);
|
||||
this.stateManager.layerManager.setActiveObjectErasable()
|
||||
// 启用笔刷指示器
|
||||
this._enableBrushIndicator();
|
||||
|
||||
@@ -34,6 +34,7 @@ export class CanvasEventManager {
|
||||
}
|
||||
this.shapeToolManager = new ShapeToolManager(managers)
|
||||
this.aiSelectboxToolManager = new AISelectboxToolManager(managers)
|
||||
this.stateManager.setManager({ aiSelectboxToolManager: this.aiSelectboxToolManager })
|
||||
|
||||
// 初始化所有事件
|
||||
this.initEvents();
|
||||
|
||||
@@ -68,3 +68,11 @@ export const BlendMode = {
|
||||
DESTINATION_IN: "destination-in", // 目标内
|
||||
DESTINATION_OUT: "destination-out", // 目标外
|
||||
};
|
||||
|
||||
/** 智能框选工具类型枚举 */
|
||||
export const AI_SELECTBOX_TYPE = {
|
||||
ADD: "add", // 添加模式
|
||||
REMOVE: "remove", // 删除模式
|
||||
DRAW: "draw", // 绘画模式
|
||||
ERASER: "eraser", // 橡皮擦模式
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user