如何使不同时长的外部Draggable事件与timeGridWeek内显示尺寸一致?
实现外部拖拽元素尺寸与FullCalendar timeGridWeek事件时长匹配
我之前也碰到过类似的需求,要让外部拖拽的事件在视觉上就和日历里对应时长的事件大小一致,核心思路就是把拖拽元素的尺寸和日历的时间格规则绑定起来,同时在拖拽过程中把预设的时长传递给日历事件。下面是具体的实现步骤和代码:
1. 给外部拖拽元素标记时长数据
首先在HTML里给每个可拖拽的事件元素加上data-duration属性,用来存储它对应的时长(单位:小时),方便后面JS直接读取:
<div id="external-events" class="external-events"> <div class="fc-event" data-duration="1">1小时会议</div> <div class="fc-event" data-duration="2">2小时培训</div> <div class="fc-event" data-duration="4">半天工作坊</div> </div>
2. 动态匹配拖拽元素的高度
FullCalendar的timeGrid视图有个内部参数minuteHeight,表示每分钟对应的像素高度。我们可以利用这个参数,在视图加载完成后,动态计算每个拖拽元素的高度,让它和日历里对应时长的事件高度完全一致:
document.addEventListener('DOMContentLoaded', function() { const calendarEl = document.getElementById('calendar'); const externalEventsEl = document.getElementById('external-events'); const calendar = new FullCalendar.Calendar(calendarEl, { initialView: 'timeGridWeek', editable: true, droppable: true, // 视图加载完成后计算拖拽元素高度 viewDidMount: function(info) { const minuteHeight = info.view.timeGrid.minuteHeight; const eventItems = externalEventsEl.querySelectorAll('.fc-event'); eventItems.forEach(item => { const durationHours = parseInt(item.dataset.duration); // 计算核心高度:时长(小时)*60分钟 * 每分钟高度 const contentHeight = durationHours * 60 * minuteHeight; // 加上元素的上下内边距(比如我这里设的是5px上下,所以加10px) item.style.height = `${contentHeight + 10}px`; }); }, // 处理拖拽到日历的事件 eventReceive: function(info) { // 从拖拽元素读取时长,设置事件的结束时间 const durationHours = parseInt(info.draggedEl.dataset.duration); const startTime = info.event.start; const endTime = new Date(startTime); endTime.setHours(startTime.getHours() + durationHours); // 更新事件的结束时间,这样日历里的事件时长就和拖拽元素一致了 info.event.setEnd(endTime); } }); calendar.render(); // 初始化外部拖拽功能 new FullCalendar.Draggable(externalEventsEl, { itemSelector: '.fc-event', eventData: function(eventEl) { // 返回事件的基础样式和标题 return { title: eventEl.textContent.trim(), backgroundColor: window.getComputedStyle(eventEl).backgroundColor, borderColor: window.getComputedStyle(eventEl).backgroundColor }; } }); });
3. 补充细节优化
- 如果需要支持视图切换(比如从timeGridWeek切换到timeGridDay),可以监听
viewDidChange事件,重新计算拖拽元素的高度,因为不同视图的minuteHeight可能不同。 - 样式上可以给外部拖拽元素加上和日历事件一致的样式,让视觉统一:
.external-events { padding: 10px; background: #f5f5f5; border-radius: 4px; } .fc-event { padding: 5px 8px; margin: 8px 0; cursor: grab; border-radius: 3px; color: #fff; user-select: none; }
这样一来,外部拖拽元素的高度会和日历里对应时长的事件完全匹配,用户拖拽前就能直观看到事件的时长,拖拽到日历后也不会出现尺寸和时长不符的问题。
内容的提问来源于stack exchange,提问作者masrlinu
相关产品推荐
相关产品推荐

