Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/FiDA_Front
This commit is contained in:
8
src/assets/icons/textToolsDecoration.svg
Normal file
8
src/assets/icons/textToolsDecoration.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="path-1-outside-1_3940_24441" maskUnits="userSpaceOnUse" x="-0.700195" y="-0.699219" width="14" height="14" fill="black">
|
||||||
|
<rect fill="white" x="-0.700195" y="-0.699219" width="14" height="14"/>
|
||||||
|
<path d="M11.7998 11.3008C12.0759 11.3008 12.2998 11.5246 12.2998 11.8008C12.2998 12.0769 12.0759 12.3008 11.7998 12.3008H0.799805C0.523663 12.3008 0.299805 12.0769 0.299805 11.8008C0.299805 11.5246 0.523663 11.3008 0.799805 11.3008H11.7998ZM9.7998 0.300781C10.0759 0.300781 10.2998 0.524639 10.2998 0.800781V5.30078C10.2998 7.50992 8.50894 9.30078 6.2998 9.30078C4.09067 9.30078 2.2998 7.50992 2.2998 5.30078V0.800781C2.2998 0.524639 2.52366 0.300781 2.7998 0.300781C3.07595 0.300781 3.2998 0.524639 3.2998 0.800781V5.30078C3.2998 6.95764 4.64295 8.30078 6.2998 8.30078C7.95666 8.30078 9.2998 6.95764 9.2998 5.30078V0.800781C9.2998 0.524639 9.52366 0.300781 9.7998 0.300781Z"/>
|
||||||
|
</mask>
|
||||||
|
<path d="M11.7998 11.3008C12.0759 11.3008 12.2998 11.5246 12.2998 11.8008C12.2998 12.0769 12.0759 12.3008 11.7998 12.3008H0.799805C0.523663 12.3008 0.299805 12.0769 0.299805 11.8008C0.299805 11.5246 0.523663 11.3008 0.799805 11.3008H11.7998ZM9.7998 0.300781C10.0759 0.300781 10.2998 0.524639 10.2998 0.800781V5.30078C10.2998 7.50992 8.50894 9.30078 6.2998 9.30078C4.09067 9.30078 2.2998 7.50992 2.2998 5.30078V0.800781C2.2998 0.524639 2.52366 0.300781 2.7998 0.300781C3.07595 0.300781 3.2998 0.524639 3.2998 0.800781V5.30078C3.2998 6.95764 4.64295 8.30078 6.2998 8.30078C7.95666 8.30078 9.2998 6.95764 9.2998 5.30078V0.800781C9.2998 0.524639 9.52366 0.300781 9.7998 0.300781Z" fill="#0D0D0D"/>
|
||||||
|
<path d="M11.7998 11.3008V11.0008V11.0008V11.3008ZM12.2998 11.8008H12.5998V11.8008H12.2998ZM11.7998 12.3008V12.0008V12.0008V12.3008ZM0.799805 12.3008L0.799805 12.6008H0.799805V12.3008ZM0.299805 11.8008H-0.000195324V11.8008H0.299805ZM0.799805 11.3008L0.799805 11.6008H0.799805V11.3008ZM11.7998 11.3008V11.6008C11.9103 11.6008 11.9998 11.6903 11.9998 11.8008H12.2998H12.5998C12.5998 11.359 12.2416 11.0008 11.7998 11.0008V11.3008ZM12.2998 11.8008H11.9998C11.9998 11.9112 11.9103 12.0008 11.7998 12.0008V12.3008V12.6008C12.2416 12.6008 12.5998 12.2426 12.5998 11.8008H12.2998ZM11.7998 12.3008V12.0008H0.799805V12.3008V12.6008H11.7998V12.3008ZM0.799805 12.3008V12.0008C0.689349 12.0008 0.599805 11.9112 0.599805 11.8008H0.299805H-0.000195324C-0.000194907 12.2426 0.357977 12.6008 0.799805 12.6008L0.799805 12.3008ZM0.299805 11.8008H0.599805C0.599805 11.6903 0.689348 11.6008 0.799805 11.6008L0.799805 11.3008V11.0008C0.357977 11.0008 -0.000195295 11.359 -0.000195324 11.8008H0.299805ZM0.799805 11.3008V11.6008H11.7998V11.3008V11.0008H0.799805V11.3008ZM9.7998 0.300781V0.600781C9.91026 0.600781 9.9998 0.690324 9.9998 0.800781H10.2998H10.5998C10.5998 0.358954 10.2416 0.000781238 9.7998 0.000781238V0.300781ZM10.2998 0.800781H9.9998V5.30078H10.2998H10.5998V0.800781H10.2998ZM10.2998 5.30078H9.9998C9.9998 7.34423 8.34326 9.00078 6.2998 9.00078V9.30078V9.60078C8.67463 9.60078 10.5998 7.67561 10.5998 5.30078H10.2998ZM6.2998 9.30078V9.00078C4.25635 9.00078 2.5998 7.34423 2.5998 5.30078H2.2998H1.9998C1.9998 7.67561 3.92498 9.60078 6.2998 9.60078V9.30078ZM2.2998 5.30078H2.5998V0.800781H2.2998H1.9998V5.30078H2.2998ZM2.2998 0.800781H2.5998C2.5998 0.690324 2.68935 0.600781 2.7998 0.600781V0.300781V0.000781238C2.35798 0.000781238 1.9998 0.358953 1.9998 0.800781H2.2998ZM2.7998 0.300781V0.600781C2.91026 0.600781 2.9998 0.690324 2.9998 0.800781H3.2998H3.5998C3.5998 0.358953 3.24163 0.000781238 2.7998 0.000781238V0.300781ZM3.2998 0.800781H2.9998V5.30078H3.2998H3.5998V0.800781H3.2998ZM3.2998 5.30078H2.9998C2.9998 7.12332 4.47726 8.60078 6.2998 8.60078V8.30078V8.00078C4.80864 8.00078 3.5998 6.79195 3.5998 5.30078H3.2998ZM6.2998 8.30078V8.60078C8.12234 8.60078 9.5998 7.12332 9.5998 5.30078H9.2998H8.9998C8.9998 6.79195 7.79097 8.00078 6.2998 8.00078V8.30078ZM9.2998 5.30078H9.5998V0.800781H9.2998H8.9998V5.30078H9.2998ZM9.2998 0.800781H9.5998C9.5998 0.690324 9.68935 0.600781 9.7998 0.600781V0.300781V0.000781238C9.35798 0.000781238 8.9998 0.358954 8.9998 0.800781H9.2998Z" fill="black" mask="url(#path-1-outside-1_3940_24441)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.1 KiB |
4
src/assets/icons/textToolsStyle.svg
Normal file
4
src/assets/icons/textToolsStyle.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="9" height="13" viewBox="0 0 9 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7.75 0.25C8.02614 0.25 8.25 0.473858 8.25 0.75C8.25 1.02614 8.02614 1.25 7.75 1.25H5.66797L3.84961 11.25H5.75C6.02614 11.25 6.25 11.4739 6.25 11.75C6.25 12.0261 6.02614 12.25 5.75 12.25H0.75C0.473858 12.25 0.25 12.0261 0.25 11.75C0.25 11.4739 0.473858 11.25 0.75 11.25H2.83203L4.65039 1.25H2.75C2.47386 1.25 2.25 1.02614 2.25 0.75C2.25 0.473858 2.47386 0.25 2.75 0.25H7.75Z" fill="#0D0D0D"/>
|
||||||
|
<path d="M5.66797 1.25V1H5.45933L5.422 1.20527L5.66797 1.25ZM3.84961 11.25L3.60364 11.2053L3.55005 11.5H3.84961V11.25ZM2.83203 11.25V11.5H3.04067L3.078 11.2947L2.83203 11.25ZM4.65039 1.25L4.89636 1.29473L4.94995 1H4.65039V1.25ZM7.75 0.25V0.5C7.88807 0.5 8 0.611929 8 0.75H8.25H8.5C8.5 0.335786 8.16421 0 7.75 0V0.25ZM8.25 0.75H8C8 0.888071 7.88807 1 7.75 1V1.25V1.5C8.16421 1.5 8.5 1.16421 8.5 0.75H8.25ZM7.75 1.25V1H5.66797V1.25V1.5H7.75V1.25ZM5.66797 1.25L5.422 1.20527L3.60364 11.2053L3.84961 11.25L4.09558 11.2947L5.91394 1.29473L5.66797 1.25ZM3.84961 11.25V11.5H5.75V11.25V11H3.84961V11.25ZM5.75 11.25V11.5C5.88807 11.5 6 11.6119 6 11.75H6.25H6.5C6.5 11.3358 6.16421 11 5.75 11V11.25ZM6.25 11.75H6C6 11.8881 5.88807 12 5.75 12V12.25V12.5C6.16421 12.5 6.5 12.1642 6.5 11.75H6.25ZM5.75 12.25V12H0.75V12.25V12.5H5.75V12.25ZM0.75 12.25V12C0.611929 12 0.5 11.8881 0.5 11.75H0.25H0C0 12.1642 0.335786 12.5 0.75 12.5V12.25ZM0.25 11.75H0.5C0.5 11.6119 0.611929 11.5 0.75 11.5V11.25V11C0.335786 11 0 11.3358 0 11.75H0.25ZM0.75 11.25V11.5H2.83203V11.25V11H0.75V11.25ZM2.83203 11.25L3.078 11.2947L4.89636 1.29473L4.65039 1.25L4.40442 1.20527L2.58606 11.2053L2.83203 11.25ZM4.65039 1.25V1H2.75V1.25V1.5H4.65039V1.25ZM2.75 1.25V1C2.61193 1 2.5 0.888071 2.5 0.75H2.25H2C2 1.16421 2.33579 1.5 2.75 1.5V1.25ZM2.25 0.75H2.5C2.5 0.611929 2.61193 0.5 2.75 0.5V0.25V0C2.33579 0 2 0.335786 2 0.75H2.25ZM2.75 0.25V0.5H7.75V0.25V0H2.75V0.25Z" fill="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
7
src/assets/icons/textToolsweight.svg
Normal file
7
src/assets/icons/textToolsweight.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg width="9" height="12" viewBox="0 0 9 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="path-1-inside-1_3940_24436" fill="white">
|
||||||
|
<path d="M4.75 0C6.54493 0 8 1.45507 8 3.25C8 4.08551 7.68116 4.84417 7.16309 5.41992C8.25691 6.01178 9 7.169 9 8.5C9 10.433 7.433 12 5.5 12H2C0.895431 12 0 11.1046 0 10V2C0 0.895431 0.895431 0 2 0H4.75ZM1.5 10C1.5 10.2761 1.72386 10.5 2 10.5H5.5C6.60457 10.5 7.5 9.60457 7.5 8.5C7.5 7.39543 6.60457 6.5 5.5 6.5H1.5V10ZM2 1.5C1.72386 1.5 1.5 1.72386 1.5 2V5H4.75C5.7165 5 6.5 4.2165 6.5 3.25C6.5 2.2835 5.7165 1.5 4.75 1.5H2Z"/>
|
||||||
|
</mask>
|
||||||
|
<path d="M4.75 0C6.54493 0 8 1.45507 8 3.25C8 4.08551 7.68116 4.84417 7.16309 5.41992C8.25691 6.01178 9 7.169 9 8.5C9 10.433 7.433 12 5.5 12H2C0.895431 12 0 11.1046 0 10V2C0 0.895431 0.895431 0 2 0H4.75ZM1.5 10C1.5 10.2761 1.72386 10.5 2 10.5H5.5C6.60457 10.5 7.5 9.60457 7.5 8.5C7.5 7.39543 6.60457 6.5 5.5 6.5H1.5V10ZM2 1.5C1.72386 1.5 1.5 1.72386 1.5 2V5H4.75C5.7165 5 6.5 4.2165 6.5 3.25C6.5 2.2835 5.7165 1.5 4.75 1.5H2Z" fill="#0D0D0D"/>
|
||||||
|
<path d="M7.16309 5.41992L6.79141 5.08548C6.6889 5.19939 6.6443 5.35402 6.67038 5.50503C6.69647 5.65604 6.79036 5.78675 6.92514 5.85967L7.16309 5.41992ZM1.5 6.5V6C1.22386 6 1 6.22386 1 6.5H1.5ZM1.5 5H1C1 5.27614 1.22386 5.5 1.5 5.5V5ZM4.75 0V0.5C6.26878 0.5 7.5 1.73122 7.5 3.25H8H8.5C8.5 1.17893 6.82107 -0.5 4.75 -0.5V0ZM8 3.25H7.5C7.5 3.95529 7.23147 4.59641 6.79141 5.08548L7.16309 5.41992L7.53477 5.75437C8.13085 5.09192 8.5 4.21573 8.5 3.25H8ZM7.16309 5.41992L6.92514 5.85967C7.86405 6.36771 8.5 7.3599 8.5 8.5H9H9.5C9.5 6.9781 8.64977 5.65585 7.40103 4.98017L7.16309 5.41992ZM9 8.5H8.5C8.5 10.1569 7.15685 11.5 5.5 11.5V12V12.5C7.70914 12.5 9.5 10.7091 9.5 8.5H9ZM5.5 12V11.5H2V12V12.5H5.5V12ZM2 12V11.5C1.17157 11.5 0.5 10.8284 0.5 10H0H-0.5C-0.5 11.3807 0.619288 12.5 2 12.5V12ZM0 10H0.5V2H0H-0.5V10H0ZM0 2H0.5C0.5 1.17157 1.17157 0.5 2 0.5V0V-0.5C0.619288 -0.5 -0.5 0.619288 -0.5 2H0ZM2 0V0.5H4.75V0V-0.5H2V0ZM1.5 10H1C1 10.5523 1.44772 11 2 11V10.5V10H1.5ZM2 10.5V11H5.5V10.5V10H2V10.5ZM5.5 10.5V11C6.88071 11 8 9.88071 8 8.5H7.5H7C7 9.32843 6.32843 10 5.5 10V10.5ZM7.5 8.5H8C8 7.11929 6.88071 6 5.5 6V6.5V7C6.32843 7 7 7.67157 7 8.5H7.5ZM5.5 6.5V6H1.5V6.5V7H5.5V6.5ZM1.5 6.5H1V10H1.5H2V6.5H1.5ZM2 1.5V1C1.44772 1 1 1.44772 1 2H1.5H2V1.5ZM1.5 2H1V5H1.5H2V2H1.5ZM1.5 5V5.5H4.75V5V4.5H1.5V5ZM4.75 5V5.5C5.99264 5.5 7 4.49264 7 3.25H6.5H6C6 3.94036 5.44036 4.5 4.75 4.5V5ZM6.5 3.25H7C7 2.00736 5.99264 1 4.75 1V1.5V2C5.44036 2 6 2.55964 6 3.25H6.5ZM4.75 1.5V1H2V1.5V2H4.75V1.5Z" fill="black" mask="url(#path-1-inside-1_3940_24436)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -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,57 @@ 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mouseDownEvent(e) {
|
/** 切换到橡皮擦工具 */
|
||||||
this.isDragging = true
|
changeToolToEraser() {
|
||||||
this.startX = e.absolutePointer.x
|
if (!this.demoObject) return;
|
||||||
this.startY = e.absolutePointer.y
|
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()
|
||||||
|
}
|
||||||
|
demoObjectDefault = {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
evented: false,
|
||||||
|
selectable: false,
|
||||||
|
erasable: false,
|
||||||
|
}
|
||||||
|
createDemoObject() {
|
||||||
|
if (this.demoObject) this.clearDemoObject()
|
||||||
|
const { canvasWidth, canvasHeight } = this.canvasManager.getCanvasSize();
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
canvas.width = canvasWidth
|
||||||
|
canvas.height = canvasHeight
|
||||||
|
this.demoObject = new fabric.Image(canvas, this.demoObjectDefault)
|
||||||
|
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 +93,64 @@ 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 createStaticCanvas(object: fabric.Object) {
|
||||||
|
if (!this.demoObject) this.createDemoObject()
|
||||||
|
const canvas = new fabric.StaticCanvas(document.createElement("canvas"), {
|
||||||
|
width: this.demoObject.width,
|
||||||
|
height: this.demoObject.height,
|
||||||
|
enableRetinaScaling: false,
|
||||||
|
});
|
||||||
|
const newObject = await cloneObjects([object]).then(v => v[0])
|
||||||
|
canvas.add(newObject)
|
||||||
|
canvas.renderAll()
|
||||||
|
return canvas
|
||||||
|
}
|
||||||
|
// 处理绘制图像
|
||||||
|
async handleDrawImage(object: fabric.Object) {
|
||||||
|
const tcanvas = await this.createStaticCanvas(this.demoObject)
|
||||||
|
tcanvas.add(object)
|
||||||
|
tcanvas.renderAll();
|
||||||
|
const canvas = getObjectAlphaToCanvas(tcanvas, null, 0, this.rgba);
|
||||||
|
this.replaceDemoObject(canvas)
|
||||||
|
}
|
||||||
|
// 处理图像删除
|
||||||
|
async handleRemoveImage(object: fabric.Object) {
|
||||||
|
const tcanvas = await this.createStaticCanvas(this.demoObject)
|
||||||
|
const rcanvas = await this.createStaticCanvas(object)
|
||||||
|
const tempCanvas = rcanvas.toCanvasElement();
|
||||||
|
const tempCtx = tempCanvas.getContext('2d');
|
||||||
|
const imageData2 = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
||||||
|
const canvas = getObjectAlphaToCanvas(tcanvas, imageData2, 0, this.rgba);
|
||||||
|
this.replaceDemoObject(canvas)
|
||||||
|
}
|
||||||
|
// 替换框选对象
|
||||||
|
async replaceDemoObject(canvas) {
|
||||||
|
const image = new fabric.Image(canvas, this.demoObjectDefault);
|
||||||
|
this.canvasManager.canvas.add(image)
|
||||||
|
this.canvasManager.canvas.remove(this.demoObject);
|
||||||
|
this.demoObject = image;
|
||||||
|
this.canvasManager.canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseDownEvent(e) {
|
||||||
|
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 +165,35 @@ 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)
|
this.clearIndicatorObject()
|
||||||
this.canvasManager.canvas.remove(this.demoObject)
|
|
||||||
this.canvasManager.canvas.renderAll()
|
this.canvasManager.canvas.renderAll()
|
||||||
|
|
||||||
// this.createSelectbox()
|
const rect = new fabric.Rect({
|
||||||
|
left: object.left,
|
||||||
|
top: object.top,
|
||||||
|
width: object.width,
|
||||||
|
height: object.height,
|
||||||
|
fill: '#f00',
|
||||||
|
strokeWidth: 0,
|
||||||
|
})
|
||||||
|
const currentTool = this.toolManager.currentTool.value
|
||||||
|
if (currentTool === OperationType.AISELECT_ADD) {
|
||||||
|
this.handleDrawImage(rect)
|
||||||
|
} else if (currentTool === OperationType.AISELECT_REMOVE) {
|
||||||
|
this.handleRemoveImage(rect)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 +201,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 +213,10 @@ 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"
|
if (!this.demoObject) return
|
||||||
const image = await this.loadImageToObject(url)
|
const fobject = this.demoObject
|
||||||
const canvas = getObjectAlphaToCanvas(image, null, 0, this.rgba);
|
this.clearDemoObject()
|
||||||
const fobject = this.canvasManager.canvas.clipPath
|
const canvas = getObjectAlphaToCanvas(fobject, null, 0, { r: 255, g: 0, b: 0, a: 255 });
|
||||||
// const top = fobject.top - fobject.height * scaleY / 2;
|
|
||||||
// const left = fobject.left - fobject.width * scaleX / 2;
|
|
||||||
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 +239,8 @@ export class AISelectboxToolManager {
|
|||||||
});
|
});
|
||||||
const group = await this.layerManager.createGroupLayer({
|
const group = await this.layerManager.createGroupLayer({
|
||||||
clipPath: path,
|
clipPath: path,
|
||||||
|
top: path.top + path.height / 2,
|
||||||
|
left: path.left + path.width / 2,
|
||||||
}, false, false)
|
}, false, false)
|
||||||
const rect = await this.layerManager.createRectLayer({
|
const rect = await this.layerManager.createRectLayer({
|
||||||
width: path.width,
|
width: path.width,
|
||||||
@@ -145,5 +259,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.handleDrawImage(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)
|
||||||
if (!layer || !object) return
|
const call = (layer, object) => {
|
||||||
layer.visible = visible
|
if (!layer || !object) return
|
||||||
object.set({
|
layer.visible = visible
|
||||||
visible: visible
|
object.set({
|
||||||
})
|
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)
|
||||||
if (!layer || !object) return
|
const call = (layer, object) => {
|
||||||
layer.info.lock = !!lock
|
if (!layer || !object) return
|
||||||
layer.evented = !lock
|
layer.info.lock = !!lock
|
||||||
object.info.lock = !!lock
|
layer.evented = !lock
|
||||||
object.set({
|
object.info.lock = !!lock
|
||||||
evented: !lock,
|
if (object.type !== "group") {
|
||||||
selectable: !lock,
|
object.set({
|
||||||
})
|
evented: !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", // 橡皮擦模式
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
])
|
])
|
||||||
const getApiData = ()=>{
|
const getApiData = ()=>{
|
||||||
return {
|
return {
|
||||||
variantCount: '2',
|
variantCount: '4',
|
||||||
colors: data.colors,
|
colors: data.colors,
|
||||||
mode: data.mode,
|
mode: data.mode,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,19 @@
|
|||||||
// if (!subordNode) {
|
// if (!subordNode) {
|
||||||
|
|
||||||
//如果是添加印花的结果就作为一级节点可以再次选择添加印花或者生成真实图
|
//如果是添加印花的结果就作为一级节点可以再次选择添加印花或者生成真实图
|
||||||
let tier = (NODE_DATATIER.Fast_MODE == currentComponent.value.tier && currentComponent.value.type == NODE_DATATYPE.Fast_MODE)?0:currentComponent.value.tier
|
let typeList = [
|
||||||
|
NODE_DATATYPE.Fast_MODE,
|
||||||
|
NODE_DATATYPE.CANVAS_MODE,
|
||||||
|
NODE_DATATYPE.SCENE_COMPOSITION,
|
||||||
|
NODE_DATATYPE.COLOR_PALETTE,
|
||||||
|
]
|
||||||
|
let tritList = [
|
||||||
|
NODE_DATATIER.Fast_MODE,
|
||||||
|
NODE_DATATIER.CANVAS_MODE,
|
||||||
|
NODE_DATATIER.SCENE_COMPOSITION,
|
||||||
|
NODE_DATATIER.COLOR_PALETTE,
|
||||||
|
]
|
||||||
|
let tier = (tritList.includes(currentComponent.value.tier) && typeList.includes(currentComponent.value.type))?currentComponent.value.tier - 1:currentComponent.value.tier
|
||||||
taskList.forEach((item,index) => {
|
taskList.forEach((item,index) => {
|
||||||
nodeManager.createResultNode({
|
nodeManager.createResultNode({
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -213,6 +213,8 @@
|
|||||||
item.canvasId = options.canvasId || null
|
item.canvasId = options.canvasId || null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stateManager.recordState()
|
||||||
|
stateManager.exportFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onEdit = (item: any) => {
|
const onEdit = (item: any) => {
|
||||||
@@ -236,7 +238,7 @@
|
|||||||
const isSubord = computed(() => props.node.id == stateManager.activeNodeID.value)
|
const isSubord = computed(() => props.node.id == stateManager.activeNodeID.value)
|
||||||
const tier = computed(() => Number(props.node?.data?.tier || 0))
|
const tier = computed(() => Number(props.node?.data?.tier || 0))
|
||||||
//只有3d模型才有三级菜单,目前三级菜单内容少直接禁用按钮
|
//只有3d模型才有三级菜单,目前三级菜单内容少直接禁用按钮
|
||||||
const isAdd3d = computed(() => (tier.value === 2 && props.node?.data?.superiorNodeType === NODE_DATATYPE.TO_3D_MODEL) || props.node?.data?.superiorNodeType !== NODE_DATATYPE.TO_3D_MODEL)
|
// const isAdd3d = computed(() => (tier.value === 2 && props.node?.data?.superiorNodeType === NODE_DATATYPE.TO_3D_MODEL) || (props.node?.data?.superiorNodeType !== NODE_DATATYPE.TO_3D_MODEL && tier.value !== 2))
|
||||||
const isReturned = computed(() => {
|
const isReturned = computed(() => {
|
||||||
return (
|
return (
|
||||||
props.node.data.type == NODE_DATATYPE.RESULT_IMAGE &&
|
props.node.data.type == NODE_DATATYPE.RESULT_IMAGE &&
|
||||||
@@ -248,7 +250,7 @@
|
|||||||
NODE_DATATYPE.RESULT_IMAGE === props.node.data.type &&
|
NODE_DATATYPE.RESULT_IMAGE === props.node.data.type &&
|
||||||
!(tier.value === NODE_DATATIER.TO_3VIEW) &&
|
!(tier.value === NODE_DATATIER.TO_3VIEW) &&
|
||||||
isReturned.value &&
|
isReturned.value &&
|
||||||
isAdd3d.value &&
|
// isAdd3d.value &&
|
||||||
isSubord.value
|
isSubord.value
|
||||||
)
|
)
|
||||||
const onAdd = () => {
|
const onAdd = () => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<div
|
<div
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="input"
|
class="input"
|
||||||
|
:style="data.textStyle"
|
||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
:contenteditable="active"
|
:contenteditable="active"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
@@ -11,6 +12,9 @@
|
|||||||
@paste.prevent
|
@paste.prevent
|
||||||
@keydown.stop
|
@keydown.stop
|
||||||
></div>
|
></div>
|
||||||
|
<div class="tools" @mousedown="onMouseDown">
|
||||||
|
<myTextTools :textStyle="data.textStyle"></myTextTools>
|
||||||
|
</div>
|
||||||
<span class="delete" @mousedown.stop @click="emit('delete-node')" v-show="active">
|
<span class="delete" @mousedown.stop @click="emit('delete-node')" v-show="active">
|
||||||
<svg-icon name="close" size="7" size-unit="px" />
|
<svg-icon name="close" size="7" size-unit="px" />
|
||||||
</span>
|
</span>
|
||||||
@@ -19,6 +23,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, onMounted, nextTick, watch } from 'vue'
|
import { reactive, ref, onMounted, nextTick, watch } from 'vue'
|
||||||
|
import myTextTools from '@/components/Canvas/FlowCanvas/components/tools/my-textTools.vue'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
active: {
|
active: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -31,7 +36,15 @@
|
|||||||
})
|
})
|
||||||
const emit = defineEmits(['update-data', 'delete-node'])
|
const emit = defineEmits(['update-data', 'delete-node'])
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
text: props.data?.text || '点击编辑文本'
|
text: props.data?.text || '点击编辑文本',
|
||||||
|
textStyle:{
|
||||||
|
'--font-size':props.data?.textStyle?.['--font-size'] || '16px',
|
||||||
|
'--font-color':props.data?.textStyle?.['--font-color'] || '#000',
|
||||||
|
'--font-style':props.data?.textStyle?.['--font-style'] || 'normal',//italic
|
||||||
|
'--font-family':props.data?.textStyle?.['--font-family'] || 'Medium',
|
||||||
|
'--font-weight':props.data?.textStyle?.['--font-weight'] || 'initial',//blod
|
||||||
|
'--font-decoration':props.data?.textStyle?.['--font-decoration'] || 'none',//underline
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const time = ref(null)
|
const time = ref(null)
|
||||||
const inputRef = ref<any>()
|
const inputRef = ref<any>()
|
||||||
@@ -70,19 +83,25 @@
|
|||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.text {
|
.text {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 2px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
&.active {
|
&.active {
|
||||||
border-color: #000;
|
|
||||||
> .input {
|
> .input {
|
||||||
|
border-color: #000;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .input {
|
> .input {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
padding: 2px;
|
||||||
outline: none;
|
outline: none;
|
||||||
min-width: 2px;
|
min-width: 2px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
color: var(--font-color);
|
||||||
|
font-style: var(--font-style);
|
||||||
|
font-weight: var(--font-weight);
|
||||||
|
font-size: var(--font-size);
|
||||||
|
text-decoration: var(--font-decoration);
|
||||||
|
font-family: var(--font-family);
|
||||||
}
|
}
|
||||||
> .delete {
|
> .delete {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -94,5 +113,15 @@
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
> .tools{
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%,-100%);
|
||||||
|
top: -10px;
|
||||||
|
height: 41px;
|
||||||
|
border: 2px solid #EBEBEB;
|
||||||
|
border-radius: 11px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
.el-select-dropdown {
|
.el-select-dropdown {
|
||||||
li {
|
li {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<template>
|
||||||
|
<div class="my-textTools">
|
||||||
|
<input class="color" type="color" ref="colorInput" @change="changeColor" />
|
||||||
|
<div class="interval"></div>
|
||||||
|
<div class="fontFamily">
|
||||||
|
<my-select v-model="textStyle['--font-family']" @change="changeFontFamily" :list="fontFamilyList[locale]" />
|
||||||
|
</div>
|
||||||
|
<div class="interval"></div>
|
||||||
|
<div class="size">
|
||||||
|
<div class="label" @click="changeFontSize(-1)">
|
||||||
|
-
|
||||||
|
</div>
|
||||||
|
<div class="value">{{ parseInt(props.textStyle?.['--font-size']) }}</div>
|
||||||
|
<div class="label" @click="changeFontSize(1)">
|
||||||
|
+
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="interval"></div>
|
||||||
|
<div class="fontStyle">
|
||||||
|
<div class="label" @click="changeFontStyle('--font-weight',['bold','normal'])" :class="{'active': props.textStyle['--font-weight'] === 'bold'}">
|
||||||
|
<svg-icon name="textToolsweight" size="12" size-unit="px" color="#000" />
|
||||||
|
</div>
|
||||||
|
<div class="label" @click="changeFontStyle('--font-style',['italic','normal'])" :class="{'active': props.textStyle['--font-style'] === 'italic'}">
|
||||||
|
<svg-icon name="textToolsStyle" size="12" size-unit="px" color="#000" />
|
||||||
|
</div>
|
||||||
|
<div class="label" @click="changeFontStyle('--font-decoration',['underline','none'])" :class="{'active': props.textStyle['--font-decoration'] === 'underline'}">
|
||||||
|
<svg-icon name="textToolsDecoration" size="12" size-unit="px" color="#000" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, markRaw, onMounted } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const emit = defineEmits(['update:textStyle'])
|
||||||
|
const { locale } = useI18n()
|
||||||
|
const fontFamilyList = ref({
|
||||||
|
ENGLISH: [
|
||||||
|
{ value:'Medium',label:'Medium' },
|
||||||
|
{ value:'Arial',label:'Arial' },
|
||||||
|
{ value:'Helvetica',label:'Helvetica' },
|
||||||
|
{ value:'Times New Roman',label:'Times New Roman' },
|
||||||
|
{ value:'Georgia',label:'Georgia' },
|
||||||
|
{ value:'Verdana',label:'Verdana' },
|
||||||
|
{ value:'Courier New',label:'Courier New' },
|
||||||
|
{ value:'Lucida Console',label:'Lucida Console' },
|
||||||
|
{ value:'General Sans',label:'General Sans' },
|
||||||
|
{ value:'Inter',label:'Inter' },
|
||||||
|
],
|
||||||
|
CHINESE_SIMPLIFIED: [
|
||||||
|
{ value:'Medium',label:'Medium' },
|
||||||
|
{ value:'微软雅黑',label:'微软雅黑' },
|
||||||
|
{ value:'宋体',label:'宋体' },
|
||||||
|
{ value:'黑体',label:'黑体' },
|
||||||
|
{ value:'仿宋',label:'仿宋' },
|
||||||
|
{ value:'楷体',label:'楷体' },
|
||||||
|
{ value:'苹方',label:'苹方' },
|
||||||
|
{ value:'华文黑体',label:'华文黑体' },
|
||||||
|
{ value:'华文宋体',label:'华文宋体' },
|
||||||
|
{ value:'华文楷体',label:'华文楷体' },
|
||||||
|
{ value:'思源黑体',label:'思源黑体' },
|
||||||
|
{ value:'MiSans',label:'MiSans' },
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const props = defineProps({
|
||||||
|
textStyle: { type: Object },
|
||||||
|
})
|
||||||
|
const changeFontFamily = (val: string) => {
|
||||||
|
props.textStyle['--font-family'] = val
|
||||||
|
onChange()
|
||||||
|
}
|
||||||
|
const changeColor = (e: Event) => {
|
||||||
|
const target = e.target as HTMLInputElement
|
||||||
|
props.textStyle['--font-color'] = target.value
|
||||||
|
onChange()
|
||||||
|
}
|
||||||
|
const changeFontSize = (val: number) => {
|
||||||
|
if (parseInt(props.textStyle?.['--font-size']) + val <= 9 || parseInt(props.textStyle?.['--font-size']) + val >= 51) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
props.textStyle['--font-size'] = parseInt(props.textStyle?.['--font-size']) + val + 'px'
|
||||||
|
onChange()
|
||||||
|
}
|
||||||
|
const changeFontStyle = (key: string,value: string[]) => {
|
||||||
|
props.textStyle[key] = props.textStyle[key] === value[0] ? value[1] : value[0]
|
||||||
|
onChange()
|
||||||
|
}
|
||||||
|
const onChange = () => {
|
||||||
|
emit('update:textStyle', props.textStyle)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.my-textTools {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
padding: 6px 19px;
|
||||||
|
align-items: center;
|
||||||
|
.interval{
|
||||||
|
margin: 0 16px;
|
||||||
|
height: 25px;
|
||||||
|
width: 1px;
|
||||||
|
background-color: #EBEBEB;
|
||||||
|
}
|
||||||
|
.label{
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
&:hover{
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fontFamily{
|
||||||
|
width: 103px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.color{
|
||||||
|
width: 55px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
.size{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.fontStyle{
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -96,18 +96,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .preview {
|
> .preview {
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
max-height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
> img {
|
> img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
max-height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
> .close {
|
> .close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.1px;
|
top: -10px;
|
||||||
right: 0.1px;
|
right: -10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export class NodeManager {
|
|||||||
//获取上级节点所生成的最后一个node,设置位置为最后一个节点的xy 加上 节点间距
|
//获取上级节点所生成的最后一个node,设置位置为最后一个节点的xy 加上 节点间距
|
||||||
const superiorGenerateNodes = this.stateManager.getSubordNodes(superiorID)
|
const superiorGenerateNodes = this.stateManager.getSubordNodes(superiorID)
|
||||||
const currentNode = superiorGenerateNodes.find((node) => {
|
const currentNode = superiorGenerateNodes.find((node) => {
|
||||||
return node.data.createIndexPosition === options?.data?.createIndexPosition
|
return (node.data.createIndexPosition === options?.data?.createIndexPosition && options?.data?.createIndexPosition)
|
||||||
})
|
})
|
||||||
const endGenerateNode = superiorGenerateNodes.reduce((max, current) => {
|
const endGenerateNode = superiorGenerateNodes.reduce((max, current) => {
|
||||||
return current.data.createIndexPosition > max.data.createIndexPosition ? current : max
|
return current.data.createIndexPosition > max.data.createIndexPosition ? current : max
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ export class StateManager {
|
|||||||
getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
|
getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
|
||||||
/** 获取下级节点 */
|
/** 获取下级节点 */
|
||||||
getSubordNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
|
getSubordNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
|
||||||
getLastNode() { console.log(this.nodes.value); return this.nodes.value[this.nodes.value.length - 1] }
|
getLastNode() { return this.nodes.value[this.nodes.value.length - 1] }
|
||||||
|
|
||||||
/** 获取上级生成节点的图片 */
|
/** 获取上级生成节点的图片 */
|
||||||
getSuperiorNodeImage(superiorID: string) {
|
getSuperiorNodeImage(superiorID: string) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Tree from './tree/index.vue'
|
|||||||
import { findAndAddChild, findAndRemoveChild } from '../../../../../utils/treeDiagram'
|
import { findAndAddChild, findAndRemoveChild } from '../../../../../utils/treeDiagram'
|
||||||
import { useProjectStore } from '@/stores'
|
import { useProjectStore } from '@/stores'
|
||||||
import { versionTree } from '@/api/versitonTree'
|
import { versionTree } from '@/api/versitonTree'
|
||||||
|
import { downloadImage } from '@/components/Canvas/tools/tools'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
versionTreeData: {
|
versionTreeData: {
|
||||||
@@ -138,7 +139,7 @@ const {} = toRefs(data)
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="expandBtnBox" v-if="versionsList.length > 0">
|
<div class="expandBtnBox" v-if="versionsList.length > 0">
|
||||||
<div class="btn" @click="openTree(true)">
|
<div class="btn" v-if="selectItem.url" @click="downloadImage(selectItem.url,'image.png')">
|
||||||
<div class="versionExport">
|
<div class="versionExport">
|
||||||
<SvgIcon name="versionExport" size="17" color="rgba(0, 0, 0, 0.6)" />
|
<SvgIcon name="versionExport" size="17" color="rgba(0, 0, 0, 0.6)" />
|
||||||
</div>
|
</div>
|
||||||
@@ -211,8 +212,10 @@ const {} = toRefs(data)
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-top: 2.2rem;
|
margin-top: 2.2rem;
|
||||||
margin-right: 3rem;
|
margin-right: 3rem;
|
||||||
|
height: 3.3rem;
|
||||||
> .btn{
|
> .btn{
|
||||||
padding: .6rem 1.8rem;
|
padding: 0 1.8rem;
|
||||||
|
line-height: 3rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -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