JSFiddle - React, Tailwind, and code Playground
HTML
<div id="viewport">
<div id="content"></div>
</div>
<div id="debug"></div>
CSS
#debug {
margin-left: 400px;
width: 200px;
background: beige;
font-size: 9pt;
opacity: 0.5;
border: 1px solid gray;
padding: 10px;
}
#viewport {
float: left;
border: 1px solid black;
overflow: auto;
width: 350px;
}
#content {
position: relative;
overflow: hidden;
}
.row {
position: absolute;
left: 0px;
width: 100%;
border-bottom: 1px dotted blue;
font-size: 9pt;
}
.row:hover {
background: rgba(0,0,255,0.05);
}
JavaScript
/*
가상 재화면 구성 과정은 아래와 같다:
1
--------
-------2-
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
--------
==================================================
[=] - 실제 스크롤 가능 높이 (h)
[-] - "페이지"; 모든 (n) 페이지의 총 높이는 (총 높이th) = (페이지 높이 ph) * (페이지 n)
페이지 사이 겹치는 부분 (cj) 과 스크롤바 길이
스크롤 높이에 따른 페이지 전환시점에 넘어갈 것이다.
부드럽게 유지하기 위해 (n) 과 (cj) 를 최소화해야 한다.
(ph) 를 (h) 값의 1/100 으로 설정해야 좋은 시발점이 된다.
*/
var th = 1000000000; // 가상 높이
var h = 1000000; // 실제 스크롤 가능 높이
var ph = h / 100; // 페이지 높이
var n = Math.ceil(th / ph); // 페이지 개수
var vp = 400; // 보이는 부분 높이
var rh = 50; // 행 높이
var cj = (th - h) / (n - 1); // "넘어가는" 계수
var page = 0; // 현재 페이지
var offset=0; // 현재 페이지 위치
var prevScrollTop = 0;
var rows = {}; // 캐시된 행 노드
var viewport, content;
$(function() {
viewport = $("#viewport");
content = $("#content");
viewport.css("height",vp);
content.css("height",h);
viewport.scroll(onScroll);
viewport.trigger("scroll");
});
function onScroll() {
var scrollTop = viewport.scrollTop();
if (Math.abs(scrollTop-prevScrollTop) > vp)
onJump();
else
onNearScroll();
renderViewport();
logDebugInfo();
}
function onNearScroll() {
var scrollTop = viewport.scrollTop();
// 다음 페이지
if (scrollTop + offset > (page+1)*ph) {
page++;
offset = Math.round(page * cj);
viewport.scrollTop(prevScrollTop = scrollTop - cj);
removeAllRows();
}
// 이전 페이지
else if (scrollTop...