深度画布
This commit is contained in:
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
3
src/assets/icons/dc/brush_sb.svg
Normal file
3
src/assets/icons/dc/brush_sb.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.157122 13.4725L0.526449 10.3737C0.550847 10.1699 0.642783 9.98015 0.787096 9.83413L9.86461 0.654119C10.1812 0.334063 10.6118 0.151974 11.062 0.149342C11.5123 0.146814 11.9457 0.324063 12.2659 0.640637L13.8892 2.24581C14.2094 2.56248 14.3915 2.99386 14.394 3.44416C14.3964 3.89432 14.2192 4.32698 13.9027 4.64714L4.8252 13.8272C4.68081 13.9731 4.49215 14.0672 4.28861 14.0938L1.19415 14.4979C1.05466 14.5161 0.912174 14.5022 0.778872 14.4573C0.645754 14.4124 0.525008 14.3374 0.425099 14.2386C0.325191 14.1398 0.248858 14.0199 0.202421 13.8873C0.167635 13.7878 0.14946 13.6829 0.149902 13.578L0.157122 13.4725ZM11.752 5.29496L13.1397 3.89164C13.2557 3.77408 13.3206 3.61539 13.3198 3.45019C13.3189 3.28482 13.2522 3.12618 13.1347 3.00982L11.5104 1.40368C11.3928 1.28748 11.2334 1.22262 11.068 1.22354C10.9028 1.22458 10.7449 1.29127 10.6286 1.40863L9.24097 2.81195L11.752 5.29496ZM1.84678 13.3302L4.09809 13.0363L10.9965 6.05996L8.4845 3.57598L1.58606 10.5523L1.31747 12.8068L1.24565 13.4088L1.84678 13.3302Z" fill="#0D0D0D" stroke="black" stroke-width="0.3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
src/assets/icons/dc/erase_sb.svg
Normal file
3
src/assets/icons/dc/erase_sb.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.26 0.555138L15.4449 4.74003C15.6209 4.91603 15.7605 5.12497 15.8557 5.35492C15.951 5.58488 16 5.83134 16 6.08024C16 6.32914 15.951 6.5756 15.8557 6.80556C15.7605 7.03551 15.6209 7.24445 15.4449 7.42045L8.13225 14.7322L13.2682 14.7331C13.421 14.7329 13.5687 14.7881 13.6839 14.8884C13.7992 14.9888 13.8741 15.1275 13.8949 15.2789L13.9 15.3648C13.9 15.5175 13.8447 15.665 13.7443 15.7801C13.644 15.8951 13.5054 15.97 13.3541 15.9907L13.2682 15.9966L6.18385 15.9975C5.91791 16.0124 5.65181 15.9709 5.403 15.8758C5.15418 15.7807 4.92826 15.6342 4.74003 15.4457L0.555138 11.26C0.379138 11.084 0.239526 10.875 0.144276 10.6451C0.0490248 10.4151 0 10.1687 0 9.91976C0 9.67086 0.0490248 9.4244 0.144276 9.19444C0.239526 8.96449 0.379138 8.75555 0.555138 8.57955L8.57955 0.555138C8.75555 0.379138 8.96449 0.239527 9.19444 0.144276C9.4244 0.049025 9.67086 0 9.91976 0C10.1687 0 10.4151 0.049025 10.6451 0.144276C10.875 0.239527 11.084 0.379138 11.26 0.555138ZM2.70065 8.21986L1.44805 9.4733C1.32974 9.59176 1.26328 9.75234 1.26328 9.91976C1.26328 10.0872 1.32974 10.2478 1.44805 10.3662L5.63378 14.5519C5.75677 14.6749 5.9185 14.7373 6.08024 14.7373L6.10467 14.7331L6.13668 14.7347C6.28414 14.7216 6.42224 14.6569 6.5267 14.5519L7.7793 13.2993L2.69981 8.21986H2.70065ZM9.4733 1.44805L3.59356 7.3261L8.67305 12.4056L14.552 6.52754C14.6107 6.46887 14.6572 6.3992 14.689 6.32253C14.7208 6.24585 14.7371 6.16366 14.7371 6.08066C14.7371 5.99766 14.7208 5.91547 14.689 5.8388C14.6572 5.76212 14.6107 5.69245 14.552 5.63378L10.3662 1.44805C10.2478 1.32974 10.0872 1.26328 9.91976 1.26328C9.75234 1.26328 9.59176 1.32974 9.4733 1.44805Z" fill="#212121"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 962 B After Width: | Height: | Size: 962 B |
@@ -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", // 橡皮擦模式
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<span class="label" v-show="!item.edit">{{ item.name }}</span>
|
||||
<el-popover
|
||||
placement="right"
|
||||
trigger="click"
|
||||
trigger="contextmenu"
|
||||
width="10rem"
|
||||
popper-style="
|
||||
padding: .6rem 0.7rem;
|
||||
@@ -54,7 +54,9 @@
|
||||
v-model:visible="item.visible"
|
||||
>
|
||||
<template #reference>
|
||||
<span @click.stop class="icon"><svg-icon name="more" size="16" /></span>
|
||||
<span @click.stop="item.visible = !item.visible" class="icon">
|
||||
<svg-icon name="more" size="16" />
|
||||
</span>
|
||||
</template>
|
||||
<div class="history-item-menu">
|
||||
<div class="rename" @click="onRenameHistoryItem(item)">
|
||||
|
||||
Reference in New Issue
Block a user