2010-06-23 99 views
11

我正在为Safari创建一个用于iPad的网站。我需要防止双击事件的缩放,但我有两个问题:Safari iPad:防止双击变焦

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

我该如何解决这些问题?

回答

7

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

劳尔·桑切斯发布了一个潜在的解决方案: http://appcropolis.com/implementing-doubletap-on-iphones-and-ipads/

+2

我确实使用了这个解决方案......这个主题真的很详细,谢谢!对于游客来说,主要想法如下:首先,抓住一个“轻拍”事件。然后,如果在500ms之前抛出另一个“tap”事件:这是一个“双击”,所以如果您可以在这里停止事件 - >不“双击”:)请参阅链接以获取更多解释。 – Nicolas 2011-06-17 07:47:43

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); 
+0

这可行,但有一个错误:多于两次点击。在触发吞噬点击之后添加:$(this).data('lastTouch',0);'。没有它,当你三次点击时,你会得到四次点击(可能更多的是四次点击)。有了它,您可以在三次点击上点击三次,四次点击就可以点击四次。这个想法是,你可能有一个元素,应该响应很多连续的水龙头(而不是被持有,无论出于何种原因)。 – 2014-10-20 16:12:08

+0

此解决方案似乎可以防止所有重复点击,如果它们之间的延迟小于500毫秒。它会以某种方式允许点击例如。在500ms的时间范围内5次并仍然防止缩放?我需要一种在鼠标设备中重复点击的方式。 – 2015-06-09 19:02:47

+0

我发现了一个简单的解决方案,我的射手问题:http://stackoverflow.com/a/30744654/1691517。它不会“等待”500毫秒,直到允许新的点击,但立即执行,但仍可防止不必要的点击缩放。 – 2015-06-09 23:38:21

1

只是塞汀视可能并不总是不够的 - 在某些情况下,你可能不得不也呼吁 event.preventDefault();在touchstart处理程序上。

5

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

  1. 我使用modernizr,因此它会在html节点上放置一个.touch css类,以便我可以检测触摸屏而不是使用用户代理检测。也许有一种“现代化”的方法,但我不知道。
  2. 我将每个“点击”分隔开来,这样它们分开发生,如果你点击一次,它会点击一次,如果你快速点击按钮/触发器,它会多次计数。
  3. 一些小的代码格式更改,我更喜欢每个var分别定义等,这是比什么都更“我”的东西,我想你可以恢复,没有什么不好的事情会发生。

我相信这些修改使之更好,因为你可以增加一个计数器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! 
// 
// [email protected]: 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处理程序,然后将所有事件处理程序附加到“.content”节点,但委托给特定的节点,因此jquery会捕获最后阶段的所有处理程序,然后该事件将冒泡到body标记。

该解决方案的主要优点是您只需将nodoubletapzoom()处理程序分配给主体,您只需执行一次,而不是每个元素都执行一次,因此,为了实现更少的工作,努力和思考把事情做完。

这有额外的好处,如果你使用AJAX添加内容,他们会自动让处理程序准备就绪并等待,我想如果你没有这样做,那么这种方法不适合你,你将不得不更多地调整它。

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

**修改于周六5月26日,因为我发现了什么似乎是绝对最小的努力

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; } 
  • =效率不高,但尝试它,它的伟大工程。

干杯!

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").nodoubletapzoom(); 
+0

感谢您的支持!我举了一个例子:http://jsbin.com/dihoxedika/1/。 ecmanauts代码中的问题是$(this).trigger('click')。trigger('click')'。当我用'e.target'替换'this'并删除了第二个触发器时,它开始在Android Chrome中运行。问题在于快速重复点击是不可能的。 – 2015-06-10 21:23:28

+0

如果是相关的,请接受答案 – Inventillect 2015-06-13 06:30:58

2

我所看到的所有解决方案(此页面上及其他地方)有一个侧它们可以防止快速重复点击。允许每500ms或类似点击一次。在某些情况下,这可以是好的,但不是例如。如果您有射手或箭头按钮可以快速移动物品。

最简单的方法是这样的:

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

这就要求fn_start()(实际回调函数),每次当触摸时开始,但阻止则默认值zoomings等时间

工作比较例子是在这里:http://jsbin.com/meluyevisi/1/。 绿框可以防止,红框允许。