Safari iPad: предотвращение увеличения при двойном нажатии - PullRequest
11 голосов
/ 23 июня 2010

Я создаю сайт в Safari для iPad. Мне нужно предотвратить масштабирование при двойном касании, но у меня есть две проблемы:

  • двойное нажатие не генерирует никаких событий, поэтому я не могу использовать "event.preventDefault ();"
  • Мне нужно делать это только тогда, когда выполняются некоторые условия, поэтому я не могу использовать тег "<meta name = "viewport" content = "user-scalable = no">" ... Если я это сделаю, пользователи никогда не смогут увеличить мою страницу.

Как я могу исправить эти проблемы?

Ответы [ 7 ]

7 голосов
/ 16 марта 2012

Вот плагин jQuery, который я написал для той же цели - выборочное отключение двойного нажатия на заданные элементы страницы (в моем случае, кнопки навигации для переворачивания страниц). Я хочу отвечать на каждое нажатие (включая двойное нажатие) какобычное событие клика, без iOS "волшебства прикосновения".

Чтобы использовать его, просто запустите что-то вроде $('.prev,.next').nodoubletapzoom(); на элементах, которые вам нужны.( Edit: теперь также игнорирует пинчи)

// 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);
7 голосов
/ 16 июня 2011

Mobile Safari не поддерживает событие javascript ondblclick. Safari интерпретирует его как «зум».

Рауль Санчес опубликовал потенциальное решение: http://appcropolis.com/implementing-doubletap-on-iphones-and-ipads/

6 голосов
/ 23 января 2014

попробуйте этот модифицированный код. Должно работать как на 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();
5 голосов
/ 18 мая 2012

Я изменил решение javascript @ ecmanaut, чтобы сделать две вещи.

  1. Я использую modernizr, поэтому он поместит класс .touch css на узел html, чтобы я мог обнаруживать сенсорные экраны вместо использования обнаружения пользовательского агента. Возможно, существует подход «без модернизма», но я его не знаю.
  2. Я разделяю каждый «щелчок», чтобы они происходили отдельно, если вы щелкнете один раз, он щелкнет один раз, если вы быстро нажмете кнопку / триггер, он будет считаться несколько раз.
  3. незначительные изменения форматирования кода, я предпочитаю каждую переменную, определенную отдельно, и т. Д., Это больше "я", чем что-либо еще, я полагаю, вы могли бы просто отменить это, ничего плохого не произойдет.

Я полагаю, что эти модификации делают это лучше, потому что вы можете увеличить счетчик 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 к телу, а затем присоединяете все ваши обработчики событий к узлу ".content", но делегируете конкретному рассматриваемому узлу, поэтому jquery перехватывает все обработчики в последняя стадия перед тем, как событие всплывет до тега body.

главное преимущество этого решения в том, что вам нужно только назначить обработчик nodoubletapzoom () для тела, вы делаете это только один раз, а не один раз для каждого элемента, так что для того, чтобы получить, требуется гораздо меньше работы, усилий и мышления. все сделано.

это дает дополнительное преимущество, заключающееся в том, что если вы добавляете контент с помощью AJAX, обработчики автоматически получают готовые и ожидающие обработчики. Полагаю, если вы этого НЕ хотите, то этот метод не будет работать для вас, и вам придется настроить это больше.

Я проверил, что этот код работает на ipad, на самом деле он прекрасен, молодец @ecmanaut для основного решения !!

** Изменено в субботу 26 мая, потому что я нашел то, что кажется идеальным решением с минимальными усилиями

3 голосов
/ 10 июня 2015

Все решения, которые я видел (на этой странице, а также в других местах), имеют побочный эффект, который предотвращают повторные клики с высокой скоростью. Позволяет один клик на 500 мс или аналогичный. Это может быть хорошо в некоторых случаях, но не например. если у вас есть стрелок или кнопки со стрелками, позволяющие быстро перемещаться от элемента к элементу.

Самое простое решение:

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

Это вызывает fn_start() (фактическая функция обратного вызова) каждый раз, когда начинается касание, но затем предотвращает масштабирование по умолчанию и т. Д.

Рабочий сравнительный пример здесь: http://jsbin.com/meluyevisi/1/. Зеленая коробка предотвращает, красная коробка позволяет.

1 голос
/ 30 марта 2012

простой настройки области просмотра может быть не всегда достаточно - в некоторых случаях вам, возможно, придется также позвонить event.preventDefault (); в обработчике сенсорного запуска.

0 голосов
/ 27 сентября 2012

Принятый ответ «двойной щелчок» для меня немного «раздут» и использует метку времени ..... почему?Посмотрите на эту простую реализацию без чрезмерного «раздувания».

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, когда событие связано или нет.

Toчтобы предотвратить масштабирование и прокрутку, сделайте следующее:

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; }
  • = не эффективно, но попробуйте, оно прекрасно работает.

Ура!

...