문서가 아닌 뷰포트를 기준으로 페이지에서 요소의 위치를 가져 오는 올바른 방법은 무엇입니까? jQuery.offset
기능이 유망 해 보였습니다.
문서를 기준으로 첫 번째 요소의 현재 좌표를 가져 오거나 일치하는 요소 집합에서 모든 요소의 좌표를 설정합니다.
그러나 그것은 문서와 관련이 있습니다. 뷰포트에 상대적인 오프셋을 반환하는 동등한 메서드가 있습니까?
문서가 아닌 뷰포트를 기준으로 페이지에서 요소의 위치를 가져 오는 올바른 방법은 무엇입니까? jQuery.offset
기능이 유망 해 보였습니다.
문서를 기준으로 첫 번째 요소의 현재 좌표를 가져 오거나 일치하는 요소 집합에서 모든 요소의 좌표를 설정합니다.
그러나 그것은 문서와 관련이 있습니다. 뷰포트에 상대적인 오프셋을 반환하는 동등한 메서드가 있습니까?
답변:
Dimensions 플러그인, 특히 scrollTop()
/를 살펴보십시오 scrollLeft()
. 정보는 http://api.jquery.com/scrollTop 에서 찾을 수 있습니다 .
요소의 크기와 위치를 결정하는 가장 쉬운 방법은 getBoundingClientRect () 메서드 를 호출하는 것입니다. 이 메서드는 뷰포트 좌표의 요소 위치를 반환합니다. 인수가 필요하지 않으며 left, right, top 및 bottom 속성이있는 객체를 반환합니다 . left 및 top 속성은 요소의 왼쪽 상단 모서리의 X 및 Y 좌표를 제공하고 right 및 bottom 속성은 오른쪽 하단 모서리의 좌표를 제공합니다.
element.getBoundingClientRect(); // Get position in viewport coordinates
모든 곳에서 지원됩니다.
getBoundingClientRect is not a function
$('#myElement')[0].getBoundingClientRect().top
(또는 다른 위치)
다음은 (비대해진) 차원 플러그인을 사용하지 않고 페이지 높이와 스크롤 양 (x, y)을 가져 오는 두 가지 함수입니다.
// getPageScroll() by quirksmode.com
function getPageScroll() {
var xScroll, yScroll;
if (self.pageYOffset) {
yScroll = self.pageYOffset;
xScroll = self.pageXOffset;
} else if (document.documentElement && document.documentElement.scrollTop) {
yScroll = document.documentElement.scrollTop;
xScroll = document.documentElement.scrollLeft;
} else if (document.body) {// all other Explorers
yScroll = document.body.scrollTop;
xScroll = document.body.scrollLeft;
}
return new Array(xScroll,yScroll)
}
// Adapted from getPageSize() by quirksmode.com
function getPageHeight() {
var windowHeight
if (self.innerHeight) { // all except Explorer
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) {
windowHeight = document.documentElement.clientHeight;
} else if (document.body) { // other Explorers
windowHeight = document.body.clientHeight;
}
return windowHeight
}
jQuery.offset
요구와 결합 할 수 scrollTop
및 scrollLeft
이 도면에 도시 된 바와 같이
데모:
function getViewportOffset($e) {
var $window = $(window),
scrollLeft = $window.scrollLeft(),
scrollTop = $window.scrollTop(),
offset = $e.offset(),
rect1 = { x1: scrollLeft, y1: scrollTop, x2: scrollLeft + $window.width(), y2: scrollTop + $window.height() },
rect2 = { x1: offset.left, y1: offset.top, x2: offset.left + $e.width(), y2: offset.top + $e.height() };
return {
left: offset.left - scrollLeft,
top: offset.top - scrollTop,
insideViewport: rect1.x1 < rect2.x2 && rect1.x2 > rect2.x1 && rect1.y1 < rect2.y2 && rect1.y2 > rect2.y1
};
}
$(window).on("load scroll resize", function() {
var viewportOffset = getViewportOffset($("#element"));
$("#log").text("left: " + viewportOffset.left + ", top: " + viewportOffset.top + ", insideViewport: " + viewportOffset.insideViewport);
});
body { margin: 0; padding: 0; width: 1600px; height: 2048px; background-color: #CCCCCC; }
#element { width: 384px; height: 384px; margin-top: 1088px; margin-left: 768px; background-color: #99CCFF; }
#log { position: fixed; left: 0; top: 0; font: medium monospace; background-color: #EEE8AA; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- scroll right and bottom to locate the blue square -->
<div id="element"></div>
<div id="log"></div>
다음은 뷰포트 내 요소의 현재 위치를 계산하는 함수입니다.
/**
* Calculates the position of a given element within the viewport
*
* @param {string} obj jQuery object of the dom element to be monitored
* @return {array} An array containing both X and Y positions as a number
* ranging from 0 (under/right of viewport) to 1 (above/left of viewport)
*/
function visibility(obj) {
var winw = jQuery(window).width(), winh = jQuery(window).height(),
elw = obj.width(), elh = obj.height(),
o = obj[0].getBoundingClientRect(),
x1 = o.left - winw, x2 = o.left + elw,
y1 = o.top - winh, y2 = o.top + elh;
return [
Math.max(0, Math.min((0 - x1) / (x2 - x1), 1)),
Math.max(0, Math.min((0 - y1) / (y2 - y1), 1))
];
}
반환 값은 다음과 같이 계산됩니다.
용법:
visibility($('#example')); // returns [0.3742887830933581, 0.6103752759381899]
데모:
function visibility(obj) {var winw = jQuery(window).width(),winh = jQuery(window).height(),elw = obj.width(),
elh = obj.height(), o = obj[0].getBoundingClientRect(),x1 = o.left - winw, x2 = o.left + elw, y1 = o.top - winh, y2 = o.top + elh; return [Math.max(0, Math.min((0 - x1) / (x2 - x1), 1)),Math.max(0, Math.min((0 - y1) / (y2 - y1), 1))];
}
setInterval(function() {
res = visibility($('#block'));
$('#x').text(Math.round(res[0] * 100) + '%');
$('#y').text(Math.round(res[1] * 100) + '%');
}, 100);
#block { width: 100px; height: 100px; border: 1px solid red; background: yellow; top: 50%; left: 50%; position: relative;
} #container { background: #EFF0F1; height: 950px; width: 1800px; margin-top: -40%; margin-left: -40%; overflow: scroll; position: relative;
} #res { position: fixed; top: 0; z-index: 2; font-family: Verdana; background: #c0c0c0; line-height: .1em; padding: 0 .5em; font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="res">
<p>X: <span id="x"></span></p>
<p>Y: <span id="y"></span></p>
</div>
<div id="container"><div id="block"></div></div>
cballou의 답변은 2014 년 1 월 현재 Firefox에서 더 이상 작동하지 않는다는 것을 발견했습니다. 특히 if (self.pageYOffset)
클라이언트가 오른쪽으로 스크롤 한 경우 트리거되지 않았지만 아래로 스크롤되지 않았습니다 0
. 이는 잘못된 숫자 이기 때문 입니다. Firefox가 document.body.scrollLeft
/를 지원했기 때문에 잠시 동안 감지되지 Top
않았지만 더 이상 작동하지 않습니다 (Firefox 26.0에서).
내 수정 된 솔루션은 다음과 같습니다.
var getPageScroll = function(document_el, window_el) {
var xScroll = 0, yScroll = 0;
if (window_el.pageYOffset !== undefined) {
yScroll = window_el.pageYOffset;
xScroll = window_el.pageXOffset;
} else if (document_el.documentElement !== undefined && document_el.documentElement.scrollTop) {
yScroll = document_el.documentElement.scrollTop;
xScroll = document_el.documentElement.scrollLeft;
} else if (document_el.body !== undefined) {// all other Explorers
yScroll = document_el.body.scrollTop;
xScroll = document_el.body.scrollLeft;
}
return [xScroll,yScroll];
};
FF26, Chrome 31, IE11에서 테스트 및 작동했습니다. 거의 확실하게 이전 버전에서 작동합니다.