Составление div на основе доступного пространства - PullRequest
0 голосов
/ 10 октября 2018

У меня есть коллекция div, которые генерируются, позиционируются абсолютно и корректируются по размеру с помощью JavaScript на основе начальных и конечных значений.

var posts = [
	{
  	start: 50,
    end: 200,
    text: "Lorem ipsum"
  },
	{
  	start: 280,
    end: 350,
    text: "dolor"
  },
	{
  	start: 140,
    end: 300,
    text: "sit amet"
  },
	{
  	start: 440,
    end: 590,
    text: "consectetur"
  },
	{
  	start: 460,
    end: 570,
    text: "adipiscing"
  },
	{
  	start: 480,
    end: 550,
    text: "elit"
  },
];

$.each(posts, function(i, post){
	var obj = $("<div />");
  
 	obj.css({
  	left: post.start,
    width: post.end - post.start
  })
  obj.text(post.text);
  
  obj.appendTo("#timeline");
})
body {
  font-family: Montserrat, Arial, sans-serif;
}

.timeline {
  margin: 20px 0;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  position: relative;
  height: 60px;
}

.timeline div {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  height: 50px;
  top: 5px;
  background: darkblue;
  color: #fff;
  border-radius: 6px;
  padding: 0 10px;
  box-shadow: 0 0 0 2px #fff;
}


h1 {
  font-size: 18px;
  text-transform: uppercase;
  color: #999;
  font-weight: 400;
  letter-spacing: 0.05em;
  margin: 50px 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Current</h1>
<div id="timeline" class="timeline"></div>




<h1>Ideal</h1>
                      <!-- Height of the timeline adjusted to make room -->
<div class="timeline" style="height: 170px">
  <div style="left: 50px; width: 150px;">Lorem ipsum</div>
                                       <!-- This one not moved down because
                                       there is still room for it in the
                                       original position -->
  <div style="left: 280px; width: 70px;">dolor</div>
                                         <!-- Element moved down to
                                         since it overlaps two previous ones -->
  <div style="left: 140px; width: 160px; top: 60px;">sit amet</div>
  <div style="left: 440px; width: 150px;">consectetur</div>
                                         <!-- Element moved down -->
  <div style="left: 460px; width: 110px; top: 60px;">adipiscing</div>
                                        <!-- Element moved down even further -->
  <div style="left: 480px; width: 70px; top: 115px;">elit</div>
</div>

Однако, если два или более из этих div имеют перекрывающиеся начальные и конечные значения, сгенерированные div также будут перекрываться.В идеале я хотел бы рассчитать, какие div будут перекрываться, и добавить значение top, чтобы каждый div был полностью видимым.Элемент с большим значением start должен быть тем, который перемещается вниз.

Как я могу выяснить, какие элементы перекрываются, чтобы я мог переместить их на одну или две ступеньки ниже?

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Вот несколько наивный подход, который просто просматривает все сообщения и сравнивает каждое сообщение с каждым другим сообщением.Если он обнаруживает, что они находятся в одном диапазоне, он увеличивает верхнее значение.Он сравнивает посты только в том случае, если они имеют одинаковые верхние значения.

Обратите внимание, что время выполнения этого файла O (n ^ 2), что не очень хорошо, но для небольшого количества постов это должно быть в порядке.

function detectOverlaps(posts) {
  for (let i=0; i<posts.length; i++) {
    for (let j=0; j<posts.length; j++) {
      if (i == j) continue;
      var post1 = posts[i];
      var post2 = posts[j];
      if (post1.top != post2.top) continue;
      if ((post1.start < post2.end && post1.start > post2.start) ||
          (post1.end > post2.start && post1.end < post2.end)) {
        var post = (post1.start>post2.start) ? post1 : post2;
        if (!post.top) post.top = 0;
        post.top += 60; // Change this by the pixel amount
      }
    }
  }
  return posts;
}

Вот обновленная скрипка!

0 голосов
/ 10 октября 2018

Следите за тем, что фактически было вставлено в каждую строку, затем вы можете запустить простую функцию проверки перекрытия, чтобы решить, подойдет ли следующий div:

var posts = [
	{
  	start: 50,
    end: 200,
    text: "Lorem ipsum"
  },
	{
  	start: 280,
    end: 350,
    text: "dolor"
  },
	{
  	start: 140,
    end: 300,
    text: "sit amet"
  },
	{
  	start: 440,
    end: 590,
    text: "consectetur"
  },
	{
  	start: 460,
    end: 570,
    text: "adipiscing"
  },
	{
  	start: 480,
    end: 550,
    text: "elit"
  },
];

var lines = [];

$.each(posts, function(i, post){
	var obj = $("<div />");

  var lineNumber = addToLines(lines, post);
  
  if (lineNumber === lines.length) {
    lines.push([post]);
  }
  
  obj.css({
  	left: post.start,
    width: post.end - post.start,
    top: 3 + lineNumber * 54
  })
  obj.text(post.text);
  
  obj.appendTo("#timeline");
})

function addToLines(lines, post)
{
  for (var i = 0; i < lines.length; i++){
    if (fitsInLine(lines[i], post)) {
      lines[i].push(post);
      return i;
    }
  };
  
  return i;
}

function fitsInLine(line, postToAdd)
{
  for (var i = 0; i < line.length; i++){
    if (overlaps(postToAdd, line[i])) return false;
  }
  
  return true;
}

function overlaps(x, y)
{
  if (x.start < y.end && x.start > y.start) return true;
  
  if (x.end < y.end && x.end > y.start) return true;
  
  return false;
}
body {
  font-family: Montserrat, Arial, sans-serif;
}

.timeline {
  margin: 20px 0;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  position: relative;
  height: 180px;
}

.timeline div {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  height: 50px;
  top: 5px;
  background: darkblue;
  color: #fff;
  border-radius: 6px;
  padding: 0 10px;
  box-shadow: 0 0 0 2px #fff;
}


h1 {
  font-size: 18px;
  text-transform: uppercase;
  color: #999;
  font-weight: 400;
  letter-spacing: 0.05em;
  margin: 50px 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Current</h1>
<div id="timeline" class="timeline"></div>



<h1>Ideal</h1>
                      <!-- Height of the timeline adjusted to make room -->
<div class="timeline" style="height: 170px">
  <div style="left: 50px; width: 150px;">Lorem ipsum</div>
                                       <!-- This one not moved down because
                                       there is still room for it in the
                                       original position -->
  <div style="left: 280px; width: 70px;">dolor</div>
                                         <!-- Element moved down to
                                         since it overlaps two previous ones -->
  <div style="left: 140px; width: 160px; top: 60px;">sit amet</div>
  <div style="left: 440px; width: 150px;">consectetur</div>
                                         <!-- Element moved down -->
  <div style="left: 460px; width: 110px; top: 60px;">adipiscing</div>
                                        <!-- Element moved down even further -->
  <div style="left: 480px; width: 70px; top: 115px;">elit</div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...