javascript – 如何在不相互重叠的情况下传播div

我正在建立一个事件调度程序,我已经陷入了一个问题,我无法找到一种方法来传播事件而不会相互重叠. (它可能同时具有事件且没有限制.只要可能,使用100%的可用宽度)

这是这个场景的图片.

enter image description here

一些考虑:

>事件被包含在div中,其位置为:relative,所有事件的位置为:absolute.
>使用javascript,我必须弄清楚每个“div事件”的左上角宽度和高度的值是什么.
>事件是一组对象,如下面的代码

{
    startAt:“12:00:30”,
    endsAt:“13:00:00”,
    描述:“evt1”,
    id:’00001′
}
>我正在使用Vue.js来开发这个项目.但如果你不了解Vue,这不是问题.我使用jsbin构建了一个小项目,所以你可以使用javascript函数.

现场代码https://jsbin.com/bipesoy/

哪里有问题?

我无法找到一种基于事件数组动态计算左上角宽度和高度的算法.

关于jsbin代码的一些注意事项:

>找到上述4个属性的所有代码都在函数parsedEvents中
>在parsedEvents中,您可以使用以下命令访问事件数组:this.events
> parsedEvents的工作是遍历事件数组,并为每个事件添加样式属性,然后使用样式对象返回一个新的事件数组.
>每30分钟高度为40px;

任何想法如何实现它或更好的解决方案?

最佳答案
经过一段时间玩这个挑战后,我认为是时候放弃这个想法了.可以编程安排事件的许多可能场景,但是当你深入挖掘时,你会发现甚至很难写出你想要完成的事情,即使你管理了,你的一些决定也看起来并不好看.屏幕.这仅适用于宽度扩展事件.定位甚至重新定位它们以填补空白已经解决并且不太困难.

代码片段在这里(或者如果您愿意则为JSBin:http://jsbin.com/humiyi/99/edit?html,output).

绿色事件被检测为“可扩展”.灰色不能扩展.为了澄清扩展逻辑的问题,一些例子:

> evt 1和evt3?它可以像这样或evt3正确,它们都扩展
> evt7和evt12?扩展这个的许多方法……如何定义规则?
>想象evt7和evt11合并成一个大事件.如何扩展evt10,evt7 / 11和evt 12?
…现在尝试编写规则以持续回答上面的3(以及更多可能的场景,不在本例中)

我的结论是,编写规则并开发这个规则并不值得. UI可用性不会太多.它们甚至会在某些情况下松动,即某些事件在视觉上会更大,因为它们有空间而不是因为它们更重要.

我建议布局与示例中的布局相似或完全相同.事件只是不扩展.我不知道你期望有多少日常事件,现实生活中的情况如何,但只有我可能做的升级是在分开的区域中垂直分割日历 – 时间点与任何事件都不重叠,例如evt7和例如,evt11.然后单独为每个区域运行相同的脚本.这将重新计算每个区域的垂直槽,因此具有evt10 i evt11的区域将仅具有2个垂直槽,每个槽填充50%的空间.如果您的日历几乎没有拥挤的时间,并且之前/之前只有几个事件,这可能是值得的.这样可以在不花太多时间的情况下解决当天晚些时候过于狭窄的事件.但如果事件全天发生并且重叠很多,我认为这不值得.

let events = [
  { startAt: "00:00",endsAt: "01:00",description: "evt1",id: '00001' },{ startAt: "01:30",endsAt: "08:00",description: "evt2",id: '00002' },endsAt: "04:00",description: "evt3",id: '00003' },{ startAt: "00:30",endsAt: "02:30",id: '00013' },{ startAt: "00:00",id: '00014' },{ startAt: "03:00",endsAt: "06:00",description: "evt4",id: '00004' },endsAt: "04:30",description: "evt5",id: '00005' },endsAt: "07:00",description: "evt6",id: '00006' },{ startAt: "06:30",endsAt: "09:00",description: "evt7",id: '00007' },{ startAt: "04:30",description: "evt8",id: '00008' },{ startAt: "05:00",description: "evt9",id: '00009' },{ startAt: "09:00",endsAt: "10:00",description: "evt10",id: '00010' },endsAt: "10:30",description: "evt11",id: '00011' },{ startAt: "07:00",description: "evt12",id: '00012' }
]

console.time()

// will store counts of events in each 30-min chunk
// each element represents 30 min chunk starting from midnight
// ... so indexOf * 30 minutes = start time
// it will also store references to events for each chunk
// each element format will be: { count: hey fit gap perfectly - we will recheck those later
events.map(event => {
  if (event.pos > 1) {
    //find positions of overlapped events on the left side
    let vertSlotsTakenLeft = event.overlaps.reduce((result,cur) => {
      if (result.indexOf(cur.pos) < 0 && cur.pos < event.pos) result.push(cur.pos)
      return result
    },[])
    
    // check if empty space on the left
    for (i = 1; i < event.pos; i++) {
      if (vertSlotsTakenLeft.indexOf(i) < 0) {
        event.pos = i
        console.log("moving " + event.description + " left to pos " + i)
        break
      }
    }
  }
})

// fix moved events if they became non-expandable because of moving
events.filter(event=>event.expandable).map(event => {
  let leftFixed = event.overlaps.filter(comp => {
    return event.pos - 1 === comp.pos && comp.maxOverlapsInChunk === calSlots
  })
  let rightFixed = event.overlaps.filter(comp => {
    return event.pos + 1 === comp.pos && comp.maxOverlapsInChunk === calSlots
  })
  event.expandable = (!leftFixed.length || !rightFixed.length)
})

//settings for calendar (positioning events)
let calendar = {width: 300,chunkHeight: 30}

// one more loop through events to calculate top,left,width and height
events.map(event => {
  event.top = time2index(event.startAt) * calendar.chunkHeight
  event.height = time2index(event.endsAt) * calendar.chunkHeight - event.top
  //event.width = 1/event.maxOverlapsInChunk * calendar.width
  event.width = calendar.width/calSlots // Todo: temporary width is 1 slot 
  event.left = (event.pos - 1) * calendar.width/calSlots 
})

console.timeEnd()

// TEST drawing divs
events.map(event => {
  $("body").append(`
Meta charset="utf-8">
  <Meta name="viewport" content="width=device-width">
  

相关文章

vue阻止冒泡事件 阻止点击事件的执行 &lt;div @click=&a...
尝试过使用网友说的API接口获取 找到的都是失效了 暂时就使用...
后台我拿的数据是这样的格式: [ {id:1 , parentId: 0, name:...
JAVA下载文件防重复点击,防止多次下载请求,Cookie方式快速简...
Mip是什么意思以及作用有哪些