如何自定义SortableJS拖拽时的Ghost元素(替代默认图标克隆)
自定义SortableJS跨列表拖拽的Ghost元素方法
直接给你两个可行的实现思路,都是基于Sortable的事件钩子来实现:
方法一:完全自定义Ghost并跟随鼠标
核心是利用onStart/onEnd事件,自己创建自定义元素替代默认Ghost,步骤清晰直接:
- 提前准备好自定义Ghost元素(初始隐藏),写好你要的样式和内容
- 初始化Sortable时,给默认Ghost加个类,用来隐藏它
- 拖拽开始时,显示自定义Ghost,绑定鼠标移动事件让它跟着鼠标走
- 拖拽结束后,隐藏自定义Ghost并清理事件监听
代码示例
HTML
<ul class="list" id="list1"> <li>列表1项1</li> <li>列表1项2</li> </ul> <ul class="list" id="list2"> <li>列表2项A</li> <li>列表2项B</li> </ul> <!-- 自定义Ghost,初始隐藏 --> <div id="customGhost" style="display:none;position:absolute;pointer-events:none;padding:10px;background:#e6f7ff;border:1px solid #91d5ff;border-radius:4px;"> 🚀 正在拖拽自定义元素 </div>
CSS
/* 隐藏默认的Ghost元素 */ .sortable-ghost { display: none !important; }
JS
// 封装初始化Sortable的函数,复用逻辑 const initSortable = (elId) => { return new Sortable(document.getElementById(elId), { group: 'cross-list', ghostClass: 'sortable-ghost', onStart(evt) { const customGhost = document.getElementById('customGhost'); // 显示自定义Ghost,根据鼠标位置设置初始偏移(让元素对齐鼠标中心) customGhost.style.display = 'block'; const offsetX = customGhost.offsetWidth / 2; const offsetY = customGhost.offsetHeight / 2; customGhost.style.left = `${evt.originalEvent.clientX - offsetX}px`; customGhost.style.top = `${evt.originalEvent.clientY - offsetY}px`; // 绑定鼠标移动事件,实时更新Ghost位置 const moveHandler = (e) => { customGhost.style.left = `${e.clientX - offsetX}px`; customGhost.style.top = `${e.clientY - offsetY}px`; }; document.addEventListener('mousemove', moveHandler); // 存下事件处理函数,方便结束时解绑 evt.moveHandler = moveHandler; }, onEnd(evt) { const customGhost = document.getElementById('customGhost'); // 隐藏自定义Ghost,解绑事件 customGhost.style.display = 'none'; document.removeEventListener('mousemove', evt.moveHandler); } }); }; // 初始化两个列表 initSortable('list1'); initSortable('list2');
方法二:动态修改默认Ghost的内容
如果不想自己做鼠标跟随逻辑,也可以直接修改默认Ghost的内容,步骤更简单:
代码示例
new Sortable(document.getElementById('list1'), { group: 'cross-list', ghostClass: 'sortable-ghost', onStart(evt) { // 获取默认的Ghost元素(Sortable拖拽时会自动创建原元素的克隆作为Ghost) const ghost = document.querySelector('.sortable-ghost'); // 替换成自定义内容 ghost.innerHTML = '<div style="color:#1890ff;font-weight:bold;">🔧 自定义拖拽提示</div>'; // 额外覆盖样式 ghost.style.background = '#f0f5ff'; ghost.style.border = '1px dashed #1890ff'; ghost.style.padding = '8px'; } }); // 第二个列表同理初始化 new Sortable(document.getElementById('list2'), { group: 'cross-list', ghostClass: 'sortable-ghost' });
这个方法的缺点是Ghost本质还是原元素的克隆,样式可能受原元素影响,需要额外覆盖。
注意事项
- 自定义Ghost要加
pointer-events:none,避免干扰拖拽的鼠标事件 - 方法一的偏移量要根据自定义元素的尺寸调整,让它对齐鼠标位置
- 如果需要根据拖拽的原元素动态变化自定义内容,可以通过
evt.item获取原元素的信息,再修改Ghost的内容
内容的提问来源于stack exchange,提问作者Riccoh
相关产品推荐
相关产品推荐

