// 10/31/2017
const SmoothScroll /** @class */ = (() => {
class SmoothScroll {
constructor({target, scrollEase, maxOffset}) {
const _this = this;
this.endThreshold = 0.05;
this.requestId = null;
this.maxDepth = 10;
this.viewHeight = 0;
this.halfViewHeight = 0;
this.maxDistance = 0;
this.scrollHeight = 0;
this.endScroll = 0;
this.currentScroll = 0;
this.resizeRequest = 1;
this.scrollRequest = 0;
this.scrollItems = [];
this.lastTime = -1;
this.maxElapsedMS = 100;
this.targetFPMS = 0.06;
this._onResize = event => {
_this.resizeRequest++;
if (!_this.requestId) {
_this.lastTime = performance.now();
_this.requestId = requestAnimationFrame(_this._update);
}
};
this._onScroll = event => {
_this.scrollRequest++;
if (!_this.requestId) {
_this.lastTime = performance.now();
_this.requestId = requestAnimationFrame(_this._update);
}
};
this._update = currentTime => {
if (currentTime === void 0) { currentTime = performance.now(); }
let elapsedMS = currentTime - _this.lastTime;
if (elapsedMS > _this.maxElapsedMS) {
elapsedMS = _this.maxElapsedMS;
}
const deltaTime = elapsedMS * _this.targetFPMS;
const dt = 1 - (1 - _this.scrollEase) ** deltaTime;
const resized = _this.resizeRequest > 0;
const scrollY = window.pageYOffset;
if (resized) {
const height = _this.target.clientHeight;
document.body.style.height = `${height}px`;
_this.scrollHeight = height;
_this.viewHeight = window.innerHeight;
_this.halfViewHeight = _this.viewHeight / 2;
_this.maxDistance = _this.viewHeight * 2;
_this.resizeRequest = 0;
}
_this.endScroll = scrollY;
// this.currentScroll += (scrollY - this.currentScroll) * this.scrollEase;
_this.currentScroll += (scrollY - _this.currentScroll) * dt;
if (Math.abs(scrollY - _this.currentScroll) < _this.endThreshold || resized) {
_this.currentScroll = scrollY;
_this.scrollRequest = 0;
}
// const scrollOrigin = scrollY + this.halfViewHeight;
const scrollOrigin = _this.currentScroll + _this.halfViewHeight;
_this.target.style.transform = `translate3d(0px,-${_this.currentScroll}px,0px)`;
for (let i = 0; i < _this.scrollItems.length; i++) {
const item = _this.scrollItems[i];
const distance = scrollOrigin - item.top;
const offsetRatio = distance / _this.maxDistance;
item.endOffset = Math.round(_this.maxOffset * item.depthRatio * offsetRatio);
if (Math.abs(item.endOffset - item.currentOffset < _this.endThreshold)) {
item.currentOffset = item.endOffset;
}
else {
// item.currentOffset += (item.endOffset - item.currentOffset) * this.scrollEase;
item.currentOffset += (item.endOffset - item.currentOffset) * dt;
}
item.target.style.transform = `translate3d(0px,-${item.currentOffset}px,0px)`;
}
_this.lastTime = currentTime;
_this.requestId = _this.scrollRequest > 0 ? requestAnimationFrame(_this._update) : null;
};
this.target = target;
this.scrollEase = scrollEase != null ? scrollEase : 0.1;
this.maxOffset = maxOffset != null ? maxOffset : 500;
this.addItems();
window.addEventListener("resize", this._onResize);
window.addEventListener("scroll", this._onScroll);
this._update();
}
addItems() {
this.scrollItems = [];
const elements = document.querySelectorAll("*[data-depth]");
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const depth = +element.getAttribute("data-depth");
const rect = element.getBoundingClientRect();
const item = {
target: element,
depth,
top: rect.top + window.pageYOffset,
depthRatio: depth / this.maxDepth,
currentOffset: 0,
endOffset: 0
};
this.scrollItems.push(item);
}
return this;
}
}
return SmoothScroll;
})();