长按“按钮”会创建许多即时点击

时间:2017-12-25 01:24:30

标签: javascript jquery jquery-ui

基本上,只要鼠标按下该按钮,我就会尝试多次再次执行按钮。

我需要这个带滑块的按钮。现在,我点击一个按钮,例如"增加滑块"并且滑块增加了1步,但是如果我长按该按钮,我现在希望能够增加滑块很多步。

我该怎么做?

2 个答案:

答案 0 :(得分:2)

do循环在1000毫秒内运行的次数最多,mouseleavemouseup处理程序永远不会有机会运行,因为their events are sitting in the message queue等待mousedown处理程序完成该循环的运行。

循环设置了几千个超时,至少在200毫秒后运行。鉴于您发布的代码,这些超时实际上并没有做任何事情,因为window's click handler is being called, not your button's

mouseleavemouseup处理程序基本上什么都不做,因为start会在被检查之前重置为有效时间。

那我们该如何解决呢?

我们需要两个延迟:初始点击和滑块第一次增加之间的1000毫秒延迟,以及滑块之间的200毫秒延迟增加。如果用户在前1000毫秒内取消,我们将其视为单击。如果用户在重复开始后取消,我们不应将其视为点击。 (我们定义"取消"释放鼠标按钮或将光标移离按钮。这意味着在UI按钮上按下鼠标按钮并将光标移开将算作点击,但是代码会更简单。)

我们可以通过设置超时来设置延迟,超时在1000毫秒后设置一个间隔,每隔200毫秒,增加滑块。由于规范的最后一行,我们不会使用click事件来增加滑块:

  

如果用户在重复开始后取消,我们不应将其视为点击。

因此我们将滑块增加代码赋予其自己的函数increaseSlider()(无论如何这都是好的做法):

function startLongClick (e) {
  window.setTimeout(() => {
    increaseSlider();
    window.setInterval(() => {
      increaseSlider();
    }, 200);
  }, 1000);
}
$('#button').on('mousedown', startLongClick);

我们在超时时首次调用increaseSlider(),因此滑块在初始点击后首先增加1000毫秒,而不是1200.我们在超时和间隔中使用箭头函数,因为arrow functions don't redefine this,所以我们& #39; d如果需要,可以引用触发<button>

I can't stop it!

现在代码,单击该按钮将启动整个长按过程,无法停止它。停止进程意味着停止超时和间隔,我们可以使用window.clearTimeout()window.clearInterval()(他们执行相同的功能;不要告诉任何人)。我们需要依赖ID [{1}}和setTimeout()给我们,并在setInterval()mouseup处理程序中清除它们:

mouseleave

短暂点击怎么办?

现在按钮正在执行我们希望它执行的操作,但有一个例外:短按不会执行任何操作,因为我们没有使用let intervalId; let timeoutId; function startLongClick (e) { timeoutId = window.setTimeout(() => { increaseSlider(); intervalId = window.setInterval(() => { increaseSlider(); }, 200); }, 1000); } function cancelLongClick () { window.clearInterval(intervalId); window.clearTimeout(timeoutId); } $('#button').on('mousedown', startLongClick); $('#button').on('mouseup', cancelLongClick); $('#button').on('mouseleave', cancelLongClick); 处理程序和在调用click之前清除超时。如果在increaseSlider()事件之后但在超时触发之前触发了取消事件,则应该注册一个短按。由于在mousedown事件之前timeoutId未定义,并且在超时触发后我们不需要它,我们可以在超时时为其分配mousedown并使用它来确定我们是否应该注册一下:

undefined

我们也在短信代码中将let intervalId; let timeoutId; function startLongClick (e) { timeoutId = window.setTimeout(() => { timeoutId = undefined; increaseSlider(); intervalId = window.setInterval(() => { increaseSlider(); }, 200); }, 1000); } function cancelLongClick () { window.clearInterval(intervalId); if (timeoutId) { increaseSlider(); window.clearTimeout(timeoutId); timeoutId = undefined; } } $('#button').on('mousedown', startLongClick); $('#button').on('mouseup', cancelLongClick); $('#button').on('mouseleave', cancelLongClick); 设置为timeoutId。否则,在短暂点击后,每次将鼠标移出按钮时都会触发增加。

更多按钮!

代码现在可以工作,但是需要两个全局变量,并且对特定按钮进行了硬编码。让我们把它变成一个通用的jQuery插件*:

&#13;
&#13;
undefined
&#13;
(($) => {
  $.fn.repeatingClick = function (callback, delay = 500, interval = 200) {
    return this.each(function () {
      let intervalId;
      let timeoutId;
      function startLongClick (e) {
        timeoutId = window.setTimeout(() => {
          timeoutId = undefined;
          callback.call($(this), e);
          intervalId = window.setInterval(() => {
            callback.call(this, e);
          }, interval);
        }, delay);
      }
      function cancelLongClick (e) {
        window.clearInterval(intervalId);
        if (timeoutId) {
          callback.call(this, e);
          window.clearTimeout(timeoutId);
          timeoutId = undefined;
        }
      }
      $(this).on('mousedown', startLongClick);
      $(this).on('mouseup', cancelLongClick);
      $(this).on('mouseleave', cancelLongClick);
    });
  }
})(jQuery);

function modifySlider (e) {
  let modifier = Number($(this).data('change'));
  $('progress').attr('value', Number($('progress').attr('value')) + modifier);
}

$('button').repeatingClick(modifySlider);
&#13;
&#13;
&#13;

改变了什么?

  • 使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button id="dec" data-change="-1">&minus;</button> <progress value="25" max="50"></progress> <button id="inc" data-change="1">+</button>参数和increaseSlider()替换了对callback的来电。这样,任何函数都可以用作回调,由于我们在超时时使用了箭头函数,我们可以使用Function.callcallback.call($(this), e)来访问回调中的触发元素。
  • 将超时和时间间隔的延迟参数化为thisdelay,以便更常用。
  • 将所有内容放入新的jQuery函数interval中。由于jQuery对象可以表示集合以及单个元素,因此我们将原始代码包装在对$.repeatingClick()的调用中以单独访问每个元素。我们还以通常的方式返回jQuery对象。

其余部分特定于此应用程序:两个按钮,用于修改($.each())&#39;滑块的值,使用自定义<progress>属性作为实际金额,以便我们可以给两个相同的代码。

*我之前从未编写过jQuery插件;围绕核心逻辑的大多数代码直接来自jquery-longpress,这是一个几乎完成OP所需的jQuery插件。

答案 1 :(得分:1)

尝试使用间隔而不是手动计算时间。看看这个:

var value = 0
var addval;
var press = false;

$('#button').on('mousedown', function (e) {
	press = true;
	increaseValue();
	return false;
});


$('#button').on('mouseleave', function (e) {
    clearInterval(addval);
	return false;
});

$('#button').on('mouseenter', function(e) {
	if (press)
		increaseValue();
});

$('#button').on('mouseup', function (e) {
	press = false;
    clearInterval(addval);
	return false;
});

function increaseValue() {
	addval = setInterval(function(){
		value++;
		$("#counter").text(value);
	}, 100);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Press me</button>
<div id="counter">0</div>

您可以通过更改间隔时间来调整速度。