简体   繁体   English

使用 mousedown 连续增加或减少值 JavaScript

[英]Increase or decrease value continuously using mousedown JavaScript

I copied some code from here .我从这里复制了一些代码。

The following code has some errors when the value reaches the minFontSize or maxFontSize .当值达到minFontSizemaxFontSize时,以下代码会出现一些错误。

I don't know how to fix this...我不知道如何解决这个...

 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>

Your timers are not cleared when you hit the minimum or maximum because (as @timmmmmb already said) disabled buttons don't trigger mouse events.当您达到最小值或最大值时,您的计时器不会被清除,因为(正如@timmmmmb 已经说过的那样)禁用的按钮不会触发鼠标事件。 Thus, when you try to go in the other direction, the original timer is again executed.因此,当您尝试向另一个方向 go 时,将再次执行原始计时器。

The simplest would probably be, calling clearTimers also when you hit the end of the range最简单的可能是,当您到达范围末尾时也调用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>

I think the problem is, that when you reach the max Fontsize you disable the button and that means your mouseup event will not be triggerd.我认为问题是,当您达到最大字体大小时,您会禁用该按钮,这意味着您的 mouseup 事件不会被触发。 I moved the mouseup event away from the buttons and on the container and i think it works now.我将 mouseup 事件从按钮和容器上移开,我认为它现在可以工作了。

 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>

Discrepancies差异

"mouseup" and "mouseleave" needs to be registered on each button or the events must be delegated to the buttons.需要在每个按钮上注册“mouseup”和“mouseleave”,或者必须将事件委托给按钮。 Right now the mouse events only affect the <div> which doesn't have any functions firing off on it.现在鼠标事件只影响<div>没有任何功能触发它。 So that's why the buttons get stuck -- they are consantly repeating themselves even after the user releases the mousebutton.这就是按钮卡住的原因——即使在用户释放鼠标按钮后,它们也会不断重复自己。

The example below has separate event handlers for each button.下面的示例为每个按钮提供了单独的事件处理程序。 Normally I prefer to use one event handler to control everything through event delegation , but because of the need to use set\clearInterval() as event handlers, the event object gets lost.通常我更喜欢使用一个事件处理程序通过事件委托来控制一切,但由于需要使用set\clearInterval()作为事件处理程序,事件 object 丢失了。 I could solve that problem with a closure, but your code was close enough that a radical change wouldn't be to your benifet.我可以用闭包来解决这个问题,但你的代码已经足够接近以至于根本改变不会对你有利。

Saving with localStorage (I know it's not part of the question) is omitted from this version since this site blocks it's use.这个版本省略了使用localStorage保存(我知道这不是问题的一部分),因为这个网站阻止了它的使用。 I wrote another version that saves the current font-size and loads it as well, to review that one go to this Plunker .我写了另一个版本来保存当前字体大小并加载它,以查看那个 go 到这个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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM