Programing

iPhone에서 방향 변경시 웹 앱의 배율 / 줌을 재설정하려면 어떻게합니까?

crosscheck 2020. 8. 29. 09:16
반응형

iPhone에서 방향 변경시 웹 앱의 배율 / 줌을 재설정하려면 어떻게합니까?


세로 모드에서 앱을 시작하면 제대로 작동합니다. 그런 다음 가로 방향으로 회전하면 확대됩니다. 가로 모드에서 올바르게 크기를 조정하려면 무언가를 두 번 두 번 탭하고 먼저 완전히 확대 (일반적인 두 번 탭 동작)하고 다시 완전히 축소해야합니다 (다시 일반적인 두 번 탭 동작). . 축소하면 가로 모드에 적합한 새 배율로 축소됩니다.

세로로 다시 전환하는 것이 더 일관되게 작동하는 것 같습니다. 즉, 방향이 다시 세로로 변경 될 때 배율이 정확하도록 줌을 처리합니다.

이것이 버그인지 알아 내려고 노력하고 있습니까? 아니면 이것이 자바 스크립트로 고칠 수 있다면?

뷰포트 메타 콘텐츠를 사용하여 초기 배율을 1.0으로 설정하고 최소 또는 최대 배율을 설정하지 않습니다 (원하지 않음). 너비를 장치 너비로 설정하고 있습니다.

어떤 아이디어? 지속적인 문제인 것 같아 많은 사람들이 해결책이 있으면 감사 할 것임을 알고 있습니다.


Jeremy Keith ( @adactio )는 그의 블로그 Orientation and scale 에서 이에 대한 좋은 해결책을 가지고 있습니다.

마크 업에서 최대 스케일을 설정하지 않음으로써 마크 업의 확장 성을 유지하십시오.

<meta name="viewport" content="width=device-width, initial-scale=1">

그런 다음 이 스크립트로 확장 성을 다시 허용 할 제스처가 시작될 때 까지로드시 자바 스크립트로 확장 성을 비활성화합니다 .

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) {
        viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
        document.body.addEventListener('gesturestart', function () {
            viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        }, false);
    }
}


2014 년 12 월 22 일 업데이트 : iPad 1에서는 작동하지 않으며 이벤트 리스너에서 실패합니다. 다음과 같은 .body수정 사항을 제거하는 것으로 나타났습니다 .

document.addEventListener('gesturestart', function() { /* */ });

Scott Jehl 은 방향 변화를 예측하기 위해 가속도계를 사용하는 환상적인 솔루션을 내놓았 습니다. 이 솔루션은 반응성이 뛰어나며 확대 / 축소 동작을 방해하지 않습니다.

https://github.com/scottjehl/iOS-Orientationchange-Fix

작동 방식 :이 수정은 기기의 가속도계를 청취하여 방향 변경이 곧 발생할시기를 예측하는 방식으로 작동합니다. 방향 변경이 임박한 것으로 판단되면 스크립트는 사용자 확대 / 축소를 비활성화하여 확대 / 축소가 비활성화 된 상태에서 방향 변경이 제대로 발생하도록합니다. 스크립트는 장치가 똑바로 세워 지거나 방향이 변경된 후에 다시 확대 / 축소를 복원합니다. 이렇게하면 페이지를 사용하는 동안 사용자 확대 / 축소가 비활성화되지 않습니다.

축소 된 소스 :

/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT License.*/(function(m){if(!(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1)){return}var l=m.document;if(!l.querySelector){return}var n=l.querySelector("meta[name=viewport]"),a=n&&n.getAttribute("content"),k=a+",maximum-scale=1",d=a+",maximum-scale=10",g=true,j,i,h,c;if(!n){return}function f(){n.setAttribute("content",d);g=true}function b(){n.setAttribute("content",k);g=false}function e(o){c=o.accelerationIncludingGravity;j=Math.abs(c.x);i=Math.abs(c.y);h=Math.abs(c.z);if(!m.orientation&&(j>7||((h>6&&i<8||h<8&&i>6)&&j>5))){if(g){b()}}else{if(!g){f()}}}m.addEventListener("orientationchange",f,false);m.addEventListener("devicemotion",e,false)})(this);

나는 같은 문제가 있었고 maximum-scale = 1.0을 설정하면 저에게 효과적이었습니다.

편집 : 주석에서 언급했듯이 콘텐츠가 너비 해상도를 초과하는 경우를 제외하고는 사용자 확대 / 축소를 비활성화합니다. 언급했듯이 이것은 현명하지 않을 수 있습니다. 어떤 경우에는 원할 수도 있습니다.

