模拟实现拖拽
实现方案
- 鼠标按下的时候记录按下的DOM。(如果有需要会进行查询父级)
- 鼠标移动时,根据鼠标位置修改DOM的位置。(如果要求原位置不变,可以clone一个新的)
- 鼠标抬起的时候判断父级不同则移入。(如果有需要会进行查询父级,如果是同级的标签可以做排序操作,目前代码中是追加)
实现代码
var drapDOM = null; window.addEventListener('mousedown', function(e){ if(e.target.classList.contains('drap')){ drapDOM = e.target; } }) window.addEventListener('mousemove', function(e){ if(drapDOM){ drapDOM.style.position = 'fixed'; drapDOM.style.pointerEvents = 'none'; drapDOM.style.left = e.clientX + 'px' drapDOM.style.top = e.clientY + 'px' console.log(e) } }) window.addEventListener('mouseup', function(e){ console.log(e.target) if(drapDOM){ drapDOM.style.position = 'initial'; drapDOM.style.pointerEvents = 'initial'; drapDOM.style.left = '0' drapDOM.style.top = '0'; if(drapDOM.parentNode != e.target){ e.target.appendChild(drapDOM) } drapDOM = null } })
注意事项
drapDOM.style.pointerEvents = 'none'
防止副本干扰e.target
- 可以拖拽的DOM
- 可以放置的DOM
drag
API 实现
先说说有什么好处
- 可以自动生成副本样式
- 动作周期的事件,可以方便的区分出(目标对象与源对象)
ondragstart
:源对象开始被拖动ondrag
:源对象被拖动的过程中ondragend
:源对象被拖动结束ondragenter
:目标对象被源对象拖动进入ondragover
:目标对象被源对象悬浮在上面ondragleave
:源对象拖动着离开了目标对象ondrop
:源对象拖动着在目标对象上方松手
- 数据传递:
- 源对象数据保存:
e.data.Transfer.setData(k,v)//k-v必须都是string类型
- 目标对象获取数据:
e.data.Transfer.getData(k,v)
实现方案
- 可拖拽点增加属性(
draggable="true"
)
- 可拖拽点增加监听函数
dragstart
记录当前拖拽点
- 放置点增加监听函数
drop
、dragover
阻止默认事件,防止(打开、不能拖拽)
- 放置点增加监听函数
drop
判断如果拖拽点不在放置点内(if(!$(ev.target).find(dragged).length){
)就追加
实现代码
var dragged; function allowDrop(ev){ // console.log('allowDrop', ev) ev.preventDefault(); } function drag(ev){ // console.log('drag', ev) } function drop(ev){ console.log('drop', ev) ev.preventDefault(); if(!$(ev.target).find(dragged).length){ $(ev.target).append(dragged) } } function dragstart(ev){ dragged = ev.target; } $(function(){ $('ul').off().on('drop', drop).on('dragover', allowDrop) $('li[draggable="true"]').off().on('drag', drag).on('dragstart', dragstart) })
注意事项
- 放置点增加监听函数
drop
、dragover
阻止默认事件,防止(打开、不能拖拽)
draggable="true"
用来标识这是一个可拖拽点。
- M端 和 PC端 表现其实还不一样的。比如M拖动会触发滚动
其他方案&开源框架
- jquery-ui
- sortable.js