You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:07:05