뷰포트 코드 :

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0;">

뷰포트에서 너비를 설정 한 경우 :

<meta name = "viewport" content = "width=device-width; initial-scale=1.0;
 maximum-scale=1.0;" />

그런 다음 방향을 변경하면 때때로 (특히 화면에서 드래그하는 경우) 무작위로 확대하여이 문제를 해결하기 위해 여기에서 너비를 설정하지 않습니다.

<meta id="viewport" name="viewport" content="initial-scale=1.0; user-scalable=0;
minimum-scale=1.0; maximum-scale=1.0" />

이것은 어떤 일이 발생하든 확대 / 축소를 수정 한 다음 window.onorientationchange 이벤트를 사용하거나 window.innerWidth 메서드 를 플랫폼 독립적 (테스트 용으로 편리함 )하려는 경우 사용할 수 있습니다 .


MobileSafari는 개체 orientationchange대한 이벤트를 지원 window합니다. 불행히도 JavaScript를 통해 확대 / 축소를 직접 제어하는 ​​방법이없는 것 같습니다. 아마도 meta뷰포트를 제어 하는 태그를 동적으로 작성 / 변경할 수있을 것입니다. 그러나 이것이 작동 할 것 같지는 않지만 페이지의 초기 상태에만 영향을줍니다. 이 이벤트를 사용하여 실제로 CSS를 사용하여 콘텐츠의 크기를 조정할 수 있습니다. 행운을 빕니다!


가로 / 세로 레이아웃의 작동 데모를 만들었지 만 JavaScript없이 작동하려면 확대 / 축소를 비활성화해야합니다.

http://matthewjamestaylor.com/blog/ipad-layout-with-landscape-portrait-modes


내 프로젝트에서이 기능을 사용하고 있습니다.

function changeViewPort(key, val) {
    var reg = new RegExp(key, "i"), oldval = document.querySelector('meta[name="viewport"]').content;
    var newval = reg.test(oldval) ? oldval.split(/,\s*/).map(function(v){ return reg.test(v) ? key+"="+val : v; }).join(", ") : oldval+= ", "+key+"="+val ;
    document.querySelector('meta[name="viewport"]').content = newval;
}

그래서 그냥 addEventListener :

