Javascript 会议日历|如何处理日历中显示的重叠会议?

Javascript 会议日历|如何处理日历中显示的重叠会议?,javascript,html,css,calendar,Javascript,Html,Css,Calendar,很抱歉问了这么长的问题 我尝试在日历上创建一个一天的会议。我需要帮助来处理重叠的间隔 我编写的代码如下: HTML <body> <div id="timeline"></div> <div id="calendar" class="calendar"> </div> </body> JS .calendar { border: 1px solid black; position: absolute;

很抱歉问了这么长的问题

我尝试在日历上创建一个一天的会议。我需要帮助来处理重叠的间隔

我编写的代码如下:

HTML

<body>
  <div id="timeline"></div>
  <div id="calendar" class="calendar">
  </div>
</body>
JS

.calendar {
  border: 1px solid black;
  position: absolute;
  width: 600px;
  height: 1440px;
  left: 60px;
}

.event {
  position: absolute;
  float: left;
  width: 100%;
  overflow: auto;
  border: 0px solid red;
}

#timeline {
  position: absolute;
  float: left;
}
function getRandomColor() {
  var letters = '0123456789ABCDEF'.split('');
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function creatTimeline(tl) {
  var i = 0;
  while (i < tl.length) {
    var divEl = document.createElement('div');
    divEl.style.width = '50px';
    divEl.style.height = '120px';
    divEl.style.border = '0px solid yellow';
    divEl.innerHTML = tl[i];
    var timeLine = document.getElementById('timeline');
    timeLine.appendChild(divEl);
    i++;
  }
}

function appendEventDivs(eventArr) {
  var i = 0;
  while (i < eventArr.length) {
    var eventEl = document.createElement('div');
    eventEl.className = 'event';
    eventEl.style.height = eventArr[i].height;
    eventEl.style.top = eventArr[i].top;
    eventEl.style.background = eventArr[i].color;
    eventEl.style.width = eventArr[i].width;
    eventEl.style.left = eventArr[i].left;
    eventEl.innerHTML = 'Meeting' + eventArr[i].id;
    var cl = document.getElementById('calendar');
    cl.appendChild(eventEl);
    i++;
  }
}

function collidesWith(a, b) {
  return a.end > b.start && a.start < b.end;
}

function checkCollision(eventArr) {
  for (var i = 0; i < eventArr.length; i++) {
    eventArr[i].cols = [];
    for (var j = 0; j < eventArr.length; j++) {
      if (collidesWith(eventArr[i], eventArr[j])) {
        eventArr[i].cols.push(i);
      }
    }
  }

  return eventArr;
}

function updateEvents(eventArr) {
  eventArr = checkCollision(eventArr);
  var arr = [];
  arr = eventArr.map(function(el) {
      //just to differentiate each event with different colours
    el.color = getRandomColor();

    el.height = (el.end - el.start) * 2 + 'px';
    el.top = (el.start) * 2 + 'px';
    el.width = (600 / el.cols.length) + 'px';
    return el;
  });
  return arr;
}

var events = [{
  id: 123,
  start: 60,
  end: 150
}, {
  id: 124,
  start: 540,
  end: 570
}, {
  id: 125,
  start: 555,
  end: 600
}, {
  id: 126,
  start: 585,
  end: 660
}];

var timeline = ['9AM', '10AM', '11AM', '12Noon', '1PM', '2PM', '3PM', '4PM', '5PM', '6PM', '7PM', '8PM', '9PM'];

function getEvents (eventArr) {
  eventArr.sort(function(a, b) {
    return a.start - b.start;
  });
  eventArr = updateEvents(eventArr);
  appendEventDivs(eventArr);
    console.log(eventArr);
  //PART 1 - function returning the eventArr with all the required attributes
  return eventArr;
};

creatTimeline(timeline);
getEvents(events);
函数getRandomColor(){ 变量字母='0123456789ABCDEF'。拆分(''); var color='#'; 对于(变量i=0;i<6;i++){ 颜色+=字母[Math.floor(Math.random()*16)]; } 返回颜色; } 功能创建时间线(tl){ var i=0; 而(ib.start&&a.start 工作小提琴

有谁能指导我如何处理重叠的间隔,使它们并排出现,而不是相互重叠


提前感谢。

您已经知道每个活动的顶部和高度,因此您可以映射日历并检查活动将占用的区域内是否已经存在活动,然后用现有事件的数量偏移左值。

在确定每个事件的宽度或左位置之前,您需要确定每个事件应位于哪一列。要执行此操作,还需要存储每个事件之前发生的碰撞事件:

function checkCollision(eventArr) {
  for (var i = 0; i < eventArr.length; i++) {
    eventArr[i].cols = [];
    eventArr[i].colsBefore=[];
    for (var j = 0; j < eventArr.length; j++) {
      if (collidesWith(eventArr[i], eventArr[j])) {
        eventArr[i].cols.push(j);
        if(i>j) eventArr[i].colsBefore.push(j); //also list which of the conflicts came before
      }
    }
  }
  return eventArr;
}
工作小提琴: 我添加了一些其他事件来测试不同的场景


哦,顺便问一下,
绝对定位元素
不能
浮动

我该如何准确地用列数和偏移量制作一张地图?你能详细说明一下吗?一个小代码就太棒了:)你真是太棒了,先生!!!!非常感谢:)我会记住不要浮动绝对定位的元素:)我仍在试图弄清楚您是如何提出此解决方案的…:\哦,我的解释是不清楚还是需要详细说明?老实说,我已经准备好放弃了,在小提琴上工作了两个小时,半个小时没有保存,然后创建了一个无限循环,标签崩溃了&我的工作丢了。。。所以在这一点上,我可能已经开始放松一些评论了,哈哈。如果我有时间的话,也许明天我会研究改进我的评论。是的,我可以看到这篇文章已经做了很多工作。这是一门伟大的艺术,像我这样的普通程序员几乎不会花时间去理解它。你是摇滚明星。。。。!!!(我希望我能马上给你一个SO标签..!!!)。
function updateEvents(eventArr) {
  eventArr = checkCollision(eventArr);
  var arr=eventArr.slice(0); //clone the array
  for(var i=0; i<arr.length; i++){
    var el=arr[i];
    el.color = getRandomColor();
    el.height = (el.end - el.start) * 2 + 'px';
    el.top = (el.start) * 2 + 'px';

    if(i>0 && el.colsBefore.length>0){ //check column if not the first event and the event has collisions with prior events
      if(arr[i-1].column>0){ //if previous event wasn't in the first column, there may be space to the left of it
        for(var j=0;j<arr[i-1].column;j++){ //look through all the columns to the left of the previous event
          if(el.colsBefore.indexOf(i-(j+2))===-1){ //the current event doesn't collide with the event being checked...
            el.column=arr[i-(j+2)].column; //...and can be put in the same column as it
          }
        }
        if(typeof el.column==='undefined') el.column=arr[i-1].column+1; //if there wasn't any free space, but it ito the right of the previous event
      }else{
        var column=0;
        for(var j=0;j<el.colsBefore.length;j++){ //go through each column to see where's space...
          if(arr[el.colsBefore[el.colsBefore.length-1-j]].column==column) column++;
        }
        el.column=column;
      }
    }else el.column=0;
  }
  //We need the column for every event before we can determine the appropriate width and left-position, so this is in a different for-loop:
  for(var i=0; i<arr.length; i++){
    arr[i].totalColumns=0;
    if(arr[i].cols.length>1){ //if event collides
      var conflictGroup=[]; //store here each column in the current event group
      var conflictingColumns=[]; //and here the column of each of the events in the group
      addConflictsToGroup(arr[i]);
      function addConflictsToGroup(a){
        for(k=0;k<a.cols.length;k++){
          if(conflictGroup.indexOf(a.cols[k])===-1){ //don't add same event twice to avoid infinite loop
            conflictGroup.push(a.cols[k]);
            conflictingColumns.push(arr[a.cols[k]].column);
            addConflictsToGroup(arr[a.cols[k]]); //check also the events this event conflicts with
          }
        }
      }
      arr[i].totalColumns=Math.max.apply(null, conflictingColumns); //set the greatest value as number of columns
    }
    arr[i].width=(600/(arr[i].totalColumns+1))+'px';
    arr[i].left=(600/(arr[i].totalColumns+1)*arr[i].column)+'px';
  }
  return arr;
}