JavaScript でキーリピート(ボタンを押し続けている間、そのボタンの処理を連続で実行するような処理)を実現したくて、色々調べたのでメモしておきます。
実はもっと簡単な方法があるかもしれませんが、私は以下のようなコードで実現できました。コピペで動作すると思います。
使うのは addKeyRepeatEventById() 関数だけで、ここにボタンのinput要素のIDと、値を変更する関数を渡せばキーリピートできるようになります。スマホのタッチ操作にも対応するにはイベントの種類を変更する必要があると思いますので、ご注意下さい。
実行結果
コード
<input id="myValue" type="number" value="50" />
<input id="incrementButton" type="button" value="+">
<input id="decrementButton" type="button" value="-">
<script>
// キーリピートの状態を管理するためのクラス
class KeyRepeatHandler {
constructor() {
this._keyRepeatTimeoutId = null;
this.intervalReductionRate = 0.9;
this.startKeyRepeatInterval = 250;
}
startKeyRepeat(incrementFunc) {
this.__startKeyRepeat(incrementFunc, this.startKeyRepeatInterval);
}
__startKeyRepeat(incrementFunc, interval) {
incrementFunc();
this._keyRepeatTimeoutId = setTimeout(() => {
this.__startKeyRepeat(incrementFunc, interval * this.intervalReductionRate);
}, interval);
}
stopKeyRepeat() {
clearTimeout(this._keyRepeatTimeoutId);
}
}
let g_keyRepeatHandler = new KeyRepeatHandler();
function addMultipleEventListener(element, events, handler) {
for (let e of events) {
element.addEventListener(e, handler);
}
}
function addKeyRepeatEvent(elem, changeValueFunc) {
// スマホのタッチ操作に対応するにはイベントを変更する必要あると思う
addMultipleEventListener(elem, ['mousedown', 'mouseup', 'mouseleave'], (e) => {
if (e.type == "mousedown") {
g_keyRepeatHandler.startKeyRepeat(changeValueFunc);
} else {
g_keyRepeatHandler.stopKeyRepeat();
}
});
}
// 指定したIDのボタンにキーリピートのイベントを登録する関数
function addKeyRepeatEventById(elemId, changeValueFunc) {
let elem = document.getElementById(elemId);
addKeyRepeatEvent(elem, changeValueFunc);
}
// 各ボタンにキーリピートのイベントを登録
addKeyRepeatEventById("incrementButton", () => {
let elem = document.getElementById("myValue");
elem.value = Number(elem.value) + 1;
});
addKeyRepeatEventById("decrementButton", () => {
let elem = document.getElementById("myValue");
elem.value = Number(elem.value) - 1;
});
</script>