Scroller.js: improvements to scrolling by keyboard

This commit is contained in:
James Magahern
2022-06-03 13:04:00 -07:00
parent ab2ff98f37
commit ebc6f4ad6a

View File

@@ -162,31 +162,55 @@ class Scroller
constructor() {
this.modelPositionY = 0;
this.modelPositionX = 0;
this.modelPositionXVel = 0;
this.modelPositionYVel = 0;
}
scrollBy(xOffset, yOffset) {
var initialPositionY = this.modelPositionY;
var initialPositionX = this.modelPositionX;
clampHorizontal(xOffset) {
return Math.max(
0, Math.min(
xOffset, document.documentElement.scrollWidth - window.visualViewport.width
)
);
}
clampVertical(yOffset) {
return Math.max(
0, Math.min(
yOffset, document.documentElement.scrollHeight - window.visualViewport.height
)
);
}
initializeModelPosition() {
if (this.timerIdentifier == undefined) {
this.startTimer();
initialPositionY = window.scrollY;
initialPositionX = window.scrollX;
this.modelPositionY = window.scrollY;
this.modelPositionX = window.scrollX;
}
}
this.modelPositionY = initialPositionY + yOffset;
this.modelPositionY = Math.max(
0, Math.min(
this.modelPositionY, document.documentElement.scrollHeight - window.visualViewport.height
)
);
scrollBy(xOffset, yOffset) {
this.initializeModelPosition();
this.modelPositionX = initialPositionX + xOffset;
this.modelPositionX = Math.max(
0, Math.min(
this.modelPositionX, document.documentElement.scrollWidth - window.visualViewport.width
)
);
this.modelPositionY += yOffset;
this.modelPositionY = this.clampVertical(this.modelPositionY);
this.modelPositionX += xOffset;
this.modelPositionX = this.clampHorizontal(this.modelPositionX);
}
setScrollVelocity(xVelocity, yVelocity) {
this.initializeModelPosition();
this.modelPositionXVel = xVelocity;
this.modelPositionYVel = yVelocity;
if (this.timerIdentifier == undefined) {
this.startTimer();
}
}
startTimer() {
@@ -199,17 +223,29 @@ class Scroller
}
updateTimer(self) {
self.modelPositionX = self.clampHorizontal(self.modelPositionX + self.modelPositionXVel);
self.modelPositionY = self.clampVertical(self.modelPositionY + self.modelPositionYVel);
const accelerationFactor = 0.05;
let positionOffsetY = (self.modelPositionY - window.scrollY) * accelerationFactor;
let positionOffsetX = (self.modelPositionX - window.scrollX) * accelerationFactor;
window.scrollBy(positionOffsetX, positionOffsetY);
if (Math.abs(positionOffsetX) <= 1.0 && Math.abs(positionOffsetY) <= 1.0) {
var atRest = Math.abs(positionOffsetX) <= 1.0 && Math.abs(positionOffsetY) <= 1.0;
var noVelocity = self.modelPositionXVel == 0 && self.modelPositionYVel == 0;
if (atRest && noVelocity) {
self.stopTimer();
}
}
}
const ScrollDirection = {
Up: 'k',
Down: 'j',
Left: 'h',
Right: 'l',
};
(function() {
let tagger = new ElementTagger();
let scroller = new Scroller();
@@ -240,20 +276,25 @@ class Scroller
tagger.clickLinkWithTag(keyName);
tagger.untagDocument();
}
} else {
} else if (event.shiftKey) {
// Otherwise, interpret as a single character command
let lowerKey = keyName.toLowerCase();
let scrollAmount = event.shiftKey ? window.visualViewport.height : 30;
if (lowerKey == 'j') {
scroller.scrollBy(0, scrollAmount);
} else if (lowerKey == 'k') {
scroller.scrollBy(0, -scrollAmount);
} else if (lowerKey == 'h') {
scroller.scrollBy(-scrollAmount, 0);
} else if (lowerKey == 'l') {
scroller.scrollBy(scrollAmount, 0);
switch (lowerKey) {
case ScrollDirection.Down:
scroller.scrollBy(0, scrollAmount);
break;
case ScrollDirection.Up:
scroller.scrollBy(0, -scrollAmount);
break;
case ScrollDirection.Left:
scroller.scrollBy(-scrollAmount, 0);
break;
case ScrollDirection.Right:
scroller.scrollBy(scrollAmount, 0);
break;
}
}
});
@@ -268,6 +309,24 @@ class Scroller
tagger.tagDocument();
}
event.preventDefault();
} else {
let lowerKey = event.key.toLowerCase();
let velocity = 5;
switch (lowerKey) {
case ScrollDirection.Down:
scroller.setScrollVelocity(0, velocity);
break;
case ScrollDirection.Up:
scroller.setScrollVelocity(0, -velocity);
break;
case ScrollDirection.Left:
scroller.setScrollVelocity(-velocity, 0);
break;
case ScrollDirection.Right:
scroller.setScrollVelocity(velocity, 0);
break;
}
}
});
@@ -279,8 +338,9 @@ class Scroller
if (event.key == " " && tagger.isTagged) {
tagger.untagDocument();
event.preventDefault();
} else {
scroller.setScrollVelocity(0, 0);
}
});
})();