diff --git a/App/Resources/Tagger.js b/App/Resources/Tagger.js index ad22b98..cda17dc 100644 --- a/App/Resources/Tagger.js +++ b/App/Resources/Tagger.js @@ -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); } }); })(); -