gpt4 book ai didi

javascript - 日历事件的可视化。以最大宽度布局事件的算法

转载 作者:IT王子 更新时间:2023-10-29 03:00:23 25 4
gpt4 key购买 nike

我需要你的算法帮助(它将在客户端使用 javascript 开发,但并不重要,我主要对算法本身感兴趣)布置日历事件以便每个事件框具有最大宽度.请看下图:

calendar events layout

Y 轴是时间。因此,如果“测试事件”在中午开始(例如)并且没有更多内容与其相交,则它占用整个 100% 的宽度。 “每周回顾”与“翻滚的基督教青年会”和“安娜/阿米莉亚”有交集,但后两者没有交集,所以都占了50%。 Test3、Test4 和 Test5 都相交,因此每个最大宽度为 33.3%。但是 Test7 是 66%,因为 Test3 是固定的 33%(见上文),所以它占用了所有可用空间,即 66%。

我需要一个算法来布置它。

提前致谢

最佳答案

  1. 想象一个只有左边的无限网格。
  2. 每个事件都是一个单元格宽,高度和垂直位置根据开始和结束时间固定。
  3. 尽量将每个事件放在尽可能靠左的列中,不要与该列中的任何较早的事件相交。
  4. 然后,当放置每个连接的事件组时,它们的实际宽度将为该组使用的最大列数的 1/n。
  5. 您还可以展开最左侧和最右侧的事件以用完所有剩余空间。
/// Pick the left and right positions of each event, such that there are no overlap.
/// Step 3 in the algorithm.
void LayoutEvents(IEnumerable<Event> events)
{
var columns = new List<List<Event>>();
DateTime? lastEventEnding = null;
foreach (var ev in events.OrderBy(ev => ev.Start).ThenBy(ev => ev.End))
{
if (ev.Start >= lastEventEnding)
{
PackEvents(columns);
columns.Clear();
lastEventEnding = null;
}
bool placed = false;
foreach (var col in columns)
{
if (!col.Last().CollidesWith(ev))
{
col.Add(ev);
placed = true;
break;
}
}
if (!placed)
{
columns.Add(new List<Event> { ev });
}
if (lastEventEnding == null || ev.End > lastEventEnding.Value)
{
lastEventEnding = ev.End;
}
}
if (columns.Count > 0)
{
PackEvents(columns);
}
}

/// Set the left and right positions for each event in the connected group.
/// Step 4 in the algorithm.
void PackEvents(List<List<Event>> columns)
{
float numColumns = columns.Count;
int iColumn = 0;
foreach (var col in columns)
{
foreach (var ev in col)
{
int colSpan = ExpandEvent(ev, iColumn, columns);
ev.Left = iColumn / numColumns;
ev.Right = (iColumn + colSpan) / numColumns;
}
iColumn++;
}
}

/// Checks how many columns the event can expand into, without colliding with
/// other events.
/// Step 5 in the algorithm.
int ExpandEvent(Event ev, int iColumn, List<List<Event>> columns)
{
int colSpan = 1;
foreach (var col in columns.Skip(iColumn + 1))
{
foreach (var ev1 in col)
{
if (ev1.CollidesWith(ev))
{
return colSpan;
}
}
colSpan++;
}
return colSpan;
}

编辑:现在对事件进行排序,而不是假定它们已排序。

Edit2:如果有足够的空间,现在将事件扩展到右侧。

关于javascript - 日历事件的可视化。以最大宽度布局事件的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11311410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com