I'm trying to implement Vim-like hotkeys for my project; first and foremost, I've decided to realise j and k bindings, so I've wrote this KeyboardEvent
handler:
window.onkeydown = function( event ) {
if (event.code === 'KeyJ')
window.scrollBy({ top: 128, behavior: 'smooth' });
else if (event.code === 'KeyK')
window.scrollBy({ top: -128, behavior: 'smooth' });
};
Seems legit, right? Actually — no: when I holding j or k the scrolling process becomes disjointed and teared (also it's seems like the scroll speed is cutted in a half, like if 64
would be added to scrollTop
instead of 128
).
Can I somehow directly map k to ↑ and j to ↓ using plain JavaScript?
I've tried this solution:
const ArrowUp = new KeyboardEvent( 'keydown', { code: 'ArrowUp' } );
const ArrowDown = new KeyboardEvent( 'keydown', { code: 'ArrowDown' } );
window.onkeydown = function( event ) {
if (event.code === 'KeyJ')
window.dispatchEvent( ArrowDown );
else if (event.code === 'KeyK')
window.dispatchEvent( ArrowUp );
};
But it doesn't work at all, I do not even get any errors .
I have two solutions. This first solution is a bit... let's just say it's not great. You can force it to only listen to the events every so often to prevent the glitchy-ness.
var lastScrollTime = Date.now();
window.onkeydown = function( event ) {
var d = Date.now();
if(d - lastScrollTime < 64){
return;
}
lastScrollTime = d;
if (event.code === 'KeyJ')
window.scrollBy({ top: 128, behavior: 'smooth' });
else if (event.code === 'KeyK')
window.scrollBy({ top: -128, behavior: 'smooth' });
};
My second solution is a bit better by still by no means great. You could implement your own smooth scrolling system.
var scrollTo = 0;
function lerpTo(){
var newPt = lerp(scrollTo, window.scrollY, 1.1);
console.log(newPt);
window.scrollBy(0, window.scrollY - newPt);
}
function lerp(v0, v1, t) {
return v0*(1-t)+v1*t
}
setInterval(lerpTo, 20);
Then with that, all you have to do is change 'scrollTo' whenever you press j or k. Now that code used a lerp function. If you wanted more consistent motion you could change it out for a fixed amount. The big downside to that one is you can no longer scroll normally. To re-add normal scrolling you would have to listen to that event and set scroll to again, however I think that is a bad solution. Alternatively, to add normal scrolling again you could disable the lerp code whenever you scroll manually, then re-enable it whenever someone presses j or k.