深度画布智能选区
This commit is contained in:
@@ -4,51 +4,63 @@
|
|||||||
<div
|
<div
|
||||||
v-for="item in list"
|
v-for="item in list"
|
||||||
:key="item.type"
|
:key="item.type"
|
||||||
:class="{ active: item.name === props.currentTool }"
|
:class="{ active: item.type === currentTool }"
|
||||||
|
@click="onClickItem(item.type)"
|
||||||
>
|
>
|
||||||
<span class="icon"><svg-icon :name="item.name" size="16" /></span>
|
<span class="icon"><svg-icon :name="item.name" size="16" /></span>
|
||||||
<span class="label">{{ item.label }}</span>
|
<span class="label">{{ item.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button>创建</button>
|
<button @click="onCreate">创建</button>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<brush-control-panel :currentTool="show ? 'draw' : ''" style="top: 14rem" />
|
<brush-control-panel v-if="show" :currentTool="currentTool2" style="top: 14rem" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, computed, watch } from 'vue'
|
import { ref, inject, computed, watch } from 'vue'
|
||||||
import depthSlider from './tools/depth-slider.vue'
|
import depthSlider from './tools/depth-slider.vue'
|
||||||
import { OperationType, AI_SELECTBOX_TYPE } from '../tools/layerHelper'
|
import { OperationType } from '../tools/layerHelper'
|
||||||
|
import brushControlPanel from './brush-control-panel.vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentTool: { required: true, type: [String, null] }
|
currentTool: { required: true, type: [String, null] }
|
||||||
})
|
})
|
||||||
const stateManager = inject('stateManager') as any
|
const stateManager = inject('stateManager') as any
|
||||||
const toolManager = inject('toolManager') as any
|
const toolManager = inject('toolManager') as any
|
||||||
const showTools = [OperationType.SELECTBOX]
|
const tool2 = {
|
||||||
const show = computed(() => showTools.includes(props.currentTool))
|
[OperationType.AISELECT_DRAW]: OperationType.ERASER,
|
||||||
|
[OperationType.AISELECT_ERASER]: OperationType.ERASER
|
||||||
|
}
|
||||||
|
const currentTool2 = computed(() => tool2[props.currentTool] || props.currentTool)
|
||||||
|
const show = computed(() => stateManager.aiSelectboxToolManager.tools.includes(props.currentTool))
|
||||||
const list = ref([
|
const list = ref([
|
||||||
{
|
{
|
||||||
type: AI_SELECTBOX_TYPE.ADD,
|
type: OperationType.AISELECT_ADD,
|
||||||
name: 'dc-add_sb',
|
name: 'dc-add_sb',
|
||||||
label: 'Add'
|
label: 'Add'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: AI_SELECTBOX_TYPE.REMOVE,
|
type: OperationType.AISELECT_REMOVE,
|
||||||
name: 'dc-remove_sb',
|
name: 'dc-remove_sb',
|
||||||
label: 'Remove'
|
label: 'Remove'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: AI_SELECTBOX_TYPE.DRAW,
|
type: OperationType.AISELECT_DRAW,
|
||||||
name: 'dc-brush_sb',
|
name: 'dc-brush_sb',
|
||||||
label: 'Brush'
|
label: 'Brush'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: AI_SELECTBOX_TYPE.ERASER,
|
type: OperationType.AISELECT_ERASER,
|
||||||
name: 'dc-erase_sb',
|
name: 'dc-erase_sb',
|
||||||
label: 'Erase'
|
label: 'Erase'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
const onClickItem = (type: string) => {
|
||||||
|
toolManager.setTool(type)
|
||||||
|
}
|
||||||
|
const onCreate = () => {
|
||||||
|
stateManager.aiSelectboxToolManager.createSelectbox()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
// 淡入淡出动画
|
// 淡入淡出动画
|
||||||
|
|||||||
@@ -39,20 +39,22 @@
|
|||||||
currentTool: { required: true, type: [String, null] }
|
currentTool: { required: true, type: [String, null] }
|
||||||
})
|
})
|
||||||
const stateManager = inject('stateManager') as any
|
const stateManager = inject('stateManager') as any
|
||||||
const toolManager = inject('toolManager') as any
|
|
||||||
const brushState = computed(() => stateManager.brushManager.brushStore.state)
|
const brushState = computed(() => stateManager.brushManager.brushStore.state)
|
||||||
const showTools = [OperationType.DRAW, OperationType.ERASER]
|
const showTools = [OperationType.DRAW, OperationType.ERASER]
|
||||||
const show = computed(() => showTools.includes(props.currentTool))
|
const show = computed(() => showTools.includes(props.currentTool))
|
||||||
watch(brushState, (value) => {
|
|
||||||
if (value) updateBrushState()
|
|
||||||
})
|
|
||||||
watch(
|
|
||||||
() => props.currentTool,
|
|
||||||
(value) => updateBrushState()
|
|
||||||
)
|
|
||||||
const brushSize = ref(40)
|
const brushSize = ref(40)
|
||||||
const brushOpacity = ref(100)
|
const brushOpacity = ref(100)
|
||||||
const brushColor = ref('#000000')
|
const brushColor = ref('#000000')
|
||||||
|
const updateBrushState = () => {
|
||||||
|
brushSize.value = brushState.value.size
|
||||||
|
brushOpacity.value = brushState.value.opacity
|
||||||
|
brushColor.value = brushState.value.color
|
||||||
|
}
|
||||||
|
updateBrushState()
|
||||||
|
watch(() => brushState.value.size, updateBrushState)
|
||||||
|
watch(() => brushState.value.opacity, updateBrushState)
|
||||||
|
watch(() => brushState.value.color, updateBrushState)
|
||||||
|
|
||||||
const onInputSize = (value: number) => {
|
const onInputSize = (value: number) => {
|
||||||
stateManager.brushManager.setBrushSize(value)
|
stateManager.brushManager.setBrushSize(value)
|
||||||
}
|
}
|
||||||
@@ -62,12 +64,6 @@
|
|||||||
const onInputColor = () => {
|
const onInputColor = () => {
|
||||||
stateManager.brushManager.setBrushColor(brushColor.value)
|
stateManager.brushManager.setBrushColor(brushColor.value)
|
||||||
}
|
}
|
||||||
const updateBrushState = () => {
|
|
||||||
brushSize.value = brushState.value.size
|
|
||||||
brushOpacity.value = brushState.value.opacity
|
|
||||||
brushColor.value = brushState.value.color
|
|
||||||
}
|
|
||||||
updateBrushState()
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
// 淡入淡出动画
|
// 淡入淡出动画
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
class="icon"
|
class="icon"
|
||||||
@click="onClickTool(v)"
|
@click="onClickTool(v)"
|
||||||
:class="{
|
:class="{
|
||||||
active: v.name === tool,
|
active: v.name === tool || v.tools?.includes(tool),
|
||||||
disabled: v.disabled
|
disabled: v.disabled
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
@@ -72,7 +72,12 @@
|
|||||||
{ name: OperationType.DRAW, icon: 'dc-brush', iconSize: 18 },
|
{ name: OperationType.DRAW, icon: 'dc-brush', iconSize: 18 },
|
||||||
{ name: OperationType.ERASER, icon: 'dc-eraser', iconSize: 18 },
|
{ name: OperationType.ERASER, icon: 'dc-eraser', iconSize: 18 },
|
||||||
{ icon: 'dc-image', iconSize: 17, on: () => onImageClick() },
|
{ icon: 'dc-image', iconSize: 17, on: () => onImageClick() },
|
||||||
{ name: OperationType.SELECTBOX, icon: 'dc-selectbox', iconSize: 16 },
|
{
|
||||||
|
name: OperationType.AISELECT_ADD,
|
||||||
|
icon: 'dc-selectbox',
|
||||||
|
iconSize: 16,
|
||||||
|
tools: stateManager.aiSelectboxToolManager.tools
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: OperationType.RECTANGLE,
|
name: OperationType.RECTANGLE,
|
||||||
icon: 'dc-rectangle',
|
icon: 'dc-rectangle',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { fabric } from 'fabric-with-all'
|
import { fabric } from 'fabric-with-all'
|
||||||
import { OperationType, AI_SELECTBOX_TYPE } from '../tools/layerHelper'
|
import { OperationType } from '../tools/layerHelper'
|
||||||
import { getObjectAlphaToCanvas, traceImageContour } from '../tools/canvasMethod'
|
import { getObjectAlphaToCanvas, traceImageContour, cloneObjects } from '../tools/canvasMethod'
|
||||||
|
|
||||||
/** 智能框选工具管理器 */
|
/** 智能框选工具管理器 */
|
||||||
export class AISelectboxToolManager {
|
export class AISelectboxToolManager {
|
||||||
@@ -13,7 +13,17 @@ export class AISelectboxToolManager {
|
|||||||
isDragging: boolean = false
|
isDragging: boolean = false
|
||||||
startX: number = 0
|
startX: number = 0
|
||||||
startY: number = 0
|
startY: number = 0
|
||||||
demoObject: any
|
|
||||||
|
indicatorObject: any// 指示框对象
|
||||||
|
demoObject: any// 演示框对象
|
||||||
|
tcanvas: any// 临时画布对象
|
||||||
|
|
||||||
|
tools = [
|
||||||
|
OperationType.AISELECT_ADD,
|
||||||
|
OperationType.AISELECT_REMOVE,
|
||||||
|
OperationType.AISELECT_DRAW,
|
||||||
|
OperationType.AISELECT_ERASER
|
||||||
|
]
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.canvasManager = options.canvasManager
|
this.canvasManager = options.canvasManager
|
||||||
this.stateManager = options.stateManager
|
this.stateManager = options.stateManager
|
||||||
@@ -22,17 +32,56 @@ export class AISelectboxToolManager {
|
|||||||
}
|
}
|
||||||
/** 处理切换工具 */
|
/** 处理切换工具 */
|
||||||
handleToolChange(oldTool: string, newTool: string) {
|
handleToolChange(oldTool: string, newTool: string) {
|
||||||
if (newTool === OperationType.SELECTBOX) {
|
const oldIsAAA = this.tools.includes(oldTool)
|
||||||
// 切换到智能框选工具
|
const newIsAAA = this.tools.includes(newTool)
|
||||||
} else {
|
if (!oldIsAAA && newIsAAA) {
|
||||||
// 切换到普通框选工具
|
// 普通工具切换到智能框选工具
|
||||||
|
this.init()
|
||||||
|
} else if (oldIsAAA && !newIsAAA) {
|
||||||
|
// 智能框选工具切换到普通工具
|
||||||
|
this.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 切换到橡皮擦工具 */
|
||||||
|
changeToolToEraser() {
|
||||||
|
if (!this.demoObject) return;
|
||||||
|
this.demoObject.set({ erasable: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
console.log("初始化智能框选工具")
|
||||||
|
this.clear();
|
||||||
|
this.createDemoObject()
|
||||||
|
this.tcanvas = null;
|
||||||
}
|
}
|
||||||
|
clear() {
|
||||||
|
console.log("清除智能框选工具")
|
||||||
|
this.clearDemoObject()
|
||||||
|
this.clearIndicatorObject()
|
||||||
|
this.isDragging = false
|
||||||
|
this.canvasManager.canvas.renderAll()
|
||||||
}
|
}
|
||||||
mouseDownEvent(e) {
|
createDemoObject() {
|
||||||
this.isDragging = true
|
if (this.demoObject) this.clearDemoObject()
|
||||||
this.startX = e.absolutePointer.x
|
const { canvasWidth, canvasHeight } = this.canvasManager.getCanvasSize();
|
||||||
this.startY = e.absolutePointer.y
|
const canvas = document.createElement('canvas')
|
||||||
|
canvas.width = canvasWidth
|
||||||
|
canvas.height = canvasHeight
|
||||||
|
this.demoObject = new fabric.Image(canvas, {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
evented: false,
|
||||||
|
selectable: false,
|
||||||
|
erasable: false,
|
||||||
|
})
|
||||||
|
this.canvasManager.canvas.add(this.demoObject)
|
||||||
|
this.canvasManager.canvas.renderAll()
|
||||||
|
}
|
||||||
|
clearDemoObject() {
|
||||||
|
this.canvasManager.canvas.remove(this.demoObject)
|
||||||
|
this.demoObject = null
|
||||||
|
}
|
||||||
|
createIndicatorObject() {
|
||||||
const rect = new fabric.Rect({
|
const rect = new fabric.Rect({
|
||||||
left: this.startX,
|
left: this.startX,
|
||||||
top: this.startY,
|
top: this.startY,
|
||||||
@@ -43,10 +92,44 @@ export class AISelectboxToolManager {
|
|||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
evented: false,
|
evented: false,
|
||||||
})
|
})
|
||||||
this.demoObject = rect
|
this.indicatorObject = rect
|
||||||
this.canvasManager.canvas.add(rect)
|
this.canvasManager.canvas.add(rect)
|
||||||
this.canvasManager.canvas.renderAll()
|
this.canvasManager.canvas.renderAll()
|
||||||
}
|
}
|
||||||
|
clearIndicatorObject() {
|
||||||
|
this.canvasManager.canvas.remove(this.indicatorObject)
|
||||||
|
this.indicatorObject = null
|
||||||
|
}
|
||||||
|
// 处理画笔绘制图像
|
||||||
|
async handleBrushDrawImage(fabricImage: fabric.Object) {
|
||||||
|
if (!this.demoObject) return;
|
||||||
|
const tcanvas = new fabric.StaticCanvas(document.createElement("canvas"), {
|
||||||
|
width: this.demoObject.width,
|
||||||
|
height: this.demoObject.height,
|
||||||
|
enableRetinaScaling: false,
|
||||||
|
});
|
||||||
|
const demoObject = await cloneObjects([this.demoObject]).then(v => v[0])
|
||||||
|
tcanvas.add(demoObject)
|
||||||
|
tcanvas.add(fabricImage)
|
||||||
|
tcanvas.renderAll();
|
||||||
|
const canvas = getObjectAlphaToCanvas(tcanvas, null, 0, this.rgba);
|
||||||
|
const image = new fabric.Image(canvas);
|
||||||
|
this.canvasManager.canvas.add(image)
|
||||||
|
this.canvasManager.canvas.remove(this.demoObject);
|
||||||
|
this.demoObject = image;
|
||||||
|
this.canvasManager.canvas.renderAll()
|
||||||
|
}
|
||||||
|
mouseDownEvent(e) {
|
||||||
|
// if (true) return
|
||||||
|
const tool = this.toolManager.currentTool.value
|
||||||
|
const tools = [OperationType.AISELECT_ADD, OperationType.AISELECT_REMOVE]
|
||||||
|
if (!tools.includes(tool)) return;
|
||||||
|
|
||||||
|
this.isDragging = true
|
||||||
|
this.startX = e.absolutePointer.x
|
||||||
|
this.startY = e.absolutePointer.y
|
||||||
|
this.createIndicatorObject()
|
||||||
|
}
|
||||||
mouseMoveEvent(e) {
|
mouseMoveEvent(e) {
|
||||||
if (!this.isDragging) return;
|
if (!this.isDragging) return;
|
||||||
var width = e.absolutePointer.x - this.startX
|
var width = e.absolutePointer.x - this.startX
|
||||||
@@ -61,25 +144,23 @@ export class AISelectboxToolManager {
|
|||||||
top += height
|
top += height
|
||||||
height = -height
|
height = -height
|
||||||
}
|
}
|
||||||
this.demoObject.set({ width, height, left, top })
|
this.indicatorObject.set({ width, height, left, top })
|
||||||
this.canvasManager.canvas.renderAll()
|
this.canvasManager.canvas.renderAll()
|
||||||
}
|
}
|
||||||
mouseUpEvent(e) {
|
mouseUpEvent(e) {
|
||||||
if (!this.isDragging) return;
|
if (!this.isDragging) return;
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
const object = this.demoObject.toJSON("evented")
|
const object = this.indicatorObject.toJSON("evented")
|
||||||
if (object.width === 0) object.width = 100
|
if (object.width === 0) object.width = 100
|
||||||
if (object.height === 0) object.height = 100
|
if (object.height === 0) object.height = 100
|
||||||
// console.log(object)
|
console.log(object.top, object.left, object.width, object.height)
|
||||||
this.canvasManager.canvas.remove(this.demoObject)
|
this.clearIndicatorObject()
|
||||||
this.canvasManager.canvas.renderAll()
|
this.canvasManager.canvas.renderAll()
|
||||||
|
|
||||||
// this.createSelectbox()
|
// this.createSelectbox()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loadImageToObject(url) {
|
loadImageToObject(url) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fabric.Image.fromURL(url, (img) => {
|
fabric.Image.fromURL(url, (img) => {
|
||||||
@@ -87,7 +168,7 @@ export class AISelectboxToolManager {
|
|||||||
}, { crossOrigin: "anonymous" });// 防止污染
|
}, { crossOrigin: "anonymous" });// 防止污染
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
rgba = { r: 0, g: 255, b: 0, a: 200 };
|
rgba = { r: 255, g: 0, b: 0, a: 127.5 };
|
||||||
selectionStyle = {
|
selectionStyle = {
|
||||||
stroke: "rgba(255, 77, 71, 1)",
|
stroke: "rgba(255, 77, 71, 1)",
|
||||||
strokeWidth: 1.5,
|
strokeWidth: 1.5,
|
||||||
@@ -99,12 +180,12 @@ export class AISelectboxToolManager {
|
|||||||
absolutePositioned: true,
|
absolutePositioned: true,
|
||||||
};
|
};
|
||||||
async createSelectbox() {
|
async createSelectbox() {
|
||||||
const url = "http://118.31.39.42:3000/falls/1a48ed3a-1faa-4fcd-bf07-765dba1702c5.png"
|
// const url = "http://118.31.39.42:3000/falls/1a48ed3a-1faa-4fcd-bf07-765dba1702c5.png"
|
||||||
const image = await this.loadImageToObject(url)
|
// const image = await this.loadImageToObject(url)
|
||||||
const canvas = getObjectAlphaToCanvas(image, null, 0, this.rgba);
|
// const fobject = this.canvasManager.canvas.clipPath
|
||||||
const fobject = this.canvasManager.canvas.clipPath
|
const fobject = this.demoObject
|
||||||
// const top = fobject.top - fobject.height * scaleY / 2;
|
this.clearDemoObject()
|
||||||
// const left = fobject.left - fobject.width * scaleX / 2;
|
const canvas = getObjectAlphaToCanvas(fobject, null, 0, { r: 255, g: 0, b: 0, a: 255 });
|
||||||
const scaleY = fobject.scaleY
|
const scaleY = fobject.scaleY
|
||||||
const scaleX = fobject.scaleX
|
const scaleX = fobject.scaleX
|
||||||
const top = fobject.top
|
const top = fobject.top
|
||||||
@@ -127,6 +208,8 @@ export class AISelectboxToolManager {
|
|||||||
});
|
});
|
||||||
const group = await this.layerManager.createGroupLayer({
|
const group = await this.layerManager.createGroupLayer({
|
||||||
clipPath: path,
|
clipPath: path,
|
||||||
|
top: path.top,
|
||||||
|
left: path.left,
|
||||||
}, false, false)
|
}, false, false)
|
||||||
const rect = await this.layerManager.createRectLayer({
|
const rect = await this.layerManager.createRectLayer({
|
||||||
width: path.width,
|
width: path.width,
|
||||||
@@ -145,5 +228,7 @@ export class AISelectboxToolManager {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
dispose() { }
|
dispose() {
|
||||||
|
this.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ fabric.Object.prototype.toObject = function () {
|
|||||||
const object = this.toObject_(arr)
|
const object = this.toObject_(arr)
|
||||||
if (object.info) {
|
if (object.info) {
|
||||||
let lock = !!object.info.lock
|
let lock = !!object.info.lock
|
||||||
|
if (object.type === "group") lock = true
|
||||||
object.evented = !lock
|
object.evented = !lock
|
||||||
object.selectable = !lock
|
object.selectable = !lock
|
||||||
}
|
}
|
||||||
@@ -214,7 +215,13 @@ export class CanvasManager {
|
|||||||
const obj = this.getObjectById(id)
|
const obj = this.getObjectById(id)
|
||||||
if (!obj) return
|
if (!obj) return
|
||||||
if (obj.type === "group") {
|
if (obj.type === "group") {
|
||||||
const objects = [];
|
obj._originPosition = {
|
||||||
|
top: obj.top,
|
||||||
|
left: obj.left,
|
||||||
|
cpTop: obj.clipPath.top,
|
||||||
|
cpLeft: obj.clipPath.left,
|
||||||
|
}
|
||||||
|
const objects = [obj];
|
||||||
this.getObjects().forEach((item: any) => {
|
this.getObjects().forEach((item: any) => {
|
||||||
if (item?.info?.parentId === id) objects.push(item)
|
if (item?.info?.parentId === id) objects.push(item)
|
||||||
})
|
})
|
||||||
@@ -258,6 +265,9 @@ export class CanvasManager {
|
|||||||
getObjectById(id: string) {
|
getObjectById(id: string) {
|
||||||
return this.getObjects().find((item: any) => item?.info?.id === id)
|
return this.getObjects().find((item: any) => item?.info?.id === id)
|
||||||
}
|
}
|
||||||
|
getChildObjectsById(id: string) {
|
||||||
|
return this.getObjects().filter((item: any) => item?.info?.parentId === id)
|
||||||
|
}
|
||||||
/** 获取选中对象 */
|
/** 获取选中对象 */
|
||||||
getSelectedObject() {
|
getSelectedObject() {
|
||||||
return this.canvas.getActiveObject()
|
return this.canvas.getActiveObject()
|
||||||
@@ -285,6 +295,8 @@ export class CanvasManager {
|
|||||||
const currentTool = this.stateManager.toolManager.currentTool.value;
|
const currentTool = this.stateManager.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (currentTool === OperationType.DRAW) {
|
||||||
this.handleDrawImage(fabricImage)
|
this.handleDrawImage(fabricImage)
|
||||||
|
} else if (currentTool === OperationType.AISELECT_DRAW) {
|
||||||
|
this.stateManager.aiSelectboxToolManager.handleBrushDrawImage(fabricImage)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
};
|
};
|
||||||
@@ -293,7 +305,7 @@ export class CanvasManager {
|
|||||||
async handleDrawImage(fabricImage: fabric.Object) {
|
async handleDrawImage(fabricImage: fabric.Object) {
|
||||||
const activeID = this.stateManager.layerManager.activeID.value
|
const activeID = this.stateManager.layerManager.activeID.value
|
||||||
const activeLayer = this.getObjectById(activeID)
|
const activeLayer = this.getObjectById(activeID)
|
||||||
if (activeLayer && activeLayer.fill?.repeat !== "repeat") {
|
if (activeLayer && activeLayer.fill?.repeat !== "repeat" && activeLayer.type !== "group") {
|
||||||
this.layerManager.imageMergeToLayer(activeLayer, fabricImage)
|
this.layerManager.imageMergeToLayer(activeLayer, fabricImage)
|
||||||
} else {
|
} else {
|
||||||
const emptyLayer = await this.layerManager.createEmptyLayer(false);
|
const emptyLayer = await this.layerManager.createEmptyLayer(false);
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ export class LayerManager {
|
|||||||
onMounted() { }
|
onMounted() { }
|
||||||
setActiveID(id: string, isActive = true) {
|
setActiveID(id: string, isActive = true) {
|
||||||
const layer = this.getLayerById(id)
|
const layer = this.getLayerById(id)
|
||||||
if (layer?.type === "group") {
|
// if (layer?.type === "group") {
|
||||||
this.activeID.value = ""
|
// this.activeID.value = ""
|
||||||
} else {
|
// } else {
|
||||||
this.activeID.value = id
|
this.activeID.value = id
|
||||||
}
|
// }
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
this.canvasManager.setActiveObjectById(id)
|
this.canvasManager.setActiveObjectById(id)
|
||||||
this.stateManager.toolManager.setTool(OperationType.SELECT)
|
this.stateManager.toolManager.setTool(OperationType.SELECT)
|
||||||
@@ -62,11 +62,21 @@ export class LayerManager {
|
|||||||
setLayerVisibleById(id, visible: boolean) {
|
setLayerVisibleById(id, visible: boolean) {
|
||||||
const layer = this.getLayerById(id)
|
const layer = this.getLayerById(id)
|
||||||
const object = this.canvasManager.getObjectById(id)
|
const object = this.canvasManager.getObjectById(id)
|
||||||
|
const call = (layer, object) => {
|
||||||
if (!layer || !object) return
|
if (!layer || !object) return
|
||||||
layer.visible = visible
|
layer.visible = visible
|
||||||
object.set({
|
object.set({
|
||||||
visible: visible
|
visible: visible
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
call(layer, object)
|
||||||
|
if (object.type === "group") {
|
||||||
|
const children = this.canvasManager.getChildObjectsById(id)
|
||||||
|
children.forEach(v => {
|
||||||
|
const layer = this.getLayerById(v.info.id)
|
||||||
|
call(layer, v)
|
||||||
|
})
|
||||||
|
}
|
||||||
this.canvasManager.renderAll()
|
this.canvasManager.renderAll()
|
||||||
this.stateManager.recordState()
|
this.stateManager.recordState()
|
||||||
}
|
}
|
||||||
@@ -74,14 +84,26 @@ export class LayerManager {
|
|||||||
setLayerLockById(id, lock: boolean) {
|
setLayerLockById(id, lock: boolean) {
|
||||||
const layer = this.getLayerById(id)
|
const layer = this.getLayerById(id)
|
||||||
const object = this.canvasManager.getObjectById(id)
|
const object = this.canvasManager.getObjectById(id)
|
||||||
|
const call = (layer, object) => {
|
||||||
if (!layer || !object) return
|
if (!layer || !object) return
|
||||||
layer.info.lock = !!lock
|
layer.info.lock = !!lock
|
||||||
layer.evented = !lock
|
layer.evented = !lock
|
||||||
object.info.lock = !!lock
|
object.info.lock = !!lock
|
||||||
|
if (object.type !== "group") {
|
||||||
object.set({
|
object.set({
|
||||||
evented: !lock,
|
evented: !lock,
|
||||||
selectable: !lock,
|
selectable: !lock,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call(layer, object)
|
||||||
|
if (object.type === "group") {
|
||||||
|
const children = this.canvasManager.getChildObjectsById(id)
|
||||||
|
children.forEach(v => {
|
||||||
|
const layer = this.getLayerById(v.info.id)
|
||||||
|
call(layer, v)
|
||||||
|
})
|
||||||
|
}
|
||||||
if (lock) {
|
if (lock) {
|
||||||
// 取消选中对象
|
// 取消选中对象
|
||||||
const e = this.canvasManager.getSelectedObject()
|
const e = this.canvasManager.getSelectedObject()
|
||||||
@@ -194,13 +216,14 @@ export class LayerManager {
|
|||||||
}
|
}
|
||||||
/** 创建组图层 */
|
/** 创建组图层 */
|
||||||
async createGroupLayer(options?: any, isRecord = true, isActive = false) {
|
async createGroupLayer(options?: any, isRecord = true, isActive = false) {
|
||||||
const children = options?.children || []
|
const groupObject = new fabric.Group([], {
|
||||||
delete options.children
|
|
||||||
const groupObject = new fabric.Group(children, {
|
|
||||||
...(options || {}),
|
...(options || {}),
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
hasControls: false, // 不显示控制点
|
hasControls: false, // 不显示控制点
|
||||||
hasBorders: false, // 不显示边框
|
hasBorders: false, // 不显示边框
|
||||||
selectable: false, // 不可选中(可选)
|
selectable: false, // 不可选中(可选)
|
||||||
|
evented: false,
|
||||||
info: {
|
info: {
|
||||||
id: createId("group"),
|
id: createId("group"),
|
||||||
name: '智能选区组',
|
name: '智能选区组',
|
||||||
@@ -423,10 +446,18 @@ export class LayerManager {
|
|||||||
const objects = this.canvasManager.getObjects()
|
const objects = this.canvasManager.getObjects()
|
||||||
objects.forEach((item: any) => {
|
objects.forEach((item: any) => {
|
||||||
item.set({
|
item.set({
|
||||||
erasable: item.info.id === this.activeID.value
|
erasable: (item.info.id === this.activeID.value && item.type !== "group")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/** 设置所有对象擦除属性 */
|
||||||
|
setAllObjectsErasable(isErasable = false) {
|
||||||
|
const objects = this.canvasManager.getObjects()
|
||||||
|
objects.forEach((item: any) => {
|
||||||
|
item.set({ erasable: isErasable })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/** 更新图层缩略图 */
|
/** 更新图层缩略图 */
|
||||||
async updateLayerThumbnailsById(id: string, thumbnail?: string, isUpdate = true) {
|
async updateLayerThumbnailsById(id: string, thumbnail?: string, isUpdate = true) {
|
||||||
const object = this.canvasManager.getObjectById(id);
|
const object = this.canvasManager.getObjectById(id);
|
||||||
|
|||||||
@@ -46,9 +46,25 @@ export class ToolManager {
|
|||||||
},
|
},
|
||||||
/** 智能选框工具 */
|
/** 智能选框工具 */
|
||||||
{
|
{
|
||||||
name: OperationType.SELECTBOX,
|
name: OperationType.AISELECT_ADD,
|
||||||
cursor: "crosshair",
|
cursor: "crosshair",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: OperationType.AISELECT_REMOVE,
|
||||||
|
cursor: "crosshair",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: OperationType.AISELECT_DRAW,
|
||||||
|
cursor: "crosshair",
|
||||||
|
setup: this.setupAISelectBrushTool.bind(this),
|
||||||
|
isDrawingMode: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: OperationType.AISELECT_ERASER,
|
||||||
|
cursor: "crosshair",
|
||||||
|
setup: this.setupAISelectEraserTool.bind(this),
|
||||||
|
isDrawingMode: true,
|
||||||
|
},
|
||||||
/** 矩形工具 */
|
/** 矩形工具 */
|
||||||
{
|
{
|
||||||
name: OperationType.RECTANGLE,
|
name: OperationType.RECTANGLE,
|
||||||
@@ -120,7 +136,7 @@ export class ToolManager {
|
|||||||
setCanvasEvented(value: boolean) {
|
setCanvasEvented(value: boolean) {
|
||||||
this.canvasManager.canvas.selection = value
|
this.canvasManager.canvas.selection = value
|
||||||
this.canvasManager.canvas.getObjects().forEach((v) => {
|
this.canvasManager.canvas.getObjects().forEach((v) => {
|
||||||
if (v.info?.lock) return
|
if (v.info?.lock || v.type === "group") return
|
||||||
v.evented = value
|
v.evented = value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -179,6 +195,46 @@ export class ToolManager {
|
|||||||
this._enableBrushIndicator();
|
this._enableBrushIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 智能选区画笔工具 */
|
||||||
|
setupAISelectBrushTool() {
|
||||||
|
if (!this.canvasManager.canvas) return;
|
||||||
|
|
||||||
|
// 确保有笔刷管理器
|
||||||
|
if (this.brushManager) {
|
||||||
|
// 检查画笔是否正在更新中
|
||||||
|
if (this.brushManager.isUpdatingBrush) {
|
||||||
|
console.warn("画笔正在更新中,请稍候...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.brushManager.setBrushSize(5);
|
||||||
|
this.brushManager.setBrushColor("rgb(255, 0, 0)");
|
||||||
|
this.brushManager.setBrushOpacity(0.5);
|
||||||
|
this.brushManager.setBrushType("pencil");
|
||||||
|
// 更新应用到画布
|
||||||
|
this.brushManager.updateBrush();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启用笔刷指示器并同步颜色
|
||||||
|
this._enableBrushIndicator();
|
||||||
|
}
|
||||||
|
/** 智能选区橡皮擦工具 */
|
||||||
|
setupAISelectEraserTool() {
|
||||||
|
if (!this.canvasManager.canvas) return;
|
||||||
|
|
||||||
|
// 确保有笔刷管理器
|
||||||
|
if (this.brushManager) {
|
||||||
|
this.brushManager.createEraser();
|
||||||
|
this.brushManager.setBrushSize(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stateManager.layerManager.setAllObjectsErasable(false)
|
||||||
|
// 启用笔刷指示器
|
||||||
|
this._enableBrushIndicator();
|
||||||
|
|
||||||
|
this.stateManager.aiSelectboxToolManager.changeToolToEraser()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启用笔刷指示器
|
* 启用笔刷指示器
|
||||||
* @param {String} color 笔刷颜色(可选)
|
* @param {String} color 笔刷颜色(可选)
|
||||||
|
|||||||
@@ -187,6 +187,58 @@ export class CanvasEventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleMouseDown(opt) {
|
||||||
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
|
if (currentTool === OperationType.DRAW) {
|
||||||
|
// 绘画模式
|
||||||
|
} else if (currentTool === OperationType.ERASER) {
|
||||||
|
// 橡皮擦模式
|
||||||
|
} else if (this.aiSelectboxToolManager.tools.includes(currentTool)) {
|
||||||
|
// 选择框模式
|
||||||
|
this.aiSelectboxToolManager.mouseDownEvent(opt);
|
||||||
|
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
||||||
|
// 形状模式
|
||||||
|
this.shapeToolManager.mouseDownEvent(opt);
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_handleMouseMove(opt) {
|
||||||
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
|
if (currentTool === OperationType.DRAW) {
|
||||||
|
// 绘画模式
|
||||||
|
} else if (currentTool === OperationType.ERASER) {
|
||||||
|
// 橡皮擦模式
|
||||||
|
} else if (this.aiSelectboxToolManager.tools.includes(currentTool)) {
|
||||||
|
// 选择框模式
|
||||||
|
this.aiSelectboxToolManager.mouseMoveEvent(opt);
|
||||||
|
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
||||||
|
// 形状模式
|
||||||
|
this.shapeToolManager.mouseMoveEvent(opt);
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_handleMouseUp(opt) {
|
||||||
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
|
if (currentTool === OperationType.DRAW) {
|
||||||
|
// 绘画模式
|
||||||
|
} else if (currentTool === OperationType.ERASER) {
|
||||||
|
// 橡皮擦模式
|
||||||
|
} else if (this.aiSelectboxToolManager.tools.includes(currentTool)) {
|
||||||
|
// 选择框模式
|
||||||
|
this.aiSelectboxToolManager.mouseUpEvent(opt);
|
||||||
|
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
||||||
|
// 形状模式
|
||||||
|
this.shapeToolManager.mouseUpEvent(opt);
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置鼠标事件处理
|
* 设置鼠标事件处理
|
||||||
*/
|
*/
|
||||||
@@ -202,16 +254,7 @@ export class CanvasEventManager {
|
|||||||
|
|
||||||
// } else
|
// } else
|
||||||
const currentTool = this.toolManager.currentTool.value;
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (this._handleMouseDown(opt)) {
|
||||||
// 绘画模式
|
|
||||||
} else if (currentTool === OperationType.ERASER) {
|
|
||||||
// 橡皮擦模式
|
|
||||||
} else if (currentTool === OperationType.SELECTBOX) {
|
|
||||||
// 选择框模式
|
|
||||||
this.aiSelectboxToolManager.mouseDownEvent(opt);
|
|
||||||
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
|
||||||
// 形状模式
|
|
||||||
this.shapeToolManager.mouseDownEvent(opt);
|
|
||||||
} else if (opt.e.altKey || opt.e.which === 2 || currentTool === OperationType.PAN) {
|
} else if (opt.e.altKey || opt.e.which === 2 || currentTool === OperationType.PAN) {
|
||||||
this.canvas.isDragging = true;
|
this.canvas.isDragging = true;
|
||||||
this.canvas.lastPosX = opt.e.clientX;
|
this.canvas.lastPosX = opt.e.clientX;
|
||||||
@@ -230,16 +273,7 @@ export class CanvasEventManager {
|
|||||||
// 鼠标移动事件
|
// 鼠标移动事件
|
||||||
this.canvas.on("mouse:move", (opt) => {
|
this.canvas.on("mouse:move", (opt) => {
|
||||||
const currentTool = this.toolManager.currentTool.value;
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (this._handleMouseMove(opt)) {
|
||||||
// 绘画模式
|
|
||||||
} else if (currentTool === OperationType.ERASER) {
|
|
||||||
// 橡皮擦模式
|
|
||||||
} else if (currentTool === OperationType.SELECTBOX) {
|
|
||||||
// 选择框模式
|
|
||||||
this.aiSelectboxToolManager.mouseMoveEvent(opt);
|
|
||||||
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
|
||||||
// 形状模式
|
|
||||||
this.shapeToolManager.mouseMoveEvent(opt);
|
|
||||||
} else if (this.canvas.isDragging) {
|
} else if (this.canvas.isDragging) {
|
||||||
const vpt = this.canvas.viewportTransform;
|
const vpt = this.canvas.viewportTransform;
|
||||||
vpt[4] += opt.e.clientX - this.canvas.lastPosX;
|
vpt[4] += opt.e.clientX - this.canvas.lastPosX;
|
||||||
@@ -314,16 +348,7 @@ export class CanvasEventManager {
|
|||||||
this.canvas.on("mouse:down", (opt) => {
|
this.canvas.on("mouse:down", (opt) => {
|
||||||
// 只在PAN模式下处理触摸事件
|
// 只在PAN模式下处理触摸事件
|
||||||
const currentTool = this.toolManager.currentTool.value;
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (this._handleMouseDown(opt)) {
|
||||||
// 绘画模式
|
|
||||||
} else if (currentTool === OperationType.ERASER) {
|
|
||||||
// 橡皮擦模式
|
|
||||||
} else if (currentTool === OperationType.SELECTBOX) {
|
|
||||||
// 选择框模式
|
|
||||||
this.aiSelectboxToolManager.mouseUpEvent(opt);
|
|
||||||
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
|
||||||
// 形状模式
|
|
||||||
this.shapeToolManager.mouseDownEvent(opt);
|
|
||||||
} else if (currentTool === OperationType.PAN) {
|
} else if (currentTool === OperationType.PAN) {
|
||||||
|
|
||||||
// 平滑停止任何正在进行的惯性动画
|
// 平滑停止任何正在进行的惯性动画
|
||||||
@@ -379,16 +404,7 @@ export class CanvasEventManager {
|
|||||||
this.canvas.on("mouse:move", (opt) => {
|
this.canvas.on("mouse:move", (opt) => {
|
||||||
|
|
||||||
const currentTool = this.toolManager.currentTool.value;
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (this._handleMouseMove(opt)) {
|
||||||
// 绘画模式
|
|
||||||
} else if (currentTool === OperationType.ERASER) {
|
|
||||||
// 橡皮擦模式
|
|
||||||
} else if (currentTool === OperationType.SELECTBOX) {
|
|
||||||
// 选择框模式
|
|
||||||
this.aiSelectboxToolManager.mouseMoveEvent(opt);
|
|
||||||
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
|
||||||
// 形状模式
|
|
||||||
this.shapeToolManager.mouseMoveEvent(opt);
|
|
||||||
} else if (currentTool === OperationType.PAN) {
|
} else if (currentTool === OperationType.PAN) {
|
||||||
|
|
||||||
// 检查是否是触摸事件
|
// 检查是否是触摸事件
|
||||||
@@ -489,16 +505,7 @@ export class CanvasEventManager {
|
|||||||
// 触摸结束事件
|
// 触摸结束事件
|
||||||
this.canvas.on("mouse:up", (opt) => {
|
this.canvas.on("mouse:up", (opt) => {
|
||||||
const currentTool = this.toolManager.currentTool.value;
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (this._handleMouseUp(opt)) {
|
||||||
// 绘画模式
|
|
||||||
} else if (currentTool === OperationType.ERASER) {
|
|
||||||
// 橡皮擦模式
|
|
||||||
} else if (currentTool === OperationType.SELECTBOX) {
|
|
||||||
// 选择框模式
|
|
||||||
this.aiSelectboxToolManager.mouseUpEvent(opt);
|
|
||||||
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
|
||||||
// 形状模式
|
|
||||||
this.shapeToolManager.mouseUpEvent(opt);
|
|
||||||
} else if (currentTool === OperationType.PAN) {
|
} else if (currentTool === OperationType.PAN) {
|
||||||
|
|
||||||
// 重置触摸状态
|
// 重置触摸状态
|
||||||
@@ -661,16 +668,7 @@ export class CanvasEventManager {
|
|||||||
*/
|
*/
|
||||||
handleDragEnd(opt, isTouch = false) {
|
handleDragEnd(opt, isTouch = false) {
|
||||||
const currentTool = this.toolManager.currentTool.value;
|
const currentTool = this.toolManager.currentTool.value;
|
||||||
if (currentTool === OperationType.DRAW) {
|
if (this._handleMouseUp(opt)) {
|
||||||
// 绘画模式
|
|
||||||
} else if (currentTool === OperationType.ERASER) {
|
|
||||||
// 橡皮擦模式
|
|
||||||
} else if (currentTool === OperationType.SELECTBOX) {
|
|
||||||
// 选择框模式
|
|
||||||
this.aiSelectboxToolManager.mouseUpEvent(opt);
|
|
||||||
} else if (this.shapeToolManager.tools.includes(currentTool)) {
|
|
||||||
// 形状模式
|
|
||||||
this.shapeToolManager.mouseUpEvent(opt);
|
|
||||||
} else if (this.canvas.isDragging) {
|
} else if (this.canvas.isDragging) {
|
||||||
// if (this.lastMousePositions.length > 1 && opt && opt.e) {
|
// if (this.lastMousePositions.length > 1 && opt && opt.e) {
|
||||||
// this.animationManager.applyInertiaEffect(
|
// this.animationManager.applyInertiaEffect(
|
||||||
@@ -691,9 +689,16 @@ export class CanvasEventManager {
|
|||||||
|
|
||||||
this.canvas.on("selection:updated", (opt) => this.updateSelectedLayer(opt));
|
this.canvas.on("selection:updated", (opt) => this.updateSelectedLayer(opt));
|
||||||
|
|
||||||
// this.canvas.on("selection:cleared", () => this.clearSelectedElements());
|
this.canvas.on("selection:cleared", (opt) => this.clearSelectedElements(opt));
|
||||||
|
}
|
||||||
|
clearSelectedElements(opt) {
|
||||||
|
if (opt.deselected && opt.deselected.length > 0) {
|
||||||
|
opt.deselected.forEach((object) => {
|
||||||
|
if (object.type !== "group") return;
|
||||||
|
if (object._originPosition) delete object._originPosition
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupObjectEvents() {
|
setupObjectEvents() {
|
||||||
// 监听对象变化事件,用于更新缩略图
|
// 监听对象变化事件,用于更新缩略图
|
||||||
// this.canvas.on("object:added", (e) => {
|
// this.canvas.on("object:added", (e) => {
|
||||||
@@ -706,34 +711,43 @@ export class CanvasEventManager {
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
const updateLayers = (e) => {
|
|
||||||
if (e.target._objects) return;
|
|
||||||
// this.layerManager.updateLayers();// 先不用数据大了非常卡
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加对象开始变换时的状态捕获
|
// 添加对象开始变换时的状态捕获
|
||||||
this.canvas.on("object:moving", (e) => {
|
this.canvas.on("object:moving", (e) => {
|
||||||
// console.log("object:moving", e);
|
console.log("object:moving", e);
|
||||||
// updateLayers(e);
|
const target = e.target;
|
||||||
|
if (target._objects && target._objects.length > 0) {
|
||||||
|
target._objects.forEach((object) => {
|
||||||
|
if (object.type !== "group") return;
|
||||||
|
if (!object._originPosition) return
|
||||||
|
const originTop = object._originPosition.top
|
||||||
|
const originLeft = object._originPosition.left
|
||||||
|
const originCpTop = object._originPosition.cpTop
|
||||||
|
const originCpLeft = object._originPosition.cpLeft
|
||||||
|
const top = object.top + target.top + target.height / 2;
|
||||||
|
const left = object.left + target.left + target.width / 2;
|
||||||
|
object.clipPath.set({
|
||||||
|
top: originCpTop + (top - originTop),
|
||||||
|
left: originCpLeft + (left - originLeft),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.canvasManager.updateSubLayerClipPath()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.canvas.on("object:scaling", (e) => {
|
this.canvas.on("object:scaling", (e) => {
|
||||||
// console.log("object:scaling", e);
|
// console.log("object:scaling", e);
|
||||||
// updateLayers(e);
|
|
||||||
});
|
});
|
||||||
this.canvas.on("object:rotating", (e) => {
|
this.canvas.on("object:rotating", (e) => {
|
||||||
// console.log("object:rotating", e);
|
// console.log("object:rotating", e);
|
||||||
// updateLayers(e);
|
|
||||||
});
|
});
|
||||||
this.canvas.on("object:skewing", (e) => {
|
this.canvas.on("object:skewing", (e) => {
|
||||||
// console.log("object:skewing", e);
|
// console.log("object:skewing", e);
|
||||||
// updateLayers(e);
|
|
||||||
});
|
});
|
||||||
this.canvas.on("object:modified", async (e) => {
|
this.canvas.on("object:modified", async (e) => {
|
||||||
// updateLayers(e);
|
// console.log("object:modified", e);
|
||||||
const target = e.target;
|
const target = e.target;
|
||||||
const id = target?.info?.id;
|
const id = target?.info?.id;
|
||||||
if (id) await this.layerManager.updateLayerThumbnailsById(id)
|
if (id) await this.layerManager.updateLayerThumbnailsById(id)
|
||||||
if (target.type === "group") await this.canvasManager.updateSubLayerClipPath()
|
|
||||||
this.stateManager.recordState();
|
this.stateManager.recordState();
|
||||||
});
|
});
|
||||||
this.canvas.on("object:removed", (e) => {
|
this.canvas.on("object:removed", (e) => {
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ export const OperationType = {
|
|||||||
PAN: "pan", // 拖拽模式
|
PAN: "pan", // 拖拽模式
|
||||||
DRAW: "draw", // 绘画模式
|
DRAW: "draw", // 绘画模式
|
||||||
ERASER: "eraser", // 橡皮擦模式
|
ERASER: "eraser", // 橡皮擦模式
|
||||||
SELECTBOX: "selectbox",// 选择框工具模式
|
|
||||||
|
AISELECT_ADD: "aiSelectAdd",// 智能框选添加模式
|
||||||
|
AISELECT_REMOVE: "aiSelectRemove",// 智能框选删除模式
|
||||||
|
AISELECT_DRAW: "aiSelectDraw",// 智能框选绘制模式
|
||||||
|
AISELECT_ERASER: "aiSelectEraser",// 智能框选橡皮擦模式
|
||||||
|
|
||||||
RECTANGLE: "rectangle",// 矩形工具模式
|
RECTANGLE: "rectangle",// 矩形工具模式
|
||||||
LINE: "line",// 直线工具模式
|
LINE: "line",// 直线工具模式
|
||||||
@@ -68,11 +72,3 @@ export const BlendMode = {
|
|||||||
DESTINATION_IN: "destination-in", // 目标内
|
DESTINATION_IN: "destination-in", // 目标内
|
||||||
DESTINATION_OUT: "destination-out", // 目标外
|
DESTINATION_OUT: "destination-out", // 目标外
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 智能框选工具类型枚举 */
|
|
||||||
export const AI_SELECTBOX_TYPE = {
|
|
||||||
ADD: "add", // 添加模式
|
|
||||||
REMOVE: "remove", // 删除模式
|
|
||||||
DRAW: "draw", // 绘画模式
|
|
||||||
ERASER: "eraser", // 橡皮擦模式
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,12 +10,13 @@
|
|||||||
import { computed, onMounted } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const url = 'https://www.minio-api.aida.com.hk/fida-test/furniture/sketches/1a48ed3a-1faa-4fcd-bf07-765dba1702c5.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20260320%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260320T020948Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=7dc192bac887bce7b02c99d7037c08d9d684310f00add9b0e63b74b36ee63d37'
|
const url =
|
||||||
|
'https://www.minio-api.aida.com.hk/fida-test/furniture/sketches/1a48ed3a-1faa-4fcd-bf07-765dba1702c5.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20260320%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260320T020948Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=7dc192bac887bce7b02c99d7037c08d9d684310f00add9b0e63b74b36ee63d37'
|
||||||
const openCanvas = () => {
|
const openCanvas = () => {
|
||||||
myEvent.emit('openFlowCanvas', { url })
|
myEvent.emit('openFlowCanvas', { url })
|
||||||
}
|
}
|
||||||
const openDepthCanvas = () => {
|
const openDepthCanvas = () => {
|
||||||
myEvent.emit('openDepthCanvas', { url })
|
myEvent.emit('openDepthCanvas', { url, canvasId: '69c34539ce996b52f07e625f' })
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (route.query.depth) {
|
if (route.query.depth) {
|
||||||
|
|||||||
Reference in New Issue
Block a user