2022-03-04 20:57:36 +08:00

322 lines
9.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="go-edit-align-line">
<div
class="line"
v-for="item in line.lineArr"
:key="item"
:class="[
item.includes('row') ? 'row' : 'col',
line['select'].has(item) && 'visible'
]"
:style="useComponentStyle(line['select'].get(item))"
/>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { CreateComponentType } from '@/packages/index.d'
import throttle from 'lodash/throttle'
import cloneDeep from 'lodash/cloneDeep'
// 全局颜色
const designStore = useDesignStore()
const themeColor = ref(designStore.getAppTheme)
const chartEditStore = useChartEditStore()
// 线条集合
const line = reactive({
// 吸附距离px
minDistance: 10,
// 行横向row上中下列竖线col左中右
lineArr: ['rowt', 'rowc', 'rowb', 'coll', 'colc', 'colr'],
// 展示线
select: new Map(),
// 已经吸附
sorptioned: {
x: false,
y: false
}
})
// 位置计算
const useComponentStyle = (attr?: Partial<{ x: number; y: number }>) => {
if (!attr) return {}
const componentStyle = {
left: `${attr.x ? attr.x : 0}px`,
top: `${attr.y ? attr.y : 0}px`
}
return componentStyle
}
// 是否开始计算
const isComputedLine = computed(() => {
const isDrag = chartEditStore.getEditCanvas[EditCanvasTypeEnum.IS_DRAG]
return isDrag
})
// 吸附判定
const isSorption = (selectValue: number, componentValue: number) => {
const isSorption = Math.abs(selectValue - componentValue) <= line.minDistance
return isSorption
}
// 当前目标
const selectId = computed(() => chartEditStore.getTargetChart.selectId)
const selectTatget = computed(
() => chartEditStore.getComponentList[chartEditStore.fetchTargetIndex()]
)
const selectAttr = computed(() => selectTatget.value.attr)
// 画布坐标
const canvasPositionList = computed(() => {
return {
id: '0',
attr: {
w: cloneDeep(chartEditStore.getEditCanvasConfig.width),
h: cloneDeep(chartEditStore.getEditCanvasConfig.height),
x: 0,
y: 0,
zIndex: 0
}
}
})
// 监听鼠标移动
watch(
() => chartEditStore.getMousePosition,
throttle(e => {
if (!isComputedLine.value) return
// 获取目标组件数据
const selectW = selectAttr.value.w
const selectH = selectAttr.value.h
// 距离左侧
const selectLeftX = selectAttr.value.x
const selectHalfX = selectLeftX + selectW / 2
const selectRightX = selectLeftX + selectW
const seletX = [selectLeftX, selectHalfX, selectRightX]
// 距离顶部
const selectTopY = selectAttr.value.y
const selectHalfY = selectTopY + selectH / 2
const selectBottomY = selectTopY + selectH
const seletY = [selectTopY, selectHalfY, selectBottomY]
line.select.clear()
line.sorptioned.y = false
// 循环查询所有组件数据
const componentList = chartEditStore.getComponentList.map((e:CreateComponentType) => {
return {
id: e.id,
attr: e.attr
}
})
componentList.push(canvasPositionList.value)
// 传入画布数据
line.lineArr.forEach(lineItem => {
componentList.forEach((component: typeof canvasPositionList.value) => {
// 排除自身
if (selectId.value === component.id) return
const componentW = component.attr.w
const componentH = component.attr.h
// 距离左侧
const componentLeftX = component.attr.x
const componentHalfX = componentLeftX + componentW / 2
const componentRightX = componentLeftX + componentW
const componentX = [componentLeftX, componentHalfX, componentRightX]
// 距离顶部
const componentTopY = component.attr.y
const componentHalfY = componentTopY + componentH / 2
const componentBottomY = componentTopY + componentH
const componentY = [componentTopY, componentHalfY, componentBottomY]
// 横线对比的是 Y
if (lineItem.includes('rowt')) {
// 顶部
if (isSorption(selectTopY, componentTopY)) {
line.select.set(lineItem, { y: componentTopY })
selectTatget.value.setPosition(selectLeftX, componentTopY)
}
if (isSorption(selectTopY, componentHalfY)) {
line.select.set(lineItem, { y: componentHalfY })
selectTatget.value.setPosition(selectLeftX, componentHalfY)
}
if (isSorption(selectTopY, componentBottomY)) {
line.select.set(lineItem, { y: componentBottomY })
selectTatget.value.setPosition(selectLeftX, componentBottomY)
}
}
if (lineItem.includes('rowc')) {
// 顶部
if (isSorption(selectHalfY, componentTopY)) {
line.select.set(lineItem, { y: componentTopY })
selectTatget.value.setPosition(
selectLeftX,
componentTopY - selectH / 2
)
}
if (isSorption(selectHalfY, componentHalfY)) {
line.select.set(lineItem, { y: componentHalfY })
selectTatget.value.setPosition(
selectLeftX,
componentHalfY - selectH / 2
)
}
if (isSorption(selectHalfY, componentBottomY)) {
line.select.set(lineItem, { y: componentBottomY })
selectTatget.value.setPosition(
selectLeftX,
componentBottomY - selectH / 2
)
}
}
if (lineItem.includes('rowb')) {
// 顶部
if (isSorption(selectBottomY, componentTopY)) {
line.select.set(lineItem, { y: componentTopY })
selectTatget.value.setPosition(selectLeftX, componentTopY - selectH)
}
if (isSorption(selectBottomY, componentHalfY)) {
line.select.set(lineItem, { y: componentHalfY })
selectTatget.value.setPosition(
selectLeftX,
componentHalfY - selectH
)
}
if (isSorption(selectBottomY, componentBottomY)) {
line.select.set(lineItem, { y: componentBottomY })
selectTatget.value.setPosition(
selectLeftX,
componentBottomY - selectH
)
}
}
// 纵线对比的是 X
if (lineItem.includes('coll')) {
if (isSorption(selectLeftX, componentLeftX)) {
line.select.set(lineItem, { x: componentLeftX })
selectTatget.value.setPosition(componentLeftX, selectTopY)
}
if (isSorption(selectLeftX, componentHalfX)) {
line.select.set(lineItem, { x: componentHalfX })
selectTatget.value.setPosition(componentHalfX, selectTopY)
}
if (isSorption(selectLeftX, componentRightX)) {
line.select.set(lineItem, { x: componentRightX })
selectTatget.value.setPosition(componentRightX, selectTopY)
}
}
if (lineItem.includes('colc')) {
if (isSorption(selectHalfX, componentLeftX)) {
line.select.set(lineItem, { x: componentLeftX })
selectTatget.value.setPosition(
componentLeftX - selectW / 2,
selectTopY
)
}
if (isSorption(selectHalfX, componentHalfX)) {
line.select.set(lineItem, { x: componentHalfX })
selectTatget.value.setPosition(
componentHalfX - selectW / 2,
selectTopY
)
}
if (isSorption(selectHalfX, componentRightX)) {
line.select.set(lineItem, { x: componentRightX })
selectTatget.value.setPosition(
componentRightX - selectW / 2,
selectTopY
)
}
}
if (lineItem.includes('colr')) {
if (isSorption(selectRightX, componentLeftX)) {
line.select.set(lineItem, { x: componentLeftX })
selectTatget.value.setPosition(componentLeftX - selectW, selectTopY)
}
if (isSorption(selectRightX, componentHalfX)) {
line.select.set(lineItem, { x: componentHalfX })
selectTatget.value.setPosition(componentHalfX - selectW, selectTopY)
}
if (isSorption(selectRightX, componentRightX)) {
line.select.set(lineItem, { x: componentRightX })
selectTatget.value.setPosition( componentRightX - selectW, selectTopY )
}
}
/*
* 我也不知道为什么这个不行,还没时间调
if(lineItem.includes('row')) {
seletY.forEach(sY => {
componentY.forEach(cY => {
if (isSorption(sY, cY)) {
line.select.set(lineItem, { y: cY })
}
})
})
return
}
if(lineItem.includes('col')) {
seletX.forEach(sX => {
componentX.forEach(cX => {
if (isSorption(sX, cX)) {
line.select.set(lineItem, { x: sX })
}
})
})
return
}
*/
})
})
}, 200),
{
deep: true
}
)
// 取消对齐线
watch(
() => isComputedLine.value,
(val: boolean) => {
if (!val) {
line.select.clear()
line.sorptioned.y = false
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true)
}
}
)
</script>
<style lang="scss" scoped>
@include go(edit-align-line) {
.line {
z-index: 1;
position: absolute;
top: 0;
left: 0;
display: none;
border-width: 1px;
border-style: solid;
border-color: v-bind('themeColor');
opacity: 0.7;
&.visible {
display: block;
}
}
.row {
width: 100%;
}
.col {
height: 100%;
}
}
</style>