Php 将碰撞元素彼此相邻放置
我正在创建某种日历/日程,显示某一天的活动。每个事件都显示为垂直小时网格中的HTML元素。同时可能有多个(“碰撞”)事件,在这些情况下,元素应水平相邻放置,并具有相等的宽度。例如,四个碰撞事件得到列值4,这样宽度为25% 棘手的部分是这些碰撞事件。我以为我解决了,但有些元素的列数不正确 可能有更好的方法来计算列数和位置-我愿意接受建议 当前(错误)结果的示例图像: 相关代码:Php 将碰撞元素彼此相邻放置,php,html,Php,Html,我正在创建某种日历/日程,显示某一天的活动。每个事件都显示为垂直小时网格中的HTML元素。同时可能有多个(“碰撞”)事件,在这些情况下,元素应水平相邻放置,并具有相等的宽度。例如,四个碰撞事件得到列值4,这样宽度为25% 棘手的部分是这些碰撞事件。我以为我解决了,但有些元素的列数不正确 可能有更好的方法来计算列数和位置-我愿意接受建议 当前(错误)结果的示例图像: 相关代码: <?php class Calendar { const ROW_HEIGHT = 24
<?php
class Calendar {
const ROW_HEIGHT = 24;
public $events = array();
public $blocks = array();
public function calculate_blocks() {
foreach($this->events as $event) {
// Calculate the correct height and vertical placement
$top = $this->time_to_pixels($event->_event_start_time);
$bottom = $this->time_to_pixels($event->_event_end_time);
$height = $bottom - $top;
// Abort if there's no height
if(!$height) continue;
$this->blocks[] = array(
'id' => $event->ID,
'columns' => 1,
'placement' => 0, // Column order, 0 = first
'css' => array(
'top' => $top,
'bottom' => $bottom, // bottom = top + height
'height' => $height
)
);
}
$done = array();
// Compare all the blocks with each other
foreach($this->blocks as &$block) {
foreach($this->blocks as &$sub) {
// Only compare two blocks once, and never compare a block with itself
if($block['id'] == $sub['id'] || (isset($done[$block['id']]) && in_array($sub['id'], $done[$block['id']])) || (isset($done[$sub['id']]) && in_array($block['id'], $done[$sub['id']]))) continue;
$done[$block['id']][] = $sub['id'];
// If the blocks are colliding
if(($sub['css']['top'] >= $block['css']['top'] && $sub['css']['top'] < $block['css']['bottom'])
|| ($sub['css']['bottom'] >= $block['css']['top'] && $sub['css']['bottom'] < $block['css']['bottom'])
|| ($sub['css']['top'] <= $block['css']['top'] && $sub['css']['bottom'] >= $block['css']['bottom'])) {
// Increase both blocks' columns and sub-block's placement
$sub['columns'] = ++$block['columns'];
$sub['placement']++;
}
}
}
}
private function time_to_int($time) {
// H:i:s (24-hour format)
$hms = explode(':', $time);
return ($hms[0] + ($hms[1] / 60) + ($hms[2] / 3600));
}
private function time_to_pixels($time) {
$block = $this->time_to_int($time);
return (int)round($block * self::ROW_HEIGHT * 2);
}
}
?>
试试这个:
public function calculate_blocks()
{
$n = count($events);
$collumns = array();
$placements = array();
// Set initial values.
for ($i = 0; $i < $n; $i++)
{
$collumns[$i] = 1;
$placements[$i] = 0;
}
// Loop over all events.
for ($i = 0; $i < $n; $i++)
{
$top1 = $this->time_to_pixels($events[$i]->_event_start_time);
$bottom1 = $this->time_to_pixels($events[$i]->_event_end_time);
// Check for collisions with events with higher indices.
for ($j = $i + 1; $j < $n; $j++)
{
$top2 = $this->time_to_pixels($events[$k]->_event_start_time);
$bottom2 = $this->time_to_pixels($events[$k]->_event_end_time);
$collides = $top1 < $bottom2 && $top2 < $bottom1;
// If there is a collision, increase the collumn count for both events and move the j'th event one place to the right.
if ($collides)
{
$collumns[$i]++;
$collumns[$j]++;
$placements[$j]++;
}
}
$this->blocks[] = array(
'id' => $events[$i]->ID,
'columns' => $collumns[$i],
'placement' => $placements[$i],
'css' => array(
'top' => $top1,
'bottom' => $bottom1,
'height' => $bottom1 - $top1;
)
);
}
}
公共函数计算\u块()
{
$n=计数($events);
$collumns=array();
$placements=array();
//设置初始值。
对于($i=0;$i<$n;$i++)
{
$collumns[$i]=1;
$placements[$i]=0;
}
//循环所有事件。
对于($i=0;$i<$n;$i++)
{
$top1=$this->time\u to\u像素($events[$i]->\u event\u start\u time);
$bottom1=$this->time\u to\u像素($events[$i]->\u event\u end\u time);
//检查是否与索引较高的事件发生冲突。
对于($j=$i+1;$j<$n;$j++)
{
$top2=$this->time\u to\u像素($events[$k]->\u event\u start\u time);
$bottom2=$this->time\u to\u像素($events[$k]->\u event\u end\u time);
$collides=$top1<$bottom2&&$top2<$bottom1;
//如果发生碰撞,增加两个事件的collumn计数,并将第j个事件向右移动一个位置。
如果($冲突)
{
$collumns[$i]++;
$collumns[$j]++;
$placements[$j]++;
}
}
$this->blocks[]=array(
'id'=>$events[$i]->id,
“列”=>$collumns[$i],
“placement”=>$placements[$i],
'css'=>数组(
“top”=>top1美元,
“底部”=>$bottom1,
“高度”=>$bottom1-$top1;
)
);
}
}
我无法实际测试它,但我认为它应该给您留下一个正确的块数组
编辑1:似乎没有产生所需的结果,请参见下面的评论
编辑2:我认为这是完全相同的问题:。有人用C#解决了这个问题,但将这个答案移植到PHP来解决您的问题应该相对容易。我不认为这是PHP需要解决的问题。这就是它。在这种特殊情况下,它应该在服务器级别完成。无论如何,谢谢你。当你用$this->blocks创建这些嵌套的foreach时,光标不是被设置到了不同的位置吗?也许你应该检查一下。谢谢你的评论,@SenseException。我检查了每个循环的光标,没有问题。处理“嵌套循环”的最简单方法是使用“预读”和“while”循环,而不是“foreach”循环。问题是您需要在当前循环中的任何点读取“下一条记录”。“foreach”的问题是,他们只在循环结束时读取“下一条记录”。非常感谢您的努力,我将在明天进行测试,并返回结果。我想我知道发生了什么。我只是不知道如何修复它目前。如果你仔细观察,这些块确实得到了预期的数字,只是不正确。例如,事件#68与#426和#385重叠,因此大小为1/3。但是#385与#68、#383、#381和#63重叠,大小为1/5。因此,这些块确实根据它们重叠的事件数量获得了正确的大小/位置,但这最终看起来很奇怪。需要记住的是,A+B和B+C之间的重叠并不一定意味着A+C之间的重叠。也许这可以帮助你想出一些东西。是的,我昨天在试验时注意到了完全相同的事情。非常感谢你的链接,看起来确实是同样的问题。我将把它翻译成PHP,明天测试它-如果它能工作,我一定会在这里分享它。抱歉耽搁了。它以链接()提供的一些JavaScript结束。非常感谢你的帮助!