Safari iPad:防止双击放大

时间:2010-06-23 17:07:55

标签: ipad safari zoom

我正在Safari for iPad上创建一个网站。我需要阻止双击事件的缩放,但我有两个问题:

  • 双击不会产生任何事件,所以我不能使用“event.preventDefault();”
  • 我只有在满足某些条件时才需要这样做,因此我无法使用标记“<meta name = "viewport" content = "user-scalable = no">”...如果我这样做,用户就永远无法放大我的页面。

如何解决这些问题?

8 个答案:

答案 0 :(得分:7)

Mobile Safari不支持javascript ondblclick事件。它被Safari解释为“缩放”。

Raul Sanchez发布了一个潜在的解决方案: http://appcropolis.com/implementing-doubletap-on-iphones-and-ipads/

答案 1 :(得分:7)

这是我为同一目的编写的jQuery插件 - 选择性地禁用双击缩放给定页面元素(在我的情况下,导航按钮翻转页面)我想响应每个点击(包括双击)作为正常点击事件,没有iOS“触摸魔法”。

要使用它,只需在您关注的元素上运行类似$('.prev,.next').nodoubletapzoom();的内容即可。 (编辑:现在也会忽略捏合)

// jQuery no-double-tap-zoom plugin

// Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy!

(function($) {
  var IS_IOS = /iphone|ipad/i.test(navigator.userAgent);
  $.fn.nodoubletapzoom = function() {
    if (IS_IOS)
      $(this).bind('touchstart', function preventZoom(e) {
        var t2 = e.timeStamp
          , t1 = $(this).data('lastTouch') || t2
          , dt = t2 - t1
          , fingers = e.originalEvent.touches.length;
        $(this).data('lastTouch', t2);
        if (!dt || dt > 500 || fingers > 1) return; // not double-tap

        e.preventDefault(); // double tap - prevent the zoom
        // also synthesize click events we just swallowed up
        $(this).trigger('click').trigger('click');
      });
  };
})(jQuery);

答案 2 :(得分:6)

尝试这个修改过的代码。它应该适用于Android和IOS设备

(function($) {
$.fn.nodoubletapzoom = function() {
    $(this).bind('touchstart', function preventZoom(e){
        var t2 = e.timeStamp;
        var t1 = $(this).data('lastTouch') || t2;
        var dt = t2 - t1;
        var fingers = e.originalEvent.touches.length;
        $(this).data('lastTouch', t2);
        if (!dt || dt > 500 || fingers > 1){
            return; // not double-tap
        }
        e.preventDefault(); // double tap - prevent the zoom
        // also synthesize click events we just swallowed up
        $(e.target).trigger('click');
    });
};
})(jQuery);

然后将nodoubletapzoom()应用于body标签

$("body").nodoubletapzoom();

答案 3 :(得分:5)

我修改了@ ecmanaut的javascript解决方案,做了两件事。

  1. 我使用modernizr,因此它会在html节点上放置.touch css类,因此我可以检测触摸屏而不是使用用户代理检测。也许有一个&#34; modernizr-less&#34;方法,但我不知道。
  2. 我将每个&#34;点击&#34;所以它们单独发生,如果你点击一次,它会点击一次,如果你快速点击按钮/触发器,它会多次计数。
  3. 一些次要的代码格式化更改,我更喜欢单独定义的var等,这更像是&#34; me&#34;事情比什么都重要,我想你可以回复一下,没有什么不好的事情会发生。
  4. 我相信这些修改使它更好,因为你可以增加一个计数器1,2,3,4而不是2,4,6,8

    这是修改后的代码:

    //  jQuery no-double-tap-zoom plugin
    //  Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy!
    //
    //  chris.thomas@antimatter-studios.com: I modified this to 
    //  use modernizr and the html.touch detection and also to stop counting two 
    //  clicks at once, but count each click separately.
    
    (function($) {
        $.fn.nodoubletapzoom = function() {
            if($("html.touch").length == 0) return;
    
            $(this).bind('touchstart', function preventZoom(e){
                var t2 = e.timeStamp;
                var t1 = $(this).data('lastTouch') || t2;
                var dt = t2 - t1;
                var fingers = e.originalEvent.touches.length;
                $(this).data('lastTouch', t2);
                if (!dt || dt > 500 || fingers > 1){
                    return; // not double-tap
                }
                e.preventDefault(); // double tap - prevent the zoom
                // also synthesize click events we just swallowed up
                $(this).trigger('click');
            });
        };
    })(jQuery);
    

    将nodoubletapzoom()应用于body标签,就像这样

    $("body").nodoubletapzoom();
    

    你的html结构应该是这样的

    <body>
        <div class="content">...your content and everything in your page</div>
    </body>
    

    然后在你的javascript中绑定你的点击处理程序

    $(".content")
        .on(".mydomelement","click",function(){...})
        .on("button","click",function(){...})
        .on("input","keyup blur",function(){...}); 
        // etc etc etc, add ALL your handlers in this way
    

    您可以使用任何jquery事件处理程序和任何dom节点。现在你不需要做更多的事情,你必须以这种方式附加你所有的事件处理程序,我没有尝试过另一种方式,但这种方式绝对坚如磐石,你可以真正地说唱屏幕10次第二,它不会缩放并记录点击次数(显然不是每秒10次,ipad不是那么快,我的意思是,你不能触发缩放)

    我认为这是有效的,因为您将nozoom处理程序附加到正文,然后将所有事件处理程序附加到&#34; .content&#34;节点,但委托给有问题的特定节点,因此jquery在事件冒泡到body标签之前的最后阶段捕获所有处理程序。

    这个解决方案的主要好处是你只需要将nodoubletapzoom()处理程序分配给正文,你只需要执行一次,而不是每个元素执行一次,这样就不需要工作,努力和思考了为了完成任务。

    这有另外一个好处,如果你使用AJAX添加内容,他们会自动让处理程序准备就绪并等待,我想如果你不想这样,那么这种方法对你和你来说都不会有用。我必须更多地调整它。

    我已验证此代码适用于ipad,它实际上非常漂亮,对于@ecmanaut主要解决方案做得很好!!

    ** 5月26日星期六修改,因为我发现似乎是一个完美的解决方案,只需极少的努力

答案 4 :(得分:3)

我看到的所有解决方案(在此页面以及其他地方)都会产生副作用,导致它们无法快速重复点击。允许每500毫秒或类似的一次点击。在某些情况下这可能没问题,但不是例如。如果你有一个射击或箭头按钮,允许快速移动项目。

最简单的解决方案是:

$('#nozoom').on('touchstart', function(e)
{
  fn_start(e);
  e.preventDefault();
});

每次启动触摸时都会调用fn_start()(实际的回调函数),但会阻止默认的缩放等。

工作比较示例如下:http://jsbin.com/meluyevisi/1/。 绿框禁止,红框允许。

答案 5 :(得分:1)

只是设置视口可能并不总是足够 - 在某些情况下,您可能还需要打电话     event.preventDefault(); 在touchstart处理程序上。

答案 6 :(得分:0)

接受的“双击”回答对我来说有点“臃肿”并使用时间戳.....为什么?看看这个简单的实现,没有过多的“臃肿”。

function simulateDblClickTouchEvent(oo)
{
 var $oo = !oo?{}:$(oo);
 if( !$oo[0] )
  { return false; }

 $oo.bind('touchend', function(e)
 {
    var ot = this,
    ev = e.originalEvent;

    if( ev && typeof ev.touches == 'object' && ev.touches.length > 1 )
     { return; }

    ot.__taps = (!ot.__taps)?1:++ot.__taps;

    if( !ot.__tabstm ) // don't start it twice
    {
     ot.__tabstm = setTimeout( function()
     {
       if( ot.__taps >= 2 )
       {  ot.__taps = 0;
          $(ot).trigger('dblclick'); 
       }
       ot.__tabstm = 0;
       ot.__taps = 0;
     },800);
    }
 });
 return true;
};

用法:

simulateDblClickTouchEvent($('#example'));

or 

simulateDblClickTouchEvent($('.example'));
当事件被绑定时,

函数返回true或false。

要防止缩放和滚动,请执行以下操作:

function disableTouchScroll()
{

 try {
  document.addEventListener('touchmove', function(e) { e.preventDefault(); }, true );
  $j('body')[0].addEventListener('touchmove', function(e) { e.preventDefault(); }, true );
  }
  catch(ee) { return false; }
  return true;
}

使用CSS也很容易避免缩放:

body * { -webkit-user-select:none; }
  • =效率不高但尝试一下,效果很好。

干杯!

答案 7 :(得分:0)

万一有人需要一个没有jQuery的解决方案,我发现这个(https://exceptionshub.com/disable-double-tap-zoom-option-in-browser-on-touch-devices.html)可以很好地工作。该函数将期望和事件对象作为参数:

function preventZoom(e) {
  var t2 = e.timeStamp;
  var t1 = e.currentTarget.dataset.lastTouch || t2;
  var dt = t2 - t1;
  var fingers = e.touches ? e.touches.length : 0;
  e.currentTarget.dataset.lastTouch = t2;

  if (!dt || dt > 500 || fingers > 1) return; // not double-tap

  e.preventDefault();
  e.target.click();
}

Angular 10示例:

<!— Template —>

<span (click)="clicked($event)">Click me</span>
Component

clicked(event) {
  this.preventZoom(event);
  // your code
}

preventZoom(e) {
  var t2 = e.timeStamp;
  var t1 = e.currentTarget.dataset.lastTouch || t2;
  var dt = t2 - t1;
  var fingers = e.touches?.length;
  e.currentTarget.dataset.lastTouch = t2;

  if (!dt || dt > 500 || fingers > 1) return; // not double-tap

  e.preventDefault();
  e.target.click();
}