iPad上的Safari如何禁用双击缩放/居中,但保留捏合缩放?

10

我想知道在Safari iOS(iPad 1)上是否可以防止对特定HTML元素的双击缩放和双击居中?

因为我的小型HTML5游戏要求用户进行快速点击(或轻拍), 这些动作被解释为双击, 当发生这种情况时 - 页面会改变缩放并居中。

检测双击(如此答案中所述 - Safari iPad:防止双击缩放) 感觉不好..

错误的答案#1: <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> - 不适用于我的目的,因为它将阻止任何缩放。

错误的答案#2:也许仅在单击事件上使用.preventDefault()就足够了吗?- 没有任何效果。


-ms-touch-action: manipulation;听起来正是我需要的。但它只被IE10支持。 - c69
8个回答

9

除了捕获你想要防止的事件并在其上调用 preventDefault(),你已经或多或少地想到了其他方法。

确实,一些特定的 CSS 属性/值可能会改变全局站点行为(例如固定宽度或 fixed),但你仍然无法避免操作系统的更改(请参见 iOS5 中 fixed 处理更改),而且这些更改不一定能够阻止所有行为(缩放可能关闭,但双击则不行)。

因此,禁用默认行为只针对双击最好的方法是利用 iOS 提供的触摸计数:如果我们只有一个接触,则表示我们正在点击。两个接触,则表示我们正在缩放。

以下设置代码提供了该功能:

var elm = document.body; // or some selection of the element you want to disable

var catcher = function(evt) {
    if (evt.touches.length < 2)
        evt.preventDefault();
};

elm.addEventListener('touchstart', catcher, true);

在 jsFiddle 上演示

注意:使用 addEventListener 的第三个参数 (true) 表示我们想要 捕获事件,即使是对于子元素也能全部捕获。


如果 preventDefault() 能够起作用,那虽然不太好但是还可以接受,但事实并非如此。至少对于 click 事件来说是这样...我会尝试在触摸事件中使用相同的方法,并使用 stopPropagation()。 (最大的障碍是“我的”iPad和我的工作地点相距甚远。) - c69
“click”事件有什么问题吗?您说您想要防止双击缩放。通过对iOS设备(iPhone 3GS)进行测试,上述代码可以防止双击缩放。我不明白为什么您提到了“click”事件 :-S - MattiSG
平均而言,我需要花费2-3天的时间来编写代码并在iPad上进行测试,抱歉。我希望明天能够进行测试。 - c69
... 呃。你的例子禁用了单指双击缩放(很酷!),但它也完全禁用了单指轻触(不太酷),所以它甚至停止生成点击。双指双击可以工作,双指平移可以工作。双指捏合缩放有一些问题.. 不过还是加个赞吧。 - c69
touchend 上放置一个 preventDefault() 监听器似乎效果更好。但是愚蠢的 iPad 开始出现了延迟。需要调查一下。 - c69
2
@c69 哦,感谢您的慷慨奖励!您是因为问题已经解决了还是因为它确切地解决了您的问题而授予它的?我们需要记录实际有效的答案供将来参考 :) - MattiSG

7
我正在这样防止双击:

var doubleTouchStartTimestamp = 0;
$(document).bind("touchstart", function (event) {
    var now = +(new Date());
    if (doubleTouchStartTimestamp + 500 > now) {
        event.preventDefault();
    }
    doubleTouchStartTimestamp = now;
});

优雅的部分在于不需要超时。我只更新一个时间戳。它只会在下一次touchstart事件中进行比较。在iOS 6上适用。

对dom下面的双击不产生影响。

同样,在没有jQuery的情况下也可以实现:

var doubleTouchStartTimestamp = 0;
document.addEventListener("touchstart", function (event) {
    var now = +(new Date());
    if (doubleTouchStartTimestamp + 500 > now) {
        event.preventDefault();
    }
    doubleTouchStartTimestamp = now;
});

6
我写了一个jQuery插件用于选择性地禁用给定页面元素上的双击缩放功能(在我的情况下是导航按钮以翻页)。我想将每次轻触(包括双击)都作为普通点击事件响应,没有iOS的“触摸神奇”,无论用户点击得多快。

要使用它,只需在关心的元素上运行$('.prev,.next').nodoubletapzoom();之类的命令。它的原理是在500毫秒内监听节点上的连续touchstart事件,并在第二个事件上运行event.preventDefault(),除非同时存在其他触摸事件。由于preventDefault会消耗两个触点,我们还需要为该节点合成两个“错过”的点击事件,从而使您预期的触摸操作按用户意愿发生相同次数。


