Fullcalendar拖拽滚动时如何让鼠标光标居中于事件?
解决FullCalendar拖拽滚动时鼠标居中于事件元素的问题
我之前也碰到过一模一样的问题,Google日历的实现核心就是在拖拽+滚动的过程中,动态调整被拖拽事件的位置,让鼠标始终牢牢卡在事件的中心,不会因为页面滚动导致鼠标移出事件范围。下面是亲测有效的具体方案:
核心思路
- 拖拽启动时,先记录鼠标相对于事件元素中心的偏移量(也就是鼠标在事件里的位置到中心的距离)
- 同时监听日历容器的滚动事件,以及FullCalendar自带的
eventDrag回调,在滚动或拖拽过程中实时计算,把事件位置调整成“鼠标位置减去偏移量”,确保中心对齐 - 覆盖FullCalendar默认的拖拽定位逻辑,用自定义的坐标计算来保证同步
具体代码实现
直接在你的FullCalendar初始化代码里加入以下逻辑:
document.addEventListener('DOMContentLoaded', function() { const calendarEl = document.getElementById('calendar'); let mouseOffsetX = 0; let mouseOffsetY = 0; let isDragging = false; const calendar = new FullCalendar.Calendar(calendarEl, { initialView: 'timeGridDay', // 匹配你的日视图场景 editable: true, events: [ // 这里放你的事件数据 ], // 拖拽开始时记录鼠标与事件中心的偏移 eventDragStart: function(info) { isDragging = true; const eventRect = info.el.getBoundingClientRect(); // 计算鼠标到事件中心的横向/纵向偏移 mouseOffsetX = info.jsEvent.clientX - (eventRect.left + eventRect.width / 2); mouseOffsetY = info.jsEvent.clientY - (eventRect.top + eventRect.height / 2); }, // 拖拽过程中实时调整事件位置 eventDrag: function(info) { if (!isDragging) return; const eventEl = info.el; // 计算事件应该在的位置:鼠标位置减去偏移,让中心对齐鼠标 const targetX = info.jsEvent.clientX - mouseOffsetX; const targetY = info.jsEvent.clientY - mouseOffsetY; // 结合日历容器的滚动偏移,修正事件的定位 const calendarRect = calendarEl.getBoundingClientRect(); const scrollLeft = calendarEl.scrollLeft; const scrollTop = calendarEl.scrollTop; eventEl.style.left = `${targetX - calendarRect.left + scrollLeft}px`; eventEl.style.top = `${targetY - calendarRect.top + scrollTop}px`; // 禁用FullCalendar默认的transform定位,用我们自己的坐标逻辑 info.draggedEl.style.transform = 'none'; }, // 拖拽结束后重置样式和状态 eventDragStop: function(info) { isDragging = false; // 清除自定义样式,恢复日历默认渲染 info.el.style.left = ''; info.el.style.top = ''; info.draggedEl.style.transform = ''; } }); // 监听日历容器的滚动事件,滚动时同步调整事件位置 calendarEl.addEventListener('scroll', function() { if (!isDragging) return; const draggingEvent = document.querySelector('.fc-event.fc-dragging'); if (!draggingEvent) return; const targetX = window.event.clientX - mouseOffsetX; const targetY = window.event.clientY - mouseOffsetY; const calendarRect = calendarEl.getBoundingClientRect(); const scrollLeft = calendarEl.scrollLeft; const scrollTop = calendarEl.scrollTop; draggingEvent.style.left = `${targetX - calendarRect.left + scrollLeft}px`; draggingEvent.style.top = `${targetY - calendarRect.top + scrollTop}px`; }); calendar.render(); });
关键细节说明
- 初始偏移计算:这一步是核心,只有记住鼠标在事件里的相对位置,后续滚动时才能精准对齐中心
- 滚动偏移修正:日历容器滚动后,事件的绝对坐标会变化,必须结合
scrollLeft和scrollTop重新计算位置 - 禁用默认transform:FullCalendar默认用transform来移动拖拽事件,会和我们的自定义定位冲突,所以要关掉它
- 状态重置:拖拽结束后一定要清除自定义样式,不然会影响后续的事件渲染和拖拽
这个方案基本能完美复刻Google日历的拖拽体验,滚动时鼠标再也不会移出事件框,你可以根据自己的日历视图(比如周视图)微调坐标计算逻辑,适配不同场景。
内容的提问来源于stack exchange,提问作者Gal Koren
相关产品推荐
相关产品推荐

