문서가 아닌 뷰포트를 기준으로 페이지에서 요소의 위치를 가져 오는 올바른 방법은 무엇입니까? 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
모든 곳에서 지원됩니다.
답변
다음은 (비대해진) 차원 플러그인을 사용하지 않고 페이지 높이와 스크롤 양 (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에서 테스트 및 작동했습니다. 거의 확실하게 이전 버전에서 작동합니다.