draggable拖拽排序和pointerEvent应用
draggable常用于PC页面的拖拽排序功能,由于原理基于HTML5中drag/drop/dragstart 等相关的事件,但是兼容性在h5/mobile中较差,且不支持!pointerEvent常用于需要多端兼容的拖动/拖拽项目需求,原理基于鼠标/触摸=>指针/点的监听事件,兼容性较好


Last updated
<draggable
:list="element.taskList"
@end="taskSort($event, element.taskList)"
class="scrum-stage-tasks"
:forceFallback="false"
ghostClass="task-ghost"
item-key="id"
dragClass="task-drag"
fallbackClass="task-drag"
:draggable="'.task-card'"
:disabled="!checked">
<template #item="{ element }">
<div class="task task-card ui-sortable-handle fadeIn" :id="element.id" :key="element.id">
<div class="task-content-set open-detail task-title-box" @click="showModal(element, index)">
<div class="task-content-wrapper">
<div class="task-content" :style="{ overflowWrap: 'anywhere' }">
{{ element.taskName }}
</div>
</div>
</div>
</div>
</template>
</draggable>
const vDirectives = {
mounted: (el) => {
el.onmousedown = function (ev) {
const exclude = ['thin-scroll']
const isExclude = exclude.some((item) => ev.target.classList.contains(item))
if (!isExclude) {
return
}
ev.stopPropagation()
ev.preventDefault()
document.body.style.cursor = 'move'
const disX = ev.clientX
const disY = ev.clientY
const originalScrollLeft = el.scrollLeft
const originalScrollTop = el.scrollTop
const originalScrollBehavior = el.style['scroll-behavior']
const originalPointerEvents = el.style['pointer-events']
el.style['scroll-behavior'] = 'auto'
let elEvent = ev
// 鼠标移动事件是监听的整个document,这样可以使鼠标能够在元素外部移动的时候也能实现拖动
document.onmousemove = function (ev) {
ev.stopPropagation()
ev.preventDefault()
document.body.style.cursor = 'move'
const distanceX = ev.clientX - disX
const distanceY = ev.clientY - disY
el.scrollTo(originalScrollLeft - distanceX, originalScrollTop - distanceY)
// 由于我们的图片本身有点击效果,所以需要在鼠标拖动的时候将点击事件屏蔽掉
el.style['pointer-events'] = 'none'
}
document.onmouseup = function (ev) {
ev.stopPropagation()
// elEvent.target.style.cursor = "auto";
// ev.target.style.cursor = "auto";
document.body.style.cursor = 'auto'
document.onmousemove = null
document.onmouseup = null
el.style['scroll-behavior'] = originalScrollBehavior
el.style['pointer-events'] = originalPointerEvents
}
}
}
}// pointer事件的应用
const box = document.querySelector('.flex-box')
const startVal = ref(null)
const endVal = ref(null)
const banList = [
['中央刀库列表', '机内刀库列表'],
['中央刀库机械手', '天轨机械手'],
['中央刀库机械手', '机内刀库列表'],
['天轨机械手', '中央刀库机械手'],
['天轨机械手', '中央刀库放刀位'],
['天轨随行台', '中央刀库放刀位'],
['中央刀库放刀位', '机内刀库列表'],
['中央刀库放刀位', '天轨随行台'],
['中央刀库放刀位', '天轨机械手'],
['机内刀库列表', '中央刀库放刀位'],
['机内刀库列表', '中央刀库列表'],
['机内刀库列表', '中央刀库机械手']
]
box.onpointerup = (e) => {
circleState(e, false)
stopScroll(false)
const doms = document.elementsFromPoint(e.clientX, e.clientY)
doms.map((item, i) => {
if (item.dataset.type && startVal.value && startVal.value.type !== item.dataset.type) {
endVal.value = {
tip: '目标',
type: item.dataset.type,
toolsWhposCode: item.dataset.toolswhposcode,
allState: item.dataset.allstate,
toolsState: item.dataset.toolsstate
}
if (banList.some((item) => item.toString() === [startVal.value.type, endVal.value.type].toString())) {
return message.warning('无法进行此操作')
}
Modal.confirm({
icon: '',
centered: true,
maskClosable: true,
content: () =>
h(
'div',
`【${startVal.value?.tip}】${startVal.value?.type}(${startVal.value?.toolsWhposCode}) -->> 【${endVal.value?.tip}】${endVal.value?.type}(${endVal.value?.toolsWhposCode})`
),
onOk() {
return new Promise((resolve) => {
let data = data = {
sourcePos: { toolsWhposCode: startVal.value.toolsWhposCode }, // 源储位
targetPos: { toolsWhposCode: endVal.value.toolsWhposCode, eqptCode: workEqptCode.value }, // 目标储位
poolActionType: ''
}
toolsdisplayApi
.fmsPosMoveDrag(data)
.then(() => {
startVal.value = null
endVal.value = null
getToolTaskPool()
getOutToolTaskList()
resolve()
})
.finally(() => {})
startVal.value = null
endVal.value = null
resolve()
})
}
})
}
})
}
box.onpointermove = (e) => {
circleState(e, true)
const doms = document.elementsFromPoint(e.clientX, e.clientY)
doms.map((item, i) => {
if (item.dataset.type) {
item.classList.add('drag-hover')
}
})
}
box.onpointerdown = (e) => {
const doms = document.elementsFromPoint(e.clientX, e.clientY)
doms.map((item) => {
if (item.dataset.type) {
stopScroll(true)
circleState(e, true)
message.success('请拖动至目标位置')
startVal.value = {
tip: '源',
type: item.dataset.type,
toolsWhposCode: item.dataset.toolswhposcode,
allState: item.dataset.allstate,
toolsState: item.dataset.toolsstate
}
}
})
}const doms = document.elementsFromPoint(e.clientX, e.clientY)<div
class="clawBall"
data-type="中央刀库机械手"
:data-toolsWhposCode="item?.toolsWhposCode"
:data-allState="item?.allState"
:data-toolsState="item?.toolsState"
:class="item?.allState == 0 ? '' : 'status-' + item?.allState"
></div>