2012-01-25 2 views
2

페이지가 있고 위젯이 있습니다. 2 개의 열이 있습니다. 위젯이 왼쪽 (또는 오른쪽)에 위젯이 없으면 위젯이 자동으로 크기가 조절됩니다.전체 페이지의 한 지점에 요소 가져 오기 (보이지 않더라도)

(위젯의 오프셋을 얻은 후) document.elementFromPoint을 사용하여 옆에 위젯이 있는지 감지합니다.

document.elementFromPoint에 문제가 있습니다.

지정된 지점이 문서의 보이는 범위 밖에 있으면 ... 결과는 null입니다.

요소가 뷰포트에있는 경우에만 작동합니다. 어떤 요소가 보이지 않더라도 특정 위치에 있는지 어떻게 알 수 있습니까?

EDIT : 여기의 예이다 :

Crappy Mockup

적색 라인 뷰포트 및 (적색 기입)와 회색 박스 위젯 D'의 원위치 (다른 위젯 D입니다 페이지로드가 완료되었을 때의 위치입니다.) 페이지가로드되면 위젯 B, C 및 D를 확인하고 오프셋을 가져온 다음 document.elementFromPoint을 사용하여 위젯 A가 올바른지 확인합니다. 위젯 A가 맞다면, 위젯은 반 너비입니다. 그렇지 않으면 전체 너비입니다.

document.elementFromPoint이 뷰포트 밖에 있기 때문에 위젯 D는 전체 너비입니다. 뷰포트 외부에 있어도 위젯 A가 위젯 D의 오른쪽에있는 것을 어떻게 발견 할 수 있습니까?

+0

, 당신은'html' 또는'body' 요소를 이동할 수 있습니다 예를 들어, 다음과 같은 기능을 고려 요소가 뷰포트 내에서 일시적이되도록 왼쪽/오른쪽/위/아래로 이동합니다. 다른 옵션 : 어떤 요소를 비교해야하는지 안다면'$ ('selector') .offset()'('.top'과'.left')과'.height()'/'.outerHeight)'및'.width()'/'.outerWidth()'를 사용하여 요소의 상대 위치를 계산합니다. –

+1

@RobW : 내 문제를 진절머리 나는 모형으로 설명하려고했습니다. –

+0

그래서 어느 요소가 서로 상대적으로 크기를 조정해야하는지 알고 있습니까? –

답변

4

다음 코드는 요소의 경계를 x 및 y 위치의 두 목록에 저장합니다. 그런 다음 for-loop을 사용하여 지정된 오프셋에서 시작하여 목록을 살펴볼 수 있습니다. 대답의 맨 아래에 구현이 표시됩니다.

// These arrays are going to contain many empty elements ;) 
var xAxis = []; 
var yAxis = []; 

// Our storage. Each element looks like: [$element, top, right, bottom, left] 
// Beware of cross-references! Deleted elements cannot be GCed if they're here! 
var allElements = []; 

/* 
* @param $elem jQuery object 
* @returns Object containing the jQuery object and the floored border offsets 
*/ 
function getBorders($elem) { 
    $elem = $elem instanceof jQuery ? $elem.first() : $($elem); 
    var offset = $elem.offset();   // Properties: top, left 

    var width = $elem.outerWidth();  // Includes padding, border. 
    var leftBorder = offset.left;   // Position of the left border ->| 
    var rightBorder = leftBorder + width; // Position of the right border |<- 

    var height = $elem.outerHeight();  // Includes padding, border 
    var topBorder = offset.top;   // Position of the top border _v_ 
    var bottomBorder = offset.top + height;// Position of the bottom border^

    // Turn all numbers in integers, so that they can be used as indexes 
    // for arrays 
    // See also: http://stackoverflow.com/a/8112802/938089 
    return { 
     $elem: $elem, 
     top: ~~topBorder, 
     right: ~~rightBorder, 
     bottom: ~~bottomBorder, 
     left: ~~leftBorder 
    }; 
} 

$('.widget').each(function() { 
    var $this = $(this); 

    var info = getBorders($this); 
    allElements.push(info); 
    // The positions are floored, so that they can be used as a quick reference 
    xAxis[info.left] = xAxis[info.right] = info; 
    yAxis[info.top] = yAxis[info.bottom] = info; 
}); 

생성 된 목록을 사용하여 충돌하는 요소가 있는지 확인할 수 있습니다.

function doesItCollide($elem) { 
    // WeakMaps are useful. For compatibility, I don't use them. 
    var info$elem = getBorders($elem); 
    // info$elem properties: $elem, top, right, bottom, left 
    // Y-oriented 
    for (var y=info$elem.top; y<yAxis.length; y++) { 
     var candidate = yAxis[y]; 
     // Not undefined, and not iself 
     if (candidate && candidate.$elem[0] !== info$elem.$elem[0]) { 
      // Check whether the element is inside the range 
      if (candidate.top >= info$elem.bottom && 
       candidate.bottom >= info$elem.bottom) continue; 
      // It's here, so the top/bottom are possibly in the same range 
      // Check whether the x-positions are also colliding 
      if (candidate.left >= info$elem.left && /* Left within range? */ 
       candidate.left <= info$elem.right || /* OR */ 
       candidate.right <= info$elem.right && /* Right within range? */ 
       candidate.right >= info$elem.left) { 
       return candidate; 
      } 
     } 
    } 
    return null; 
} 

예 (데모 : http://jsfiddle.net/LtJsM/) : 코드가 자주 실행되지 않는 경우

$('.widget').each(function() { 
    var $this = $(this); 
    var overlapping = doesItCollide($this); 
    if (overlapping) { 
     alert('Current element: '+this.className + 
      '\nColliding element: ' + overlapping.$elem[0].className); 
    } 
}); 
+0

고마워요. 조금 조정 해줘야 겠지만 요소 위치 배열은 좋은 생각입니다 .-) –