Поиск позиционно ближайшего div к другому

#javascript

#javascript

Вопрос:

занятый кот

Привет, как бы я нашел длины строк, выделенные другим цветом (с вопросительными знаками) на картинке выше? Прямоугольники — это просто подразделения с абсолютной позицией.

Моя цель — найти «ближайший» div к зеленому, но «ближайший» — довольно абстрактное определение, поэтому я решил, что «ближайшим» будет тот, у которого самая короткая выделенная строка на картинке выше. Может быть, есть другие более простые способы найти «ближайший» div??

Ответ №1:

Некоторое время назад возник вопрос, связанный с этим, который вдохновил меня начать писать плагин jQuery, чтобы сделать именно это. Вы не упомянули jQuery в своем вопросе, но это, безусловно, значительно упростит эту задачу.

Вот рабочий пример (он выделен ближе div всего к красному). Вы вызываете плагин следующим образом:

 $("#myDiv").physicallyClosest("div").css("background-color", "#00ff00");
 

Это находит тот div , который физически ближе #myDiv всего, и изменяет его цвет фона.

Я уверен, что это далеко от совершенства, но если вы можете использовать jQuery, этого должно быть достаточно, чтобы вы начали.

Ответ №2:

Живая демонстрация

Чистый JS. В основном просто получает смещения и выполняет стандартную проверку расстояния.

 //setup for the example
var divs = document.getElementsByTagName('div');

// Randomly place some divs around the screen.
for(var i = 0; i < divs.length; i  ){
     divs[i].style.top = Math.random()*500   'px';
     divs[i].style.left = Math.random()*600   'px';    
     divs[i].onclick = getClosest;
}

// Actual function to get the closest
function getClosest(e){
    var x = this.offsetLeft,
        y = this.offsetTop,
        minDist = 99999,
        closestElement = {};

    for(var i = 0; i < divs.length; i  ){
        if(divs[i] !== this){
           var x2 = divs[i].offsetLeft,
               y2 = divs[i].offsetTop;

           dist = Math.sqrt((x2 - x) *(x2-x)   (y2 - y) * (y2-y));

           if(dist < minDist){
               minDist = dist;
               closestElement = divs[i];
            }
        }
    }

    // Set the background of the closest element to red.
    closestElement.style.background = 'red';
}
 

Это основано на том, что начало координат находится в верхнем левом углу, но вы можете изменить его на середину элемента, просто выполнив что-то вроде следующего

 x = offsetLeft   width/2;
y = offsetTop   height/2;
 

Комментарии:

1. Это работает некорректно -> cl.ly/423N2V1Y1h253P0d0b3V Я нажал на тест 1, и тест 3 стал красным

2. @AlaskaKid с этим произошла ошибка, я по ошибке сравнил все x и ни одного y. Теперь все должно работать нормально.

3. Ваша функция работает довольно хорошо, но есть некоторые ошибки cl.ly/212B3f0u072A3n1E0Y1l просто нажал на тест 5

4. @AlaskaKid да, его сравнение сверху / слева test1 должно быть ближе, хотя для его работы используется простая документированная функция расстояния.

Ответ №3:

Только что написал функцию, которая принимает 2 параметра (элемент и массив divs, где мы должны искать ближайший div к элементу в первом параметре) и возвращает ближайший элемент.

Живой пример

 function getClosest(element, divs) {

// Returns x, y coords of object relatively to the whole document
function getWindowPosition(obj) {
  var box = obj.getBoundingClientRect();
  return {
    x : box.left,
    y : box.top
  }
}

var elementLeft = getWindowPosition(element).x;
var elementRight = elementLeft   element.offsetWidth;
var elementTop = getWindowPosition(element).y;
var elementBottom = elementTop   element.offsetHeight;

var smallestDistance = null;
var closestElement = null;
for(var i = 0; i < divs.length; i  ) {
    divs[i].style.background = 'yellow'; //For demo, delete this line
    var divLeft = getWindowPosition(divs[i]).x;
    var divRight = divLeft   divs[i].offsetWidth;
    var divTop = getWindowPosition(divs[i]).y;
    var divBottom = divTop   divs[i].offsetHeight;

    var xPosition = 0;
    //Finding div's postion on x axis
    if(divRight < elementLeft) {
        xPosition = elementLeft - divRight;
    } else if(divLeft > elementRight) {
        xPosition = divLeft - elementRight;
    }

    var yPosition = 0;
    //Finding div's postion on y axis
    if(divBottom < elementTop) {
        yPosition = elementTop - divBottom;
    } else if(divTop > elementBottom) {
        yPosition = divTop - elementBottom;
    }

    var valueForComparison = 0;
    if(xPosition > yPosition) {
        valueForComparison = xPosition;
    } else {
        valueForComparison = yPosition;
    }

    //Comparing divs
    if(smallestDistance === null) {
        smallestDistance = valueForComparison;
        closestElement = divs[i];
    } else if(valueForComparison < smallestDistance) {
        smallestDistance = valueForComparison;
        closestElement = divs[i];
    }
}

closestElement.style.background = 'red'; //For demo, delete this line
return closestElement;
}