if( /iPad|iPhone|iPod|Android/i.test(navigator.userAgent) ){
    window.addEventListener("orientationchange", function() { 
        changeViewPort("maximum-scale", 1);
        changeViewPort("maximum-scale", 10);
    }
}

기본 iOS 확대 / 축소를 비활성화하고 대신 JavaScript에서 확대 / 축소 기능을 구현하여 내가 본 것과는 다른 새로운 해결 방법을 찾았습니다.

확대 / 축소 / 방향 문제에 대한 다양한 다른 솔루션에 대한 훌륭한 배경은 Sérgio Lopes입니다. 세로 방향 변경시 유명한 iOS 확대 / 축소 버그 수정 .

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" id="viewport" content="user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
    <title>Robocat mobile Safari zoom fix</title>
    <style>
        body {
            padding: 0;
            margin: 0;
        }
        #container {
            -webkit-transform-origin: 0px 0px;
            -webkit-transform: scale3d(1,1,1);
            /* shrink-to-fit needed so can measure width of container http://stackoverflow.com/questions/450903/make-css-div-width-equal-to-contents */
            display: inline-block;
            *display: inline;
            *zoom: 1;
        }
        #zoomfix {
            opacity: 0;
            position: absolute;
            z-index: -1;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <input id="zoomfix" disabled="1" tabIndex="-1">
    <div id="container">
        <style>
            table {
                counter-reset: row cell;
                background-image: url(http://upload.wikimedia.org/wikipedia/commons/3/38/JPEG_example_JPG_RIP_010.jpg);
            }
            tr {
                counter-increment: row;
            }
            td:before {
                counter-increment: cell;
                color: white;
                font-weight: bold;
                content: "row" counter(row) ".cell" counter(cell);
            }
        </style>
        <table cellspacing="10">
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
        </table>
    </div>

    <script>
    (function() {
        var viewportScale = 1;
        var container = document.getElementById('container');
        var scale, originX, originY, relativeOriginX, relativeOriginY, windowW, windowH, containerW, containerH, resizeTimer, activeElement;
        document.addEventListener('gesturestart', function(event) {
            scale = null;
            originX = event.pageX;
            originY = event.pageY;
            relativeOriginX = (originX - window.pageXOffset) / window.innerWidth;
            relativeOriginY = (originY - window.pageYOffset) / window.innerHeight;
            windowW = window.innerWidth;
            windowH = window.innerHeight;
            containerW = container.offsetWidth;
            containerH = container.offsetHeight;
        });
        document.addEventListener('gesturechange', function(event) {
            event.preventDefault();
            if (originX && originY && event.scale && event.pageX && event.pageY) {
                scale = event.scale;
                var newWindowW = windowW / scale;
                if (newWindowW > containerW) {
                    scale = windowW / containerW;
                }
                var newWindowH = windowH / scale;
                if (newWindowH > containerH) {
                    scale = windowH / containerH;
                }
                if (viewportScale * scale < 0.1) {
                    scale = 0.1/viewportScale;
                }
                if (viewportScale * scale > 10) {
                    scale = 10/viewportScale;
                }
                container.style.WebkitTransformOrigin = originX + 'px ' + originY + 'px';
                container.style.WebkitTransform = 'scale3d(' + scale + ',' + scale + ',1)';
            }
        });
        document.addEventListener('gestureend', function() {
            if (scale && (scale < 0.95 || scale > 1.05)) {
                viewportScale *= scale;
                scale = null;
                container.style.WebkitTransform = '';
                container.style.WebkitTransformOrigin = '';
                document.getElementById('viewport').setAttribute('content', 'user-scalable=no,initial-scale=' + viewportScale + ',minimum-scale=' + viewportScale + ',maximum-scale=' + viewportScale);
                document.body.style.WebkitTransform = 'scale3d(1,1,1)';
                // Without zoomfix focus, after changing orientation and zoom a few times, the iOS viewport scale functionality sometimes locks up (and completely stops working).
                // The reason I thought this hack would work is because showing the keyboard is the only way to affect the viewport sizing, which forces the viewport to resize (even though the keyboard doesn't actually get time to open!).
                // Also discovered another amazing side effect: if you have no meta viewport element, and focus()/blur() in gestureend, zoom is disabled!! Wow!
                var zoomfix = document.getElementById('zoomfix');
                zoomfix.disabled = false;
                zoomfix.focus();
                zoomfix.blur();
                setTimeout(function() {
                    zoomfix.disabled = true;
                    window.scrollTo(originX - relativeOriginX * window.innerWidth, originY - relativeOriginY * window.innerHeight);
                    // This forces a repaint. repaint *intermittently* fails to redraw correctly, and this fixes the problem.
                    document.body.style.WebkitTransform = '';
                }, 0);
            }
        });
    })();
    </script>
</body>
</html>

개선 될 수 있지만 내 필요에 따라 내가 본 다른 모든 솔루션에서 발생하는 주요 단점을 피할 수 있습니다. 지금까지 iOS4가 설치된 iPad 2에서 모바일 Safari를 사용하여 테스트했습니다.

focus () / blur ()는 방향을 변경하고 몇 번 확대 / 축소 한 후에 발생할 수있는 확대 / 축소 기능이 가끔 잠기는 것을 방지하는 해결 방법입니다.

Setting the document.body.style forces a full screen repaint, which avoids an occasional intermittent problems where the repaint badly fails after zoom.


Elisabeth you can change viewport content dynamically by adding the "id" property to the metatag:

<meta name="viewport" id="view" content="user-scalable=yes, width=device-width minimum-scale=1, maximum-scale=1" />

Then you just can call by javascript:

document.getElementById("view").setAttribute('content','user-scalable=yes, width=device-width, minimum-scale=1, maximum-scale=10');

Here's another way to do it, which seems to work well.

  1. Set the meta tag to restrict the viewport to scale=1, which prevents zooming:

    < meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">

  2. With javascript, change the meta tag 1/2 second later to allow zooming:

    setTimeout(function(){ document.querySelector("meta[name=viewport]").setAttribute('content','width=device-width, initial-scale=1');}, 500);

  3. Again with javascript, on orientation change, reload the page:

    window.onorientationchange = function(){window.location.reload();};

Every time you reorient the device, the page reloads, initially without zoom. But 1/2 second later, ability to zoom is restored.


Found a very easily implemented fix. Set the focus to a text element that has a font size of 50px on completion of the form. It does not seem to work if the text element is hidden but hiding this element is easily done by setting the elements color properties to have no opacity.

참고URL : https://stackoverflow.com/questions/2557801/how-do-i-reset-the-scale-zoom-of-a-web-app-on-an-orientation-change-on-the-iphon

반응형