使用鼠标向下 JavaScript 连续增加或减少值



我从这里复制了一些代码。

当值达到minFontSizemaxFontSize时,以下代码会出现一些错误。

我不知道如何解决这个问题...

const decreaseFontSizeBtn = document.querySelector(".fontsize-via-btn #decrease");
const increaseFontSizeBtn = document.querySelector(".fontsize-via-btn #increase");
const fontSizeDisplay = document.querySelector(".fontsize-via-btn .current-fontsize");
const defaultFontSize = 20;
const minFontSize = 16;
const maxFontSize = 40;
let currentFontSize = defaultFontSize;
var timeout, interval;
[decreaseFontSizeBtn, increaseFontSizeBtn].forEach(btn => {
btn.addEventListener("mousedown", () => {
if (btn.id === "decrease") {
decreaseFontSize();
hold(decreaseFontSize);
}
if (btn.id === "increase") {
increaseFontSize();
hold(increaseFontSize);
}
saveFontSize();
})
btn.addEventListener("mouseup", clearTimers);
btn.addEventListener("mouseleave", clearTimers);
function clearTimers() {
clearTimeout(timeout);
clearInterval(interval);
}
})
function hold(func) {
timeout = setTimeout(() => {
interval = setInterval(() => {
func();
saveFontSize();
}, 50)
}, 300)
}
function decreaseFontSize() {
if (currentFontSize > minFontSize) {
currentFontSize -= 2;
}
if (currentFontSize === minFontSize) {
decreaseFontSizeBtn.disabled = true;
} else {
increaseFontSizeBtn.disabled = false;
}
}
function increaseFontSize() {
if (currentFontSize < maxFontSize) {
currentFontSize += 2;
}
if (currentFontSize === maxFontSize) {
increaseFontSizeBtn.disabled = true;
} else {
decreaseFontSizeBtn.disabled = false;
}
}
function saveFontSize() {
fontSizeDisplay.textContent = currentFontSize;
// localStorage ...
}
.fontsize-via-btn {
width: 100px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
font-size: 2rem;
}
<div class="fontsize-via-btn">
<button id="decrease">A-</button>
<div class="current-fontsize">20</div>
<button id="increase">A+</button>
</div>

当您达到最小值或最大值时,不会清除计时器,因为(如@timmmmmb所述)禁用的按钮不会触发鼠标事件。因此,当您尝试朝另一个方向前进时,将再次执行原始计时器。

最简单的可能是,当你达到范围的尽头时也调用clearTimers

const decreaseFontSizeBtn = document.querySelector(".fontsize-via-btn #decrease");
const increaseFontSizeBtn = document.querySelector(".fontsize-via-btn #increase");
const fontSizeDisplay = document.querySelector(".fontsize-via-btn .current-fontsize");
const defaultFontSize = 20;
const minFontSize = 16;
const maxFontSize = 40;
let currentFontSize = defaultFontSize;
var timeout, interval;
function clearTimers() {
clearTimeout(timeout);
clearInterval(interval);
}
[decreaseFontSizeBtn, increaseFontSizeBtn].forEach(btn => {
btn.addEventListener("mousedown", () => {
if (btn.id === "decrease") {
decreaseFontSize();
hold(decreaseFontSize);
}
if (btn.id === "increase") {
increaseFontSize();
hold(increaseFontSize);
}
saveFontSize();
})
btn.addEventListener("mouseup", clearTimers);
btn.addEventListener("mouseleave", clearTimers);
})
function hold(func) {
timeout = setTimeout(() => {
interval = setInterval(() => {
func();
saveFontSize();
}, 50)
}, 300)
}
function decreaseFontSize() {
if (currentFontSize > minFontSize) {
currentFontSize -= 2;
}
if (currentFontSize === minFontSize) {
decreaseFontSizeBtn.disabled = true;
clearTimers();
} else {
increaseFontSizeBtn.disabled = false;
}
}
function increaseFontSize() {
if (currentFontSize < maxFontSize) {
currentFontSize += 2;
}
if (currentFontSize === maxFontSize) {
clearTimers();
increaseFontSizeBtn.disabled = true;
} else {
decreaseFontSizeBtn.disabled = false;
}
}
function saveFontSize() {
fontSizeDisplay.textContent = currentFontSize;
// localStorage ...
}
.fontsize-via-btn {
width: 100px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
font-size: 2rem;
}
<div class="fontsize-via-btn">
<button id="decrease">A-</button>
<div class="current-fontsize">20</div>
<button id="increase">A+</button>
</div>

我认为问题是,当您达到最大字体大小时,您会禁用该按钮,这意味着您的鼠标向上事件不会被触发。我将鼠标向上事件从按钮移到容器上,我认为它现在可以工作了。

const decreaseFontSizeBtn = document.querySelector(".fontsize-via-btn #decrease");
const increaseFontSizeBtn = document.querySelector(".fontsize-via-btn #increase");
const fontSizeDisplay = document.querySelector(".fontsize-via-btn .current-fontsize");
const fontSizeContainer = document.querySelector(".fontsize-via-btn");
const defaultFontSize = 20;
const minFontSize = 16;
const maxFontSize = 40;
let currentFontSize = defaultFontSize;
var timeout, interval;

