feat: 新增页面框选效果

This commit is contained in:
奔跑的面条 2022-08-18 20:30:02 +08:00
parent 23bbac7318
commit c987dd8816
9 changed files with 179 additions and 21 deletions

View File

@ -6,7 +6,7 @@ export enum MouseEventButton {
// 页面拖拽键名
export enum DragKeyEnum {
DROG_KEY = 'ChartData'
DRAG_KEY = 'ChartData'
}
// 操作枚举

View File

@ -59,4 +59,10 @@ export const requestInterval = 30
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND
// 工作区域历史记录存储最大数量
export const editHistoryMax = 100
export const editHistoryMax = 100
// 拖拽时蒙层的 z-index需比所有图表高
export const canvasModelIndex = 9999
// 框选时蒙层的 z-index需比所有图表高
export const selectBoxIndex = canvasModelIndex + 10

View File

@ -21,7 +21,8 @@ export enum EditCanvasTypeEnum {
USER_SCALE = 'userScale',
LOCK_SCALE = 'lockScale',
IS_CREATE = 'isCreate',
IS_DRAG = 'isDrag'
IS_DRAG = 'isDrag',
IS_SELECT = 'isSelect'
}
// 编辑区域
@ -41,6 +42,8 @@ export type EditCanvasType = {
[EditCanvasTypeEnum.IS_CREATE]: boolean
// 拖拽中
[EditCanvasTypeEnum.IS_DRAG]: boolean
// 框选中
[EditCanvasTypeEnum.IS_SELECT]: boolean
}
// 滤镜/背景色/宽高主题等

View File

@ -52,7 +52,9 @@ export const useChartEditStore = defineStore({
// 初始化
isCreate: false,
// 拖拽中
isDrag: false
isDrag: false,
// 框选中
isSelect: false
},
// 右键菜单
rightMenuShow: false,
@ -216,10 +218,10 @@ export const useChartEditStore = defineStore({
},
// * 设置鼠标位置
setMousePosition(x?: number, y?: number, startX?: number, startY?: number): void {
if (startX) this.mousePosition.startX = startX
if (startY) this.mousePosition.startY = startY
if (x) this.mousePosition.x = x
if (y) this.mousePosition.y = y
if (startX) this.mousePosition.startX = startX
if (startY) this.mousePosition.startY = startY
},
// * 找到目标 id 数据的下标位置id可为父级或子集数组无则返回-1
fetchTargetIndex(id?: string): number {

View File

@ -45,7 +45,7 @@ const dragStartHandle = (e: DragEvent, item: ConfigType) => {
componentInstall(item.chartKey, fetchChartComponent(item))
componentInstall(item.conKey, fetchConfigComponent(item))
//
e!.dataTransfer!.setData(DragKeyEnum.DROG_KEY, JSON.stringify(omit(item, ['image'])))
e!.dataTransfer!.setData(DragKeyEnum.DRAG_KEY, JSON.stringify(omit(item, ['image'])))
//
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CREATE, true)
}

View File

@ -1,5 +1,5 @@
<template>
<div class="go-edit-range go-transition" :style="rangeStyle" @mousedown="mousedownHandleUnStop($event, undefined)">
<div class="go-edit-range go-transition" :style="rangeStyle" @mousedown="mousedownBoxSelect($event, undefined)">
<slot></slot>
<!-- 水印 -->
<edit-watermark></edit-watermark>
@ -7,19 +7,23 @@
<edit-rule></edit-rule>
<!-- 拖拽时的辅助线 -->
<edit-align-line></edit-align-line>
<!-- 框选时的样式框 -->
<edit-select></edit-select>
<!-- 拖拽时的遮罩 -->
<div class="go-edit-range-model" :style="rangeModelStyle"></div>
<div v-if="showModel" class="go-edit-range-model" :style="rangeModelStyle"></div>
</div>
</template>
<script setup lang="ts">
import { toRefs, computed } from 'vue'
import { useSizeStyle } from '../../hooks/useStyle.hook'
import { mousedownHandleUnStop } from '../../hooks/useDrag.hook'
import { canvasModelIndex } from '@/settings/designSetting'
import { mousedownBoxSelect } from '../../hooks/useDrag.hook'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditAlignLine } from '../EditAlignLine'
import { EditWatermark } from '../EditWatermark'
import { EditRule } from '../EditRule'
import { EditSelect } from '../EditSelect'
const chartEditStore = useChartEditStore()
@ -41,11 +45,15 @@ const rangeStyle = computed(() => {
return { ...useSizeStyle(size.value), ...scale }
})
//
const showModel = computed(() => {
return getEditCanvas.value.isCreate || getEditCanvas.value.isDrag
})
//
const rangeModelStyle = computed(() => {
const dragStyle = getEditCanvas.value.isCreate && { 'z-index': 99999 }
// @ts-ignore
return { ...useSizeStyle(size.value), ...dragStyle }
return { ...useSizeStyle(size.value), 'z-index': canvasModelIndex }
})
</script>

View File

@ -0,0 +1,3 @@
import EditSelect from './index.vue'
export { EditSelect }

View File

@ -0,0 +1,107 @@
<template>
<div class="go-edit-select" v-if="isSelect" :style="positionStyle">
<div class="select-background"></div>
<div class="select-border"></div>
</div>
</template>
<script setup lang="ts">
import { ref, toRefs, watch } from 'vue'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useSizeStyle, useComponentStyle } from '../../hooks/useStyle.hook'
import { selectBoxIndex } from '@/settings/designSetting'
//
const designStore = useDesignStore()
const themeColor = ref(designStore.getAppTheme)
const chartEditStore = useChartEditStore()
const { isSelect, scale } = toRefs(chartEditStore.getEditCanvas)
//
const positionStyle = ref()
watch(
() => chartEditStore.getMousePosition,
positionInfo => {
if (!isSelect.value) return
const { startX, startY, x, y } = positionInfo
const attr = {
zIndex: selectBoxIndex,
// left
x: 0,
// top
y: 0,
//
w: 0,
//
h: 0
}
//
if (x > startX && y > startY) {
//
attr.x = startX
attr.y = startY
attr.w = Math.round((x - startX) / scale.value)
attr.h = Math.round((y - startY) / scale.value)
} else if (x > startX && y < startY) {
//
attr.x = startX
attr.w = Math.round((x - startX) / scale.value)
attr.h = Math.round((startY - y) / scale.value)
attr.y = startY - attr.h
} else if (x < startX && y > startY) {
//
attr.y = startY
attr.w = Math.round((startX - x) / scale.value)
attr.h = Math.round((y - startY) / scale.value)
attr.x = startX - attr.w
} else {
//
attr.w = Math.round((startX - x) / scale.value)
attr.h = Math.round((startY - y) / scale.value)
attr.x = startX - attr.w
attr.y = startY - attr.h
}
positionStyle.value = {
...useComponentStyle(attr, selectBoxIndex),
...useSizeStyle(attr)
}
},
{
deep: true
}
)
</script>
<style lang="scss" scoped>
@include go('edit-select') {
position: absolute;
.select-border,
.select-background {
position: absolute;
width: 100%;
height: 100%;
border-radius: 10px;
overflow: hidden;
}
.select-border {
left: 0;
top: 0;
opacity: 1;
border-width: 2px;
border-style: solid;
border-color: v-bind('themeColor');
}
.select-background {
top: 2px;
left: 2px;
opacity: 0.1;
background-color: v-bind('themeColor');
}
}
</style>

View File

@ -20,7 +20,7 @@ export const dragHandle = async (e: DragEvent) => {
loadingStart()
// 获取拖拽数据
const drayDataString = e!.dataTransfer!.getData(DragKeyEnum.DROG_KEY)
const drayDataString = e!.dataTransfer!.getData(DragKeyEnum.DRAG_KEY)
if (!drayDataString) {
loadingFinish()
return
@ -60,6 +60,38 @@ export const mousedownHandleUnStop = (e: MouseEvent, item?: CreateComponentType
chartEditStore.setTargetSelectChart(undefined)
}
// * 框选
export const mousedownBoxSelect = (e: MouseEvent, item?: CreateComponentType | CreateComponentGroupType) => {
mousedownHandleUnStop(e)
// 记录点击初始位置
const startOffsetX = e.offsetX
const startOffsetY = e.offsetY
const startScreenX = e.screenX
const startScreenY = e.screenY
chartEditStore.setMousePosition(undefined, undefined, startOffsetX, startOffsetY)
// 移动框选
const mousemove = throttle((moveEvent: MouseEvent) => {
const currX = startOffsetX + moveEvent.screenX - startScreenX
const currY = startOffsetY + moveEvent.screenY - startScreenY
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, true)
chartEditStore.setMousePosition(currX, currY)
}, 50)
// 鼠标抬起
const mouseup = () => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, false)
chartEditStore.setMousePosition(0, 0, 0, 0)
document.removeEventListener('mousemove', mousemove)
document.removeEventListener('mouseup', mouseup)
}
document.addEventListener('mousemove', mousemove)
document.addEventListener('mouseup', mouseup)
}
// * 鼠标事件
export const useMouseHandle = () => {
// * Click 事件, 松开鼠标触发
@ -86,7 +118,6 @@ export const useMouseHandle = () => {
e.preventDefault()
e.stopPropagation()
onClickOutSide()
// 按下左键 + CTRL
if (
e.buttons === MouseEventButton.LEFT &&
@ -124,11 +155,10 @@ export const useMouseHandle = () => {
const startY = e.screenY
// 记录初始位置
chartEditStore.setMousePosition(startX, startY)
chartEditStore.setMousePosition(undefined, undefined, startX, startY)
// 移动-计算偏移量
const mousemove = throttle((moveEvent: MouseEvent) => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true)
chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY)
// 当前偏移量,处理 scale 比例问题
@ -136,8 +166,8 @@ export const useMouseHandle = () => {
let offsetY = (moveEvent.screenY - startY) / scale
chartEditStore.getTargetChart.selectId.forEach(id => {
if(!targetMap.has(id)) return
if (!targetMap.has(id)) return
const index = chartEditStore.fetchTargetIndex(id)
// 拿到初始位置数据
const { x, y, w, h } = targetMap.get(id)
@ -166,8 +196,7 @@ export const useMouseHandle = () => {
}, 30)
const mouseup = () => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false)
chartEditStore.setMousePosition(0, 0)
chartEditStore.setMousePosition(0, 0, 0, 0)
document.removeEventListener('mousemove', mousemove)
document.removeEventListener('mouseup', mouseup)
}
@ -237,7 +266,7 @@ export const useMousePointHandle = (e: MouseEvent, point: string, attr: PickCrea
const mouseup = () => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false)
chartEditStore.setMousePosition(0, 0)
chartEditStore.setMousePosition(0, 0, 0, 0)
document.removeEventListener('mousemove', mousemove)
document.removeEventListener('mouseup', mouseup)
}