Reader: j/k-Scrollen ohne Ramp-up, an feste Kadenz statt Display-Hz gekoppelt (SW v34)
Die requestAnimationFrame-Schleife aus dem letzten Fix lief mit der tatsächlichen Bildwiederholrate des Displays statt einer festen Rate — auf Laptops mit 120/144/165Hz-Panels bedeutete das 2-3x mehr scrollBy-Aufrufe (und damit Scroll-Listener-Durchläufe) pro Sekunde als beabsichtigt, was sich als Lag statt als Beschleunigung äußerte. Zurück zu setInterval, aber mit fester 20ms-Kadenz unabhängig vom Display und dt-kompensierter, konstanter Geschwindigkeit (~1200px/s, kein Ramp-up mehr). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
e70bb881cc
commit
5053d0036a
2 changed files with 20 additions and 23 deletions
|
|
@ -2240,13 +2240,10 @@ document.addEventListener('keydown', e => {
|
||||||
const continuousKeys = {'j': 1, 'k': -1};
|
const continuousKeys = {'j': 1, 'k': -1};
|
||||||
if (continuousKeys[e.key] !== undefined && !e.repeat) {
|
if (continuousKeys[e.key] !== undefined && !e.repeat) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const dir = continuousKeys[e.key];
|
_readerScrollDir = continuousKeys[e.key];
|
||||||
const now = performance.now();
|
if (!_readerScrollInterval) {
|
||||||
if (_readerScrollDir !== dir) _readerScrollStartTs = now;
|
_readerScrollLastTs = performance.now();
|
||||||
_readerScrollDir = dir;
|
_readerScrollInterval = setInterval(_readerScrollTick, READER_SCROLL_TICK_MS);
|
||||||
_readerScrollLastTs = now;
|
|
||||||
if (!_readerScrollRaf) {
|
|
||||||
_readerScrollRaf = requestAnimationFrame(_readerScrollTick);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.key === 'd') { e.preventDefault(); contentEl.scrollBy({top: large / 2, behavior: 'smooth'}); }
|
if (e.key === 'd') { e.preventDefault(); contentEl.scrollBy({top: large / 2, behavior: 'smooth'}); }
|
||||||
|
|
@ -2266,8 +2263,8 @@ document.addEventListener('keydown', e => {
|
||||||
|
|
||||||
document.addEventListener('keyup', e => {
|
document.addEventListener('keyup', e => {
|
||||||
if (e.key === 'j' || e.key === 'k') {
|
if (e.key === 'j' || e.key === 'k') {
|
||||||
if (_readerScrollRaf) cancelAnimationFrame(_readerScrollRaf);
|
clearInterval(_readerScrollInterval);
|
||||||
_readerScrollRaf = null;
|
_readerScrollInterval = null;
|
||||||
_readerScrollDir = 0;
|
_readerScrollDir = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -3189,21 +3186,21 @@ let pdfTotalPages = 0;
|
||||||
let _pdfPageTextBoxCache = {};
|
let _pdfPageTextBoxCache = {};
|
||||||
let _pdfRenderGen = 0;
|
let _pdfRenderGen = 0;
|
||||||
let _touchStartX = 0;
|
let _touchStartX = 0;
|
||||||
let _readerScrollRaf = null;
|
let _readerScrollInterval = null;
|
||||||
let _readerScrollDir = 0;
|
let _readerScrollDir = 0;
|
||||||
let _readerScrollStartTs = 0;
|
|
||||||
let _readerScrollLastTs = 0;
|
let _readerScrollLastTs = 0;
|
||||||
const READER_SCROLL_MIN_SPEED = 700; // px/s right as j/k is pressed
|
const READER_SCROLL_SPEED = 1200; // constant px/s, no ramp-up
|
||||||
const READER_SCROLL_MAX_SPEED = 1800; // px/s once ramped up
|
const READER_SCROLL_TICK_MS = 20; // fixed cadence, independent of the
|
||||||
const READER_SCROLL_RAMP_MS = 300; // time to reach max speed
|
// display's refresh rate — rAF runs at
|
||||||
function _readerScrollTick(ts) {
|
// that rate (120/144/165Hz on plenty of
|
||||||
const dt = ts - _readerScrollLastTs;
|
// laptops), which was driving 2-3x more
|
||||||
_readerScrollLastTs = ts;
|
// scrollBy + scroll-listener work per
|
||||||
const held = ts - _readerScrollStartTs;
|
// second than intended and read as lag.
|
||||||
const t = Math.min(held / READER_SCROLL_RAMP_MS, 1);
|
function _readerScrollTick() {
|
||||||
const speed = READER_SCROLL_MIN_SPEED + (READER_SCROLL_MAX_SPEED - READER_SCROLL_MIN_SPEED) * t;
|
const now = performance.now();
|
||||||
$('reader-content')?.scrollBy({top: _readerScrollDir * speed * dt / 1000});
|
const dt = now - _readerScrollLastTs;
|
||||||
_readerScrollRaf = requestAnimationFrame(_readerScrollTick);
|
_readerScrollLastTs = now;
|
||||||
|
$('reader-content')?.scrollBy({top: Math.round(_readerScrollDir * READER_SCROLL_SPEED * dt / 1000)});
|
||||||
}
|
}
|
||||||
let _pinchStartDist = 0;
|
let _pinchStartDist = 0;
|
||||||
let _pinchStartZoom = 100;
|
let _pinchStartZoom = 100;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* diora service worker — caches the app shell for offline use.
|
* diora service worker — caches the app shell for offline use.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CACHE = 'diora-v33';
|
const CACHE = 'diora-v34';
|
||||||
const PODCAST_CACHE = 'diora-podcast-v1';
|
const PODCAST_CACHE = 'diora-podcast-v1';
|
||||||
const SHELL = [
|
const SHELL = [
|
||||||
'/static/css/app.css',
|
'/static/css/app.css',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue