Programming

뷰포트 확대 / 축소 사용 중지 iOS 10 이상 사파리?

procodes 2020. 6. 16. 23:01
반응형

뷰포트 확대 / 축소 사용 중지 iOS 10 이상 사파리?


나는 내 아이폰 6 플러스 아이폰 OS 10 베타 버전을 업데이트하고 바로 모바일 사파리, 당신은 두 번 눌러 모든 웹 페이지를 확대하거나 곤란 것으로 나타났습니다 무시user-scalable=no 메타 태그 코드를. 버그인지 기능인지 모르겠습니다. 기능으로 간주되면 뷰포트 확대 / 축소 iOS 10 사파리를 어떻게 비활성화합니까?


iOS 11/12 릴리스에서 업데이트되었지만 iOS 11 및 iOS 12 사파리는 여전히 메타 태그를 존중 하지 않습니다user-scalable=no .

Safari의 모바일 github 사이트


iOS 10에서는 Safari에서 웹 페이지 크기 조정을 막을 수 있지만 더 많은 작업이 필요합니다. 카고 컬트 개발자들이 모든 뷰포트 태그에 "user-scalable = no"를 떨어 뜨리고 시각 장애가있는 사용자에게는 불필요하게 어려운 일이 발생하는 것을 막는 데 어려움이 있다고 생각합니다.

그럼에도 불구하고 Apple이 더블 탭 투 줌을 비활성화하는 간단한 (메타 태그) 방법이 있도록 구현 방식을 변경하고 싶습니다. 어려움의 대부분은 그 상호 작용과 관련이 있습니다.

다음과 같이 핀치 투 줌을 중지 할 수 있습니다.

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, false);

더 깊은 대상이 이벤트에서 stopPropagation을 호출하면 이벤트가 문서에 도달하지 않으며이 리스너가 스케일링 동작을 막지 않습니다.

두 번 탭하여 확대를 비활성화하는 것도 비슷합니다. 이전 탭에서 300 밀리 초 이내에 발생하는 문서의 탭을 비활성화합니다.

var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
  var now = (new Date()).getTime();
  if (now - lastTouchEnd <= 300) {
    event.preventDefault();
  }
  lastTouchEnd = now;
}, false);

양식 요소를 올바르게 설정하지 않으면 입력에 초점을 맞추면 자동 확대 / 축소가 수행되며 수동 확대 / 축소를 대부분 사용하지 않도록 설정했기 때문에 이제 확대 / 축소를 해제하는 것이 거의 불가능합니다. 입력 글꼴 크기가 16 픽셀 이상인지 확인하십시오.

기본 앱의 WKWebView 에서이 문제를 해결하려는 경우 위에 제공된 솔루션이 가능하지만 https : //.com/a/31943976/661418보다 나은 솔루션 입니다. 다른 답변에서 언급했듯이 iOS 10 베타 6에서 Apple은 이제 메타 태그를 기리는 플래그를 제공했습니다.

2017 년 5 월 업데이트 : pinch-zoom을 비활성화하는 오래된 '터치 스타트 길이를 터치 스타트'방법으로보다 간단한 'check event.scale on touchmove'접근 방식으로 바꿨습니다. 모든 사람에게 더 안정적이어야합니다.


이것은 iOS 10의 새로운 기능입니다.

iOS 10 베타 1 릴리스 정보에서 :

  • Safari에서 웹 사이트에 대한 접근성을 향상시키기 위해 웹 사이트 user-scalable=no가 뷰포트에 설정 되어 있어도 확대 / 축소 할 수 있습니다 .

우리는 곧 JS 애드온이 어떤 식 으로든 이것을 비활성화 할 것으로 기대합니다.


이 동작은 최신 베타 버전에서 변경된 것으로 보이며, 작성 당시 베타 6입니다.

iOS 10 Beta 6 릴리스 정보 :

WKWebView now defaults to respecting user-scalable=no from a viewport. Clients of WKWebView can improve accessibility and allow users to pinch-to-zoom on all pages by setting the WKWebViewConfiguration property ignoresViewportScaleLimits to YES.

However, in my (very limited) testing, I can't yet confirm this to be the case.

Edit: verified, iOS 10 Beta 6 respects user-scalable=no by default for me.


I've been able to fix this using the touch-action css property on individual elements. Try setting touch-action: manipulation; on elements that are commonly clicked on, like links or buttons.


I spent about an hour looking for a more robust javascript option, and did not find one. It just so happens that in the past few days I've been fiddling with hammer.js (Hammer.js is a library that lets you manipulate all sorts of touch events easily) and mostly failing at what I was trying to do.

With that caveat, and understanding I am by no means a javascript expert, this is a solution I came up with that basically leverages hammer.js to capture the pinch-zoom and double-tap events and then log and discard them.

Make sure you include hammer.js in your page and then try sticking this javascript in the head somewhere:

< script type = "text/javascript" src="http://hammerjs.github.io/dist/hammer.min.js"> < /script >
< script type = "text/javascript" >

  // SPORK - block pinch-zoom to force use of tooltip zoom
  $(document).ready(function() {

    // the element you want to attach to, probably a wrapper for the page
    var myElement = document.getElementById('yourwrapperelement');
    // create a new hammer object, setting "touchAction" ensures the user can still scroll/pan
    var hammertime = new Hammer(myElement, {
      prevent_default: false,
      touchAction: "pan"
    });

    // pinch is not enabled by default in hammer
    hammertime.get('pinch').set({
      enable: true
    });

    // name the events you want to capture, then call some function if you want and most importantly, add the preventDefault to block the normal pinch action
    hammertime.on('pinch pinchend pinchstart doubletap', function(e) {
      console.log('captured event:', e.type);
      e.preventDefault();
    })
  });
</script>


The workaround that works in Mobile Safari at this time of writing, is to have the the third argument in addEventListener be { passive: false }, so the full workaround looks like this:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

You may want to check if options are supported to remain backwards compatible.


I tried the previous answer about pinch-to-zoom

document.documentElement.addEventListener('touchstart', function (event) {
    if (event.touches.length > 1) {
        event.preventDefault();
    }
}, false);

however sometime the screen still zoom when the event.touches.length > 1 I found out the best way is using touchmove event, to avoid any finger moving on the screen. The code will be something like this:

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();      
}, false);

Hope it will help.


Check for scale factor in touchove event then prevent touch event.

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);

We can get everything we want by injecting one style rule and by intercepting zoom events:

$(function () {
  if (!(/iPad|iPhone|iPod/.test(navigator.userAgent))) return
  $(document.head).append(
    '<style>*{cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}</style>'
  )
  $(window).on('gesturestart touchmove', function (evt) {
    if (evt.originalEvent.scale !== 1) {
      evt.originalEvent.preventDefault()
      document.body.style.transform = 'scale(1)'
    }
  })
})

✔ Disables pinch zoom.

✔ Disables double-tap zoom.

✔ Scroll is not affected.

✔ Disables tap highlight (which is triggered, on iOS, by the style rule).

NOTICE: Tweak the iOS-detection to your liking. More on that here.


Apologies to lukejackson and Piotr Kowalski, whose answers appear in modified form in the code above.


I came up with a pretty naive solution, but it seems to work. My goal was to prevent accidental double-taps to be interpreted as zoom in, while keeping pinch to zoom working for accessibility.

The idea is in measuring time between the first touchstart and second touchend in a double tap and then interpreting the last touchend as click if the delay is too small. While preventing accidental zooming, this method seems to keep list scrolling unaffected, which is nice. Not sure if I haven't missed anything though.

let preLastTouchStartAt = 0;
let lastTouchStartAt = 0;
const delay = 500;

document.addEventListener('touchstart', () => {
  preLastTouchStartAt = lastTouchStartAt;
  lastTouchStartAt = +new Date();
});
document.addEventListener('touchend', (event) => {
  const touchEndAt = +new Date();
  if (touchEndAt - preLastTouchStartAt < delay) {
    event.preventDefault();
    event.target.click();
  }
});

Inspired by a gist from mutewinter and Joseph's answer.


In my particular case, I am using Babylon.js to create a 3D scene and my whole page consists of one full screen canvas. The 3D engine has its own zooming functionality but on iOS the pinch-to-zoom interferes with that. I updated the the @Joseph answer to overcome my problem. To disable it, I figured out that I need to pass the {passive: false} as an option to the event listener. The following code works for me:

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);

Found this simple work around which appears to prevent double click to zoom:

    // Convert touchend events to click events to work around an IOS 10 feature which prevents
    // developers from using disabling double click touch zoom (which we don't want).
    document.addEventListener('touchend', function (event) {
        event.preventDefault();
        $(event.target).trigger('click');
    }, false);

As odd as it sounds, at least for Safari in iOS 10.2, double tap to zoom is magically disabled if your element or any of its ancestors have one of the following:

  1. An onClick listener - it can be a simple noop.
  2. A cursor: pointer set in CSS

Unintentional zooming tends to happen when:

  • A user double taps on a component of the interface
  • A user interacts with the viewport using two or more digits (pinch)

To prevent the double tap behaviour I have found two very simple workarounds:

<button onclick='event.preventDefault()'>Prevent Default</button>
<button style='touch-action: manipulation'>Touch Action Manipulation</button>

Both of these prevent Safari (iOS 10.3.2) from zooming in on the button. As you can see one is JavaScript only, the other is CSS only. Use appropriately.

Here is a demo: https://codepen.io/lukejacksonn/pen/QMELXQ

필자는 웹에 멀티 터치 인터페이스를 만들지 않는 경향이 있기 때문에 핀치 동작 (아직)을 방지하려고 시도하지 않았으며, 둘째로 네이티브 앱 UI를 포함한 모든 인터페이스가 "확대 / 축소"되어야한다는 생각으로 돌아 왔습니다. 장소에서 가능합니다. 나는 여전히 사용자 UI에 액세스 할 수 있도록하기 위해이 작업을 수행하지 않아도 되도록 설계하고 있습니다.


iOS (iPhone 6, iOS 10.0.2)의 페이지에서 실제로 위의 모든 답변을 확인했지만 성공하지 못했습니다. 이것은 내 작업 솔루션입니다.

$(window).bind('gesturestart touchmove', function(event) {
    event = event.originalEvent || event;
    if (event.scale !== 1) {
         event.preventDefault();
         document.body.style.transform = 'scale(1)'
    }
});

이것은 나를 위해 일했다 :

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();
}, false);

참고 URL : https://stackoverflow.com/questions/37808180/disable-viewport-zooming-ios-10-safari

반응형