看起来很有趣。我会尝试测试它,并回复我的结论。 - c69
这是一个很棒的解决方案。但是当发生双击时,我无法使目标项上的onclick="..."事件触发。你有什么想法吗? - Charlie Schliesser
对我来说可以运行:http://jsfiddle.net/ecmanaut/xptak/show/ - 源代码在 http://jsfiddle.net/ecmanaut/xptak/ - 也许你的页面有处理程序窃取那些 click(或 touchstart)事件并在它们到达你的 onclick 处理程序之前运行 e.preventDefault()e.stopPropagation() - ecmanaut
它可以工作。你知道是否也可能在捏合时禁用缩放吗? - viebel

0
你使用的是哪个iOS版本/Safari浏览器?那个网站绝对不会让你双击。我找到了一些CSS,但由于我即将离开,还没有时间尝试它。
body {
  -webkit-text-size-adjust:none;
  margin:0px;
}

div{
  clear:both!important;
  display:block!important;
  width:100%!important;
  float:none!important;
  margin:0!important;
  padding:0!important;
}

0

你需要实现一个双击函数,并在第二次点击上使用preventDefault。这里有一些经过测试的代码,使用了全局变量,可以让你开始:

<button id="test1">Double Tap Me!</button>
<div id="test2">EMPTY</div>

var elm1 = document.getElementById('test1');
var elm2 = document.getElementById('test2');
var timeout;
var lastTap = 0;
elm1.addEventListener('touchend', function(event) {
    var currentTime = new Date().getTime();
    var tapLength = currentTime - lastTap;
    clearTimeout(timeout);
    if (tapLength < 500 && tapLength > 0) {
        elm2.innerHTML = 'Double Tap';
        event.preventDefault();
    } else {
        elm2.innerHTML = 'Single Tap';
        timeout = setTimeout(function() {
            elm2.innerHTML = 'Single Tap (timeout)';
            clearTimeout(timeout);
        }, 500);
    }
    lastTap = currentTime;
});

还有一个 JSFiddle: http://jsfiddle.net/brettwp/J4djY/


谢谢,但它没有在我的安卓设备上禁用缩放。有什么想法吗? - Gaurav
@Gaurav,你可能需要开一个单独的问题来讨论Android,并包括你想要实现什么以及目标设备(手机、平板电脑、版本等)的具体细节。 - Brett Pontarelli

0
JQuery方法禁用MVC4中的双击缩放 要禁用iOS 1+上的双击(双鼠标按下)功能,您需要捕获touchStart事件并创建一个覆盖以防止缩放。

//使用单个script.js和JQuery.Mobile-1.2.0 UI,每个页面在MVC中通过委托分配JQuery,因此您无需对页面进行完全刷新,从而可以利用data-prefetch,该功能在应用程序首次加载时将页面加载到DOM中

$(document).delegate(“#CashRegister”,“pageinit”,function(){

// To Disable 'Pinch to Zoom' Note: don't implement gester event handlers if you want to 
//keep pinch to zoom functionality NOTE: i use this as my pageinit is a delegate of a page
this.addEventListener("gesturestart", gestureStart, false);
this.addEventListener("gesturechange", gestureChange, false);
this.addEventListener("gestureend", gestureEnd, false);
//handle each event by disabling the defaults
function gestureStart(event) {
    event.preventDefault();
}

function gestureChange(event) {
    event.preventDefault();
}

function gestureEnd(event) {
    event.preventDefault();
}
//Recreate Double Tap and preventDefault on it
$(this).bind('touchstart', function preventZoom(e) {
// recreate the double tab functionality
        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');
    });

0

苹果有很多专门为 WebKit(Safari)设计的带有特殊标签的技巧。查看官方文档


我想我只需要尝试我的最初想法 - 阻止默认行为 - c69
有可能做到...只是不幸的是我找不到我用来实现它的代码!去像foxnews.mobi这样的网站;你无法使用捏合缩放或双击缩放。这是通过特殊的CSS Webkit元素完成的。如果我找到了代码,我会分享的哈哈 - master_gracey
抱歉,伙计们,它并不能防止任何事情发生。在foxnews.mobi上 - 它的宽度为95%,这就是为什么没有缩放,但是当您双击时,它会将内容居中,因此它不是一个好的例子。 - c69

-1

实际上,.preventDefault() 绝对有效... 使用 jQuery:

var InputHandler = {    
    startEventType : isTouch ? "touchstart" : "mousedown"
}

$(selector).bind(InputHandler.startEventType, function(evnt) {
    evnt.preventDefault();
});

你尝试在 .click() 上进行防止,但问题在于浏览器没有抛出“click”元素。Safari 只会触发点击来帮助模拟单击... 但是当双击时,Safari 不会抛出“click”元素。你的事件处理程序 .click() 永远不会触发,因此 .preventDefault() 也不会触发。

1
这种方法似乎可以检测到触摸客户端。实际上,有些设备既支持触摸又支持鼠标,因此这种非此即彼的区分并不适用,或者会使一些用户无法使用网站。 - amenthes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接