我有一个“活动”的PHP数组,只有1天,有一个开始&结束时间(未按时间顺序排列)如下:
$events_list = array(
array(
'name' => 'Event B',
'start' => '5:00pm',
'end' => '6:30pm',
),
array(
'name' => 'Event C',
'start' => '3:30pm',
'end' => '5:00pm',
),
array(
'name' => 'Event H',
'start' => '1:15pm',
'end' => '2:45pm',
),
array(
'name' => 'Event I',
'start' => '1:30pm',
'end' => '4:00pm',
),
array(
'name' => 'Event K',
'start' => '4:30pm',
'end' => '5:30pm',
),
array(
'name' => 'Event L',
'start' => '3:15pm',
'end' => '5:00pm',
),
);
我试图在水平时间轴上直观地输出这些事件,如下所示:
[* Event H: 1:15pm-2:45pm *] [* Event L: 3:15pm-5:00pm *][* Event B: 5:00pm-6:30pm *]
[* Event I: 1:30pm-4:00pm *] [* Event K: 4:30pm-5:30pm *]
[* Event C: 3:30pm-5:00pm *]
(请注意,上述内容绝对不是“按比例绘制”。)
如您所见,当事件的开始/结束时间重叠时,需要移至下一行。
然而,我很难找到一种方法来实现这一点,特别是当事件的开始/结束时间与其他两个事件重叠时(例如,K的开始重叠“事件L”,而K的结束重叠“事件B“),使其向下移动2行而不是1行。
这感觉非常挑战。非常感谢任何想法或建议!
答案 0 :(得分:1)
我已经做过类似的事了。这是我们所做工作的缩小版。还有一个使用具有绝对位置的div显示图表的简单版本。
<?php
$events_list = array(
array(
'name' => 'Event B',
'start' => '5:00pm',
'end' => '6:30pm',
),
array(
'name' => 'Event C',
'start' => '3:30pm',
'end' => '5:00pm',
),
array(
'name' => 'Event H',
'start' => '1:15pm',
'end' => '2:45pm',
),
array(
'name' => 'Event I',
'start' => '1:30pm',
'end' => '4:00pm',
),
array(
'name' => 'Event K',
'start' => '4:30pm',
'end' => '5:30pm',
),
array(
'name' => 'Event L',
'start' => '3:15pm',
'end' => '5:00pm',
),
);
//easier to use timestamps, looping over all rows and overwriting time with timestamp
foreach($events_list as $k=>$v){
$events_list[$k]['start']=strtotime($v['start']);
$events_list[$k]['end']=strtotime($v['end']);
}
//sort list by start time. Lowers the number of loops needed below
function cmp($a,$b){
if($a['start']==$b['start']){
$aTS = $a['end'];
$bTS = $b['end'];
} else {
$aTS = $a['start'];
$bTS = $b['start'];
}
if($aTS == $bTS)return 0;
return ($aTS < $bTS)?-1:1;
}
usort($events_list, 'cmp');
//This is where the data will be saved
$levels = array();
//loop over all the events
foreach($events_list as $event){
//was this event placed in a level already?
$placed = false;
//loop through each level checking only the last event
foreach($levels as $row=>$events){
//we only need to check the last event if they are already sorted
$last = end($events);
//does the current event start after the end time of the last event in this level
if($event['start'] >= $last['end']){
//add to this level and break out of the inner loop
$levels[$row][] = $event;
$placed = true;
break;
}
}
//if not placed in another level, add a new level
if(!$placed){
$levels[] = array($event);
}
}
//used for display purposes
$minutesPerPixel = 2;
?>
<html>
<head>
<style type="text/css">
.level {
background-color:#DDD;
width:<?=floor(24*60/$minutesPerPixel)?>px;
border:1px solid #999;
position:relative;
height:25px;
}
.event {
position:absolute;
overflow:hidden;
height:19px;
top:2px;
background-color:#ACF;
border:1px solid black;
padding-left:3px;
font:9px arial;
line-height:9px;
}
</style>
</head>
<body>
<?php
//display
foreach($levels as $level){
echo "<div class='level'>\n";
foreach($level as $event){
$left = floor((date('H',$event['start'])*60 + date('i', $event['start']))/$minutesPerPixel);
$width = floor((($event['end']-$event['start'])/60)/$minutesPerPixel);
echo "\t<div class='event' style='left:{$left}px;width:{$width}px'>{$event['name']}</div>\n";
}
echo "</div>";
}
?>
</body>
</html>