feat:drag and drop element

pr675
Hufe921 3 years ago
parent 9f64a068b1
commit 9b9a0a09ae

@ -122,8 +122,7 @@ export class CheckboxControl implements IControlInstance {
}
public cut(): number {
const { endIndex } = this.control.getRange()
return endIndex
return -1
}
}

@ -1,50 +1,150 @@
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../../dataset/constant/Element'
import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
import { ElementType } from '../../../dataset/enum/Element'
import { IElement } from '../../../interface/Element'
import { deepClone, getUUID } from '../../../utils'
import { formatElementList } from '../../../utils/element'
import { CanvasEvent } from '../CanvasEvent'
type IDragElement = IElement & { dragId: string }
function createDragId(element: IElement): string {
const dragId = getUUID()
Reflect.set(element, 'dragId', dragId)
return dragId
}
function getElementIndexByDragId(dragId: string, elementList: IElement[]) {
return (<IDragElement[]>elementList).findIndex((el) => el.dragId === dragId)
}
export function mouseup(evt: MouseEvent, host: CanvasEvent) {
// 判断是否允许拖放
if (host.isAllowDrop) {
const draw = host.getDraw()
const position = draw.getPosition()
const positionList = position.getPositionList()
const rangeManager = draw.getRange()
const cacheRange = host.cacheRange!
const cacheElementList = host.cacheElementList!
const cachePositionList = host.cachePositionList!
// 如果同一上下文拖拽位置向后移动,则重置光标位置
const range = rangeManager.getRange()
const elementList = draw.getElementList()
const positionList = position.getPositionList()
const startPosition = positionList[range.startIndex]
const cacheStartElement = cacheElementList[cacheRange.startIndex]
const startElement = elementList[range.startIndex]
let curIndex = range.startIndex
if (cacheStartElement.tdId === startElement.tdId && range.startIndex > cacheRange.endIndex) {
curIndex -= (cacheRange.endIndex - cacheRange.startIndex)
// 是否是不可拖拽的控件结构元素
const dragElementList = cacheElementList.slice(cacheRange.startIndex + 1, cacheRange.endIndex + 1)
const isContainControl = dragElementList.find(element =>
element.type === ElementType.CONTROL ||
element.type === ElementType.DATE
)
if (isContainControl) {
// 仅允许 (最前/后元素不是控件 || 在控件前后 || 文本控件且是值) 拖拽
const cacheStartElement = cacheElementList[cacheRange.startIndex + 1]
const cacheEndElement = cacheElementList[cacheRange.endIndex]
const isAllowDragControl =
(
(
cacheStartElement.type !== ElementType.CONTROL ||
cacheStartElement.controlComponent === ControlComponent.PREFIX
) &&
(
cacheEndElement.type !== ElementType.CONTROL ||
cacheEndElement.controlComponent === ControlComponent.POSTFIX
) &&
cacheStartElement.type !== ElementType.DATE &&
cacheEndElement.type !== ElementType.DATE
) ||
(
cacheStartElement.controlId === cacheEndElement.controlId &&
cacheStartElement.controlComponent === ControlComponent.PREFIX &&
cacheEndElement.controlComponent === ControlComponent.POSTFIX
) ||
(
cacheStartElement.control?.type === ControlType.TEXT &&
cacheStartElement.controlComponent === ControlComponent.VALUE &&
cacheEndElement.control?.type === ControlType.TEXT &&
cacheEndElement.controlComponent === ControlComponent.VALUE
)
if (!isAllowDragControl) {
draw.render({
curIndex: range.startIndex,
isCompute: false,
isSubmitHistory: false
})
return
}
}
// 删除原有拖拽元素
const deleteElementList = cacheElementList.splice(cacheRange.startIndex + 1, cacheRange.endIndex - cacheRange.startIndex)
// 格式化元素
const editorOptions = draw.getOptions()
const elementList = draw.getElementList()
const anchorElement = elementList[range.startIndex]
let restArg = {}
if (startElement.tableId) {
const { tdId, trId, tableId } = startElement
if (anchorElement.tableId) {
const { tdId, trId, tableId } = anchorElement
restArg = { tdId, trId, tableId }
}
const replaceElementList = deleteElementList.map(el => {
const newElement: IElement = {
value: el.value,
...restArg
}
EDITOR_ELEMENT_STYLE_ATTR.forEach(attr => {
const value = el[attr] as never
if (value !== undefined) {
newElement[attr] = value
const replaceElementList = dragElementList.map(el => {
if (!el.type || el.type === ElementType.TEXT || el.control?.type === ControlType.TEXT) {
const newElement: IElement = {
value: el.value,
...restArg
}
})
return newElement
EDITOR_ELEMENT_STYLE_ATTR.forEach(attr => {
const value = el[attr] as never
if (value !== undefined) {
newElement[attr] = value
}
})
return newElement
} else {
const newElement = deepClone(el)
formatElementList([newElement], {
isHandleFirstElement: false,
editorOptions,
})
return newElement
}
})
elementList.splice(curIndex + 1, 0, ...replaceElementList)
// 缓存拖拽选区开始结束id
const cacheRangeStartId = createDragId(cacheElementList[cacheRange.startIndex])
const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex])
// 设置拖拽值
const replaceLength = replaceElementList.length
let rangeStart = range.startIndex
let rangeEnd = rangeStart + replaceLength
const control = draw.getControl()
const activeControl = control.getActiveControl()
if (activeControl && cacheElementList[rangeStart].controlComponent !== ControlComponent.POSTFIX) {
rangeEnd = activeControl.setValue(replaceElementList)
rangeStart = rangeEnd - replaceLength
} else {
elementList.splice(rangeStart + 1, 0, ...replaceElementList)
}
if (!~rangeEnd) {
draw.render({
isSetCursor: false
})
return
}
// 缓存当前开始结束id
const rangeStartId = createDragId(elementList[rangeStart])
const rangeEndId = createDragId(elementList[rangeEnd])
// 删除原有拖拽元素
const cacheRangeStartIndex = getElementIndexByDragId(cacheRangeStartId, cacheElementList)
const cacheRangeEndIndex = getElementIndexByDragId(cacheRangeEndId, cacheElementList)
const cacheEndElement = cacheElementList[cacheRangeEndIndex]
if (cacheEndElement.type === ElementType.CONTROL && cacheEndElement.controlComponent !== ControlComponent.POSTFIX) {
rangeManager.replaceRange({
...cacheRange,
startIndex: cacheRangeStartIndex,
endIndex: cacheRangeEndIndex
})
control.getActiveControl()?.cut()
} else {
cacheElementList.splice(cacheRangeStartIndex + 1, cacheRangeEndIndex - cacheRangeStartIndex)
}
// 重设上下文
const startElement = elementList[range.startIndex]
const cacheStartElement = cacheElementList[cacheRange.startIndex]
const startPosition = positionList[range.startIndex]
const cacheStartPosition = cachePositionList[cacheRange.startIndex]
const positionContext = position.getPositionContext()
let positionContextIndex = positionContext.index
@ -52,12 +152,12 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
if (startElement.tableId && !cacheStartElement.tableId) {
// 表格外移动到表格内&&表格之前
if (cacheStartPosition.index < positionContextIndex) {
positionContextIndex -= deleteElementList.length
positionContextIndex -= replaceLength
}
} else if (!startElement.tableId && cacheStartElement.tableId) {
// 表格内移到表格外&&表格之前
if (startPosition.index < positionContextIndex) {
positionContextIndex += deleteElementList.length
positionContextIndex += replaceLength
}
}
position.setPositionContext({
@ -65,25 +165,24 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
index: positionContextIndex
})
}
// 设置选区
// 重设选区
const rangeStartIndex = getElementIndexByDragId(rangeStartId, elementList)
const rangeEndIndex = getElementIndexByDragId(rangeEndId, elementList)
rangeManager.setRange(
curIndex,
curIndex + deleteElementList.length,
rangeStartIndex,
rangeEndIndex,
range.tableId,
range.startTdIndex,
range.endTdIndex,
range.startTrIndex,
range.endTrIndex
)
// 重新渲染&重设状态
// 重新渲染
draw.render({
isSetCursor: false
})
host.isAllowDrag = false
host.isAllowDrop = false
} else if (host.isAllowDrag) {
// 如果是允许拖拽不允许拖放则光标重置
host.mousedown(evt)
host.isAllowDrag = false
}
}

@ -103,6 +103,18 @@ export class RangeManager {
control.destroyControl()
}
public replaceRange(range: IRange) {
this.setRange(
range.startIndex,
range.endIndex,
range.tableId,
range.startTdIndex,
range.endTdIndex,
range.startTrIndex,
range.endTrIndex
)
}
public setRangeStyle() {
if (!this.listener.rangeStyleChange) return
let curElementList = this.getSelection()

Loading…
Cancel
Save