fontSizeContainer.addEventListener("mouseup", clearTimers);
fontSizeContainer.addEventListener("mouseleave", clearTimers);
function clearTimers() {
clearTimeout(timeout);
clearInterval(interval);
}
[decreaseFontSizeBtn, increaseFontSizeBtn].forEach(btn => {
btn.addEventListener("mousedown", () => {
if (btn.id === "decrease") {
decreaseFontSize();
hold(decreaseFontSize);
}
if (btn.id === "increase") {
increaseFontSize();
hold(increaseFontSize);
}
saveFontSize();
})
})
function hold(func) {
timeout = setTimeout(() => {
interval = setInterval(() => {
func();
saveFontSize();
}, 50)
}, 300)
}
function decreaseFontSize() {
if (currentFontSize > minFontSize) {
currentFontSize -= 2;
}
if (currentFontSize === minFontSize) {
decreaseFontSizeBtn.disabled = true;
} else {
increaseFontSizeBtn.disabled = false;
}
}
function increaseFontSize() {
if (currentFontSize < maxFontSize) {
currentFontSize += 2;
}
if (currentFontSize === maxFontSize) {
increaseFontSizeBtn.disabled = true;
} else {
decreaseFontSizeBtn.disabled = false;
}
}
function saveFontSize() {
fontSizeDisplay.textContent = currentFontSize;
// localStorage ...
}
.fontsize-via-btn {
width: 100px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
font-size: 2rem;
}
<div class="fontsize-via-btn">
<button id="decrease">A-</button>
<div class="current-fontsize">20</div>
<button id="increase">A+</button>
</div>

差异

需要在每个按钮上注册"mouseup"和"mouseleave",或者必须将事件委托给按钮。现在,鼠标事件仅影响没有任何功能触发的<div>。所以这就是按钮卡住的原因 - 即使在用户释放鼠标按钮之后,它们也会不断重复。

下面的示例为每个按钮提供了单独的事件处理程序。通常我更喜欢使用一个事件处理程序来控制所有内容 事件委托,但由于需要使用setclearInterval()作为事件处理程序,事件对象会丢失。我可以用闭包来解决这个问题,但是你的代码足够接近,以至于你的恩尼弗特不会发生根本性的改变。

使用此版本省略了使用localStorage保存(我知道这不是问题的一部分),因为该站点阻止使用它。我写了另一个版本来保存当前的字体大小并加载它,以审查这个Plunker

const io = document.forms.UI.elements;
let current = 1.5;
let repeatInc = null;
let repeatDec = null;
function holdInc(e) {
if (repeatInc === null) {
repeatInc = setInterval(incFontSize, 100);
}
};
function releaseInc(e) {
if (repeatInc != null) {
clearInterval(repeatInc);
repeatInc = null;
}
};
function incFontSize() {
const io = document.forms.UI.elements;
const max = 4;
if (current < max) {
current += 0.25;
io.dec.disabled = false;
}
if (current == max) {
io.inc.disabled = true;
releaseInc();
}
io.fSize.value = current.toFixed(2);
io.text.style.fontSize = `${current}rem`
};
function holdDec(e) {
if (repeatDec == null) {
repeatDec = setInterval(decFontSize, 100);
}
};
function releaseDec(e) {
if (repeatDec != null) {
clearInterval(repeatDec);
repeatDec = null;
}
};
function decFontSize() {
const io = document.forms.UI.elements;
const min = 1;
if (current > min) {
current -= 0.25;
io.inc.disabled = false;
}
if (current == min) {
io.dec.disabled = true;
releaseDec()
}
io.fSize.value = current.toFixed(2);
io.text.style.fontSize = `${current}rem`
};
io.inc.addEventListener('mousedown', holdInc);
io.inc.addEventListener('mouseup', releaseInc);
io.inc.addEventListener('mousemove', releaseInc);
io.dec.addEventListener('mousedown', holdDec);
io.dec.addEventListener('mouseup', releaseDec);
io.dec.addEventListener('mouseleave', releaseDec);
:root {
font: 2ch/1 'Segoe UI'
}
body {
font-size: 1ch;
}
.ctrl {
display: flex;
align-items: center;
justify-content: flex-start;
font-size: 1rem;
padding: 5px;
}
#fSize {
display: block;
width: 5ch;
margin: 0 4px;
font-family: Consolas;
text-align: center;
}
button {
display: block;
width: max-content;
font: inherit;
cursor: pointer;
}
label {
display: block;
width: max-content;
margin: 0 8px;
font-size: 1rem;
}
.text {
min-height: 50px;
font-size: 1.25rem;
}
<form id='UI'>
<fieldset name='ctrl' class='ctrl'>
<button id="dec" type='button'>&#128475;-</button>
<output id="fSize">1.50</output>
<button id="inc" type='button'>&#128474;+</button>
<label>Scale: 1ch => 1rem</label>
</fieldset>
<fieldset name='text' class='text' contenteditable>
This test area has editable content
</fieldset>
</form>

最新更新