<html>
<head>
<meta charset="UTF-8">
<title>test</title>
<style type="text/css">
.viewpoint {
margin: 20px auto;
width: 380px;
height: 200px;
border: 1px solid #333;
overflow-y:scroll;
}
.canvas {
height: 20000px;
}
</style>
</head>
<body>
<div class="viewpoint">
<div class="canvas"></div>
</div>
<div class="log"></div>
<script>
var lineHeight = 10;
var data = new Array(2000).fill(0).map((d, i) => ({ v: i }));
var buffer = {
start: 0,
limit: 200/ 10,
domain:[0, 20],
isAmong(value) {
return buffer.domain[0] <= value && value <= buffer.domain[1];
},
preLoad(dir, index) {
if (dir === 0) return false;
var current = ~~(index/ lineHeight), [start, end] = buffer.domain;
// scroll up
if (dir < 0 && current < Math.max(0, start + buffer.limit)) {
end = buffer.isAmong(current) ? start - 1 : current;
start = end - buffer.limit;
buffer.domain = [start, end];
return true;
}
// scroll down
if (dir > 0 && current > end - buffer.limit) {
start = buffer.isAmong(current) ? end + 1 : current;
end = start + buffer.limit;
buffer.domain = [start, end];
return true;
}
return false;
}
};
var scroller = {
dir: 0, // -1,0,-1
preIndex: 0,
on(fn) {
this.fn = function(index) {
log('current', index);
scroller.dir = index - scroller.preIndex;
if (buffer.preLoad(scroller.dir, scroller.preIndex = index)) {
fn(scroller.dir > 0 ? 1 : -1, buffer.domain, index);
}
};
},
fire() {this.fn.apply(this, arguments);}
};
var dataView = {
getRange(start, end) {
return data.slice(start, end);
}
};
document.querySelector('.viewpoint').addEventListener('scroll', function(evt) {
// console.log(this.scrollTop);
scroller.fire(this.scrollTop);
});
scroller.on(function(dir, [start, limit], offsetTop) {
console.log(dir, start, limit, offsetTop);
// console.log(dataView.getRange(start, limit));
});
var $log = document.querySelector('.log');
function log(...args) {
$log.innerHTML = args;
}
</script>
</body>
</html>