如何限制范围输入的 requestFrameAnimation?
How to throttle requestFrameAnimation on a range input?
我有一个简单的范围输入,我想每隔几秒return这个值。
我创建了两个回调函数 func
和 step
。我想创建另一个回调函数,每隔 x
秒从 rangeListener
内部调用一次
有什么想法吗?
编辑:根据评论编辑。
class Test{
rangeListener(range, func, step) {
range.addEventListener("change", function () {
func(range.value);
});
let listener = function () {
window.requestAnimationFrame(function () {
step(range.value);
});
};
range.addEventListener("mousedown", function () {
listener();
range.addEventListener("mousemove", listener);
});
range.addEventListener("mouseup", function () {
range.removeEventListener("mousemove", listener);
});
range.addEventListener("keydown", listener);
}
}
let test = new Test();
test.rangeListener(document.querySelector(".range"), (value) => {
document.querySelector(".value").innerHTML = value;
}, (step)=> {
document.querySelector(".step").innerHTML = step;
});
<input type="range" class="range" min="1" max="100" value="1">
<div class="value">0</div>
<div class="step">0</div>
油门部分
限制函数调用的一种简单方法是使用标志(布尔变量)。它是这样工作的:
- 设置标志为
false
- 在您的节流函数中,如果标志设置为
true
,请不要执行任何操作
- 否则,将其设置为
true
并执行您的函数
- 完成后,将标志重置为
false
,以允许以后调用
区间部分
如果您想每 X
秒执行一次函数,最好的选择是使用 setTimeout
或 setInterval
。但是,有多种方法可以做到这一点,并且根据您的使用情况,您可能更喜欢使用其中一种。例如,使用此代码:
setInterval(myFunc, 5000);
您的函数将在执行前等待 5 秒。
如果你希望第一次执行立即发生,你可以这样做(在这里使用 IIFE):
(function myInterval(){
myFunc();
setTimeout(myInterval, 5000);
})();
结果,加上你的代码
我在下面调整了您的代码以合并这些更改:
class Test {
rangeListener(range, options) {
/*
* This flag will be set to true when we are waiting
* for the next AnimationFrame, and back to false
*/
let throttling = false;
let timer;
/*
* Functions
*/
const changeListener = () => {
if (!options.onChange) return;
options.onChange(range.value);
};
const stepListener = () => {
if (!options.onStep || throttling) return;
throttling = true;
window.requestAnimationFrame(() => {
options.onStep(range.value);
throttling = false;
});
};
const intervalFunc = (isInitialization = false) => {
if (!options.onInterval) return;
options.onInterval(range.value);
if (!isInitialization) {
timer = setTimeout(intervalFunc, options.delay || 500);
}
};
/*
* Event listeners
*/
range.addEventListener("change", changeListener);
range.addEventListener("mousedown", () => {
clearTimeout(timer);
intervalFunc();
stepListener();
range.addEventListener("mousemove", stepListener);
});
range.addEventListener("mouseup", () => {
// Execute it once more to get the last value
intervalFunc();
clearTimeout(timer);
range.removeEventListener("mousemove", stepListener);
});
range.addEventListener("keydown", stepListener);
/*
* Values initialization
*/
changeListener();
stepListener();
intervalFunc(true);
}
}
let test = new Test();
const setHTML = (selector, value) => {
document.querySelector(selector).innerHTML = value;
};
test.rangeListener(document.querySelector(".range"), {
onChange: (value) => setHTML(".value", value),
onStep: (value) => setHTML(".step", value),
onInterval: (value) => setHTML(".delayed", value),
delay: 300
});
<input type="range" class="range" min="1" max="100" value="1">
<div>onChange: <span class="value">0</span></div>
<div>onStep: <span class="step">0</span></div>
<div>onInterval: <span class="delayed">0</span></div>
我有一个简单的范围输入,我想每隔几秒return这个值。
我创建了两个回调函数 func
和 step
。我想创建另一个回调函数,每隔 x
秒从 rangeListener
有什么想法吗?
编辑:根据评论编辑。
class Test{
rangeListener(range, func, step) {
range.addEventListener("change", function () {
func(range.value);
});
let listener = function () {
window.requestAnimationFrame(function () {
step(range.value);
});
};
range.addEventListener("mousedown", function () {
listener();
range.addEventListener("mousemove", listener);
});
range.addEventListener("mouseup", function () {
range.removeEventListener("mousemove", listener);
});
range.addEventListener("keydown", listener);
}
}
let test = new Test();
test.rangeListener(document.querySelector(".range"), (value) => {
document.querySelector(".value").innerHTML = value;
}, (step)=> {
document.querySelector(".step").innerHTML = step;
});
<input type="range" class="range" min="1" max="100" value="1">
<div class="value">0</div>
<div class="step">0</div>
油门部分
限制函数调用的一种简单方法是使用标志(布尔变量)。它是这样工作的:
- 设置标志为
false
- 在您的节流函数中,如果标志设置为
true
,请不要执行任何操作
- 否则,将其设置为
true
并执行您的函数 - 完成后,将标志重置为
false
,以允许以后调用
区间部分
如果您想每 X
秒执行一次函数,最好的选择是使用 setTimeout
或 setInterval
。但是,有多种方法可以做到这一点,并且根据您的使用情况,您可能更喜欢使用其中一种。例如,使用此代码:
setInterval(myFunc, 5000);
您的函数将在执行前等待 5 秒。
如果你希望第一次执行立即发生,你可以这样做(在这里使用 IIFE):
(function myInterval(){
myFunc();
setTimeout(myInterval, 5000);
})();
结果,加上你的代码
我在下面调整了您的代码以合并这些更改:
class Test {
rangeListener(range, options) {
/*
* This flag will be set to true when we are waiting
* for the next AnimationFrame, and back to false
*/
let throttling = false;
let timer;
/*
* Functions
*/
const changeListener = () => {
if (!options.onChange) return;
options.onChange(range.value);
};
const stepListener = () => {
if (!options.onStep || throttling) return;
throttling = true;
window.requestAnimationFrame(() => {
options.onStep(range.value);
throttling = false;
});
};
const intervalFunc = (isInitialization = false) => {
if (!options.onInterval) return;
options.onInterval(range.value);
if (!isInitialization) {
timer = setTimeout(intervalFunc, options.delay || 500);
}
};
/*
* Event listeners
*/
range.addEventListener("change", changeListener);
range.addEventListener("mousedown", () => {
clearTimeout(timer);
intervalFunc();
stepListener();
range.addEventListener("mousemove", stepListener);
});
range.addEventListener("mouseup", () => {
// Execute it once more to get the last value
intervalFunc();
clearTimeout(timer);
range.removeEventListener("mousemove", stepListener);
});
range.addEventListener("keydown", stepListener);
/*
* Values initialization
*/
changeListener();
stepListener();
intervalFunc(true);
}
}
let test = new Test();
const setHTML = (selector, value) => {
document.querySelector(selector).innerHTML = value;
};
test.rangeListener(document.querySelector(".range"), {
onChange: (value) => setHTML(".value", value),
onStep: (value) => setHTML(".step", value),
onInterval: (value) => setHTML(".delayed", value),
delay: 300
});
<input type="range" class="range" min="1" max="100" value="1">
<div>onChange: <span class="value">0</span></div>
<div>onStep: <span class="step">0</span></div>
<div>onInterval: <span class="delayed">0</span></div>