2010-11-22 18 views
0

我正在做一個應用程序,如MS Outlook日曆,用戶可以把事件等 我有事件對象佈局根據大小等問題,因爲用戶可以拖動和重新大小事件對象在MS Outlook日曆和事件對象的大小自動設置。製作日曆如MS Outlook所需的幫助?

我需要這樣做的算法,我寫我自己的,但有幾個問題需要幫助。

此屏幕快照將顯示動態的事件對象排列。 alt text

+0

你在使用到建立你的日曆應用? (HTML + JS,WPF等) – josh3736 2010-11-22 13:40:02

+0

我正在使用flex動作腳本 – Badr 2010-11-24 05:38:46

+1

可以任何一步一步描述算法。 – Badr 2010-12-01 12:32:32

回答

1

這裏是俺們

,你可以去矩形包裝算法,但要記住的事件應該進行排序WRT時間和日期,只有水平包裝會爲你工作

這裏是矩形包裝algo

1

由於您使用的是Flex,所以這不是對您的問題的直接回答,但它有望讓您走上正確的道路。

試試看看FullCalendar的周視圖和日視圖是如何實現這一點的。 FullCalendar是一個jQuery插件,用於呈現完全符合您需求的日曆。

您必須從FullCalendar中提取渲染邏輯並將其轉換爲Flex中的項目。我知道JavaScript和ActionScript是非常相似的,但我從來沒有使用Flex —對不起,我不能在這方面更多的幫助。

FullCalendar的回購是here。具體來說,它看起來像AgendaView.js是你最關注的文件。

+1

它沒有爲我工作................ – Badr 2010-12-01 07:26:13

0

我想你是問一個普通的對象佈局算法,對不對?

我敢肯定,這是一個NP完全問題:排列一組,如果間隔,各由一個開始年底儘可能定義。

是NP完全的手段,你最好的拍攝可能正試圖尋找一切可能的安排:

  • 找到集羣在你的對象 - 在,你有事情做,其中的間隔重疊。
  • 爲每個羣集都
    • Ñ是對象的數目的簇中
    • 如果Ñ過高(如10或15),停止並只畫重疊對象
    • 生成所有可能的排序集羣中的對象的(對於ñ對象,這些都是N!可能的組合,即6個對象,120級可能的排序)
    • 對於每個排序以平凡的方式佈局對象:循環遍歷元素並將它們放置在現有列中,如果它適合那裏,則在需要時啓動一個新列。
    • 保持佈局用最少的列
+0

我已經這樣做過,但在重新調整大小後,它無法根據需要佈置所有事件框 – Badr 2010-12-01 07:27:32

0

這是我如何做的:

  1. 事件是分組到由天(或一些其它規則)可變列
  2. 活動在一列中被進一步分離成列,只要有在Y軸的連續交叉點。
  3. 事件被賦予它們的X軸值(0到1)和它們的X尺寸(0到1)
  4. 事件遞歸地展開,直到每個相交組的最後一個(由Y和X軸)列屏障或其他事件,已完成擴展。

本質上講,它是一種蠻力,而是相當快的工作,因爲有需要進一步擴大,超出的步驟不是很多事件3

var physics = []; 
var step = 0.01; 

var PackEvents = function(columns){ 
    var n = columns.length; 
    for (var i = 0; i < n; i++) { 
     var col = columns[ i ]; 
     for (var j = 0; j < col.length; j++) 
     { 
      var bubble = col[j]; 
      bubble.w = 1/n; 
      bubble.x = i*bubble.w; 
     } 
    } 
}; 

var collidesWith = function(a,b){ 
    return b.y < a.y+a.h && b.y+b.h > a.y; 
}; 

var intersects = function(a,b){ 
    return b.x < a.x+a.w && b.x+b.w > a.x && 
      b.y < a.y+a.h && b.y+b.h > a.y; 
}; 

var getIntersections = function(box){ 
    var i = []; 
    Ext.each(physics,function(b){ 
     if(intersects(box,b) && b.x > box.x) 
      i.push(b); 
    }); 
    return i; 
}; 

var expand = function(box,off,exp){ 
    var newBox = { 
     x:box.x, 
     y:box.y, 
     w:box.w, 
     h:box.h, 
     collision:box.collision, 
     rec:box.rec 
    }; 
    newBox.x += off; 
    newBox.w += exp; 
    var i = getIntersections(newBox); 
    var collision = newBox.x + newBox.w > 1; 
    Ext.each(i,function(n){ 
     collision = collision || expand(n,off+step,step) || n.collision; 
    }); 
    if(!collision){ 
     box.x = newBox.x; 
     box.w = newBox.w; 
     box.rec.x = box.x; 
     box.rec.w = box.w; 
    }else{ 
     box.collision = true; 
    } 
    return collision; 
}; 

Ext.each(columns,function(column){ 
    var lastEventEnding = null; 
    var columns = []; 
    physics = []; 

    Ext.each(column,function(a){ 
     if (lastEventEnding !== null && a.y >= lastEventEnding) { 
      PackEvents(columns); 
      columns = []; 
      lastEventEnding = null; 
     } 
     var placed = false; 
     for (var i = 0; i < columns.length; i++) { 
      var col = columns[ i ]; 
      if (!collidesWith(col[col.length-1], a)) { 
       col.push(a); 
       placed = true; 
       break; 
      } 
     } 
     if (!placed) { 
      columns.push([a]); 
     } 
     if (lastEventEnding === null || a.y+a.h > lastEventEnding) { 
      lastEventEnding = a.y+a.h; 
     } 
    }); 
    if (columns.length > 0) { 
     PackEvents(columns); 
    } 

    Ext.each(column,function(a){ 
     a.box = { 
      x:a.x, 
      y:a.y, 
      w:a.w, 
      h:a.h, 
      collision:false, 
      rec:a 
     }; 
     physics.push(a.box); 
    }); 

    while(true){ 
     var box = null; 
     for(i = 0; i < physics.length; i++){ 
      if(!physics[i].collision){ 
       box = physics[i]; 
       break; 
      } 
     } 
     if(box === null) 
      break; 
     expand(box,0,step); 
    } 

}); 

結果:http://imageshack.com/a/img913/9525/NbIqWK.jpg