【问题标题】:How to detect a long touch pressure with javascript for android and iphone?如何使用适用于 android 和 iphone 的 javascript 检测长触摸压力?
【发布时间】:2011-09-02 14:40:55
【问题描述】:

如何使用 javascript 为 android 和 iphone 检测长触摸压力? 本机 javascript 或 jquery...

我想要一些听起来像:

<input type='button' onLongTouch='myFunc();' />

【问题讨论】:

    标签: javascript iphone android html mobile-website


    【解决方案1】:

    基于@djanowski 的解决方案来处理触摸滚动。这也应该防止上下文菜单和长按选择。

    function onLongPress(element, callback) {
        var timeoutId;
    
        element.addEventListener('touchstart', function(e) {
            timeoutId = setTimeout(function() {
                timeoutId = null;
                e.stopPropagation();
                callback(e.target);
            }, 500);
        });
    
        element.addEventListener('contextmenu', function(e) {
            e.preventDefault();
        });
    
        element.addEventListener('touchend', function () {
            if (timeoutId) clearTimeout(timeoutId);
        });
    
        element.addEventListener('touchmove', function () {
            if (timeoutId) clearTimeout(timeoutId);
        });
    }
    
    onLongPress(document.getElementById('kitty1'), function(element) {
        alert('Meow from ' + element.outerHTML );
    });
    
    onLongPress(document.getElementById('kitty2'), function(element) {
        alert('Meow from ' + element.outerHTML );
    });
    img {
      max-width: 100%;
      -webkit-user-select: none; /* Safari */
      -ms-user-select: none; /* IE 10 and IE 11 */
      user-select: none; /* Standard syntax */
    }
    <p>Long press on kitty!  Kitty should meow on 500ms long press but not scroll</p>
    
    <img id="kitty1" src="http://placekitten.com/300/400" />
    <img id="kitty2" src="http://placekitten.com/300/300" />

    【讨论】:

      【解决方案2】:

      这适用于我的用例,即想要在触摸屏幕时执行某些功能。

      let triggerInterval = 200; // in milliseconds
      let timerId;
      
      function touchstart(e) {
        // e.preventDefault();
        timerId = setInterval(yourFunction, triggerInterval);
      }
      
      function touchend(e) {
        clearInterval(timerId);
      }
      
      function yourFunction() {
        //   perform your logic
      }
      
      document.addEventListener("touchstart", touchstart);
      document.addEventListener("touchend", touchend);
      

      注意:- triggerInterval 中的较小值将更快地执行 yourFunction()

      当你完成你的程序后,你可以移除相应的事件监听器:

      document.removeEventListener("touchstart", touchstart);
      document.removeEventListener("touchend", touchend);
      

      【讨论】:

        【解决方案3】:

        这个基于@Joshua 的更好的解决方案,有时代码需要直接在事件内部调用(一些Web API 需要用户操作来触发某些东西)对于这种情况你可以使用这个修改:

        var longtouch;
        var timer;
        //length of time we want the user to touch before we do something
        var touchduration = 500;
        
        function touchstart() {
            longtouch = false;
        
            timer = setTimeout(function() {
               longtouch = true;
               timer = null
            }, touchduration);
        }
        
        function touchend() {
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            if (longtouch) {
                // your long acction inside event
                longtouch = false;
            }
        }
        

        在 setTimeout 中将标志设置为 true,在 touchend 中检查是否已设置。

        【讨论】:

          【解决方案4】:

          这是 Joshua 答案的扩展版本,因为他的代码在用户不执行多点触控之前运行良好(您可以用两根手指点击屏幕,功能将被触发两次,4 指 - 4 次)。 在一些额外的测试场景之后,我什至触发了非常频繁地触摸并接收每次点击后执行的功能的可能性。

          我添加了名为“lockTimer”的变量,它应该在用户触发“touchend”之前锁定任何额外的 touchstart。

          var onlongtouch; 
          var timer;
          var touchduration = 800; //length of time we want the user to touch before we do something
          
          function touchstart(e) {
              e.preventDefault();
              if (!timer) {
                  timer = setTimeout(onlongtouch, touchduration);
              }
          }
          
          function touchend() {
              //stops short touches from firing the event
              if (timer) {
                  clearTimeout(timer);
                  timer = null;
              }
          }
          
          onlongtouch = function() { 
              timer = null;
              document.getElementById('ping').innerText+='ping\n'; 
          };
          
          document.addEventListener("DOMContentLoaded", function(event) { 
              window.addEventListener("touchstart", touchstart, false);
              window.addEventListener("touchend", touchend, false);
          });
          &lt;div id="ping"&gt;&lt;/div&gt;

          【讨论】:

          • 您不需要额外的lockTimer 变量,因为您只需检查是否设置了timer
          【解决方案5】:

          此处发布的解决方案忽略了用户需要触摸屏幕才能启动滚动的事实。如果用户不尝试滚动,我们只需要长按行为。

          function onLongPress(element, callback) {
            let timer;
          
            element.addEventListener('touchstart', () => { 
              timer = setTimeout(() => {
                timer = null;
                callback();
              }, 500);
            });
          
            function cancel() {
              clearTimeout(timer);
            }
          
            element.addEventListener('touchend', cancel);
            element.addEventListener('touchmove', cancel);
          }
          

          然后:

          onLongPress(element, () => {
            console.log('Long pressed', element);
          });
          

          【讨论】:

          • 迄今为止最好的答案,谢谢!也可能想要捕获上下文菜单。
          【解决方案6】:

          长按事件适用于所有浏览器

          (function (a) {
                  function n(b) { a.each("touchstart touchmove touchend touchcancel".split(/ /), function (d, e) { b.addEventListener(e, function () { a(b).trigger(e) }, false) }); return a(b) } function j(b) { function d() { a(e).data(h, true); b.type = f; jQuery.event.handle.apply(e, o) } if (!a(this).data(g)) { var e = this, o = arguments; a(this).data(h, false).data(g, setTimeout(d, a(this).data(i) || a.longclick.duration)) } } function k() { a(this).data(g, clearTimeout(a(this).data(g)) || null) } function l(b) {
                      if (a(this).data(h)) return b.stopImmediatePropagation() ||
                      false
                  } var p = a.fn.click; a.fn.click = function (b, d) { if (!d) return p.apply(this, arguments); return a(this).data(i, b || null).bind(f, d) }; a.fn.longclick = function () { var b = [].splice.call(arguments, 0), d = b.pop(); b = b.pop(); var e = a(this).data(i, b || null); return d ? e.click(b, d) : e.trigger(f) }; a.longclick = { duration: 500 }; a.event.special.longclick = {
                      setup: function () {
                          /iphone|ipad|ipod/i.test(navigator.userAgent) ? n(this).bind(q, j).bind([r, s, t].join(" "), k).bind(m, l).css({ WebkitUserSelect: "none" }) : a(this).bind(u, j).bind([v,
                          w, x, y].join(" "), k).bind(m, l)
                      }, teardown: function () { a(this).unbind(c) }
                  }; var f = "longclick", c = "." + f, u = "mousedown" + c, m = "click" + c, v = "mousemove" + c, w = "mouseup" + c, x = "mouseout" + c, y = "contextmenu" + c, q = "touchstart" + c, r = "touchend" + c, s = "touchmove" + c, t = "touchcancel" + c, i = "duration" + c, g = "timer" + c, h = "fired" + c
              })(jQuery);
          

          用时间间隔绑定 longclick 事件

           $('element').longclick(250, longClickHandler);
          

          在触摸设备上长按以下功能触发

          function longClickHandler() {
              alter('Long tap Fired');
          }
          

          【讨论】:

            【解决方案7】:

            我已经在我的 Android 应用中这样做了:

            1. 注册的事件监听器:

              var touchStartTimeStamp = 0;
              var touchEndTimeStamp   = 0;
              
              window.addEventListener('touchstart', onTouchStart,false);
              window.addEventListener('touchend', onTouchEnd,false);
              
            2. 新增功能:

              var timer;
              function onTouchStart(e) {
                  touchStartTimeStamp = e.timeStamp;
              }
              
              function onTouchEnd(e) {
                  touchEndTimeStamp = e.timeStamp;
              
                  console.log(touchEndTimeStamp - touchStartTimeStamp);// in miliseconds
              }
              
            3. 检查时差并完成我的工作

            我希望这会有所帮助。

            【讨论】:

            • 这是一个长按触摸端,但我认为长按不需要触摸端。
            【解决方案8】:

            我们可以计算触摸开始和触摸结束的时间差。如果计算出的时间差超过了触摸持续时间,那么我们使用函数名称 taphold。

            var touchduration = 300; 
            var timerInterval;
            
            function timer(interval) {
            
                interval--;
            
                if (interval >= 0) {
                    timerInterval = setTimeout(function() {
                                        timer(interval);
                                    });
                } else {
                    taphold();
                }
            
            }
            
            function touchstart() {
                timer(touchduration);
            }
            
            function touchend() {
                clearTimeout(timerInterval);
            }
            
            function taphold(){
                alert("taphold");
            }
            
            
            document.getElementById("xyz").addEventListener('touchstart',touchstart);
            document.getElementById("xyz").addEventListener('touchend',touchend);
            

            【讨论】:

            • 我认为大多数人的想法是让函数在被执行时执行,而不是在执行之后。因此触摸结束不起作用。
            【解决方案9】:

            对于跨平台开发者:

            Mouseup/down 似乎在 android 上工作正常 - 但不是所有设备,即(三星 tab4)。在 iOS 上根本无法使用。

            进一步研究似乎这是由于元素具有选择和本机放大率打断了听众。

            如果用户持有图像 500 毫秒,此事件侦听器允许在引导模式中打开缩略图图像。

            它使用响应式图像类,因此显示更大版本的图像。 这段代码已经过全面测试(iPad/Tab4/TabA/Galaxy4):

            var pressTimer;  
            $(".thumbnail").on('touchend', function (e) {
               clearTimeout(pressTimer);
            }).on('touchstart', function (e) {
               var target = $(e.currentTarget);
               var imagePath = target.find('img').attr('src');
               var title = target.find('.myCaption:visible').first().text();
               $('#dds-modal-title').text(title);
               $('#dds-modal-img').attr('src', imagePath);
               // Set timeout
               pressTimer = window.setTimeout(function () {
                  $('#dds-modal').modal('show');
               }, 500)
            });
            

            【讨论】:

              【解决方案10】:

              使用 Touch End 检测长触摸的问题是,如果您希望事件在一段时间后触发,它将无法正常工作。最好在触摸开始时使用计时器并在触摸结束时清除事件计时器。可以使用以下模式:

              var onlongtouch; 
              var timer;
              var touchduration = 500; //length of time we want the user to touch before we do something
              
              touchstart() {
                  timer = setTimeout(onlongtouch, touchduration); 
              }
              
              touchend() {
              
                  //stops short touches from firing the event
                  if (timer)
                      clearTimeout(timer); // clearTimeout, not cleartimeout..
              }
              
              onlongtouch = function() { //do something };
              

              【讨论】:

              • 这也会在元素拖放时触发。如果您想检测不包含 touchmove 的真实点击,您还应该清除 touchmove 事件上的计时器。 (touchmove = touchend)
              • @Semra 虽然不确定是否仍然如此......即将检查谷歌的第二个结果..这是第一个..我唯一要添加到您的评论中的还有添加容差range.. 存储向下位置并检查移动位置是否在距离内。
              • 这需要timer = undefined;,因为timer 只是一个整数(文档:setTimeout())——似乎没有办法测试计时器是否仍在运行。编辑:this other answer 这样做。
              • 电弧反应堆技术是一种宣传噱头。弧线从来没有成本效益,我们在建造它之前就知道了!电弧反应堆技术!那是个死胡同,对吧?我们在这方面没有什么突破…… 30 年了? 我看电影太多了。请不要介意我忍不住写了这段对话。
              猜你喜欢
              • 2013-07-06
              • 1970-01-01
              • 2014-12-20
              • 1970-01-01
              • 2023-03-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-12-22
              相关资源
              最近更新 更多