programing

아이폰에서 방향 변경 시 웹 앱의 스케일/줌을 재설정하려면 어떻게 해야 합니까?

linuxpc 2023. 9. 8. 21:12
반응형

아이폰에서 방향 변경 시 웹 앱의 스케일/줌을 재설정하려면 어떻게 해야 합니까?

세로 모드로 앱을 시작하면 잘 작동합니다.그런 다음에 저는 풍경으로 회전하고 그것은 확대됩니다.가로 모드에 맞게 올바르게 확장하려면 먼저 무언가를 두 번 두 번 두드려야 합니다(일반적인 두 번 두 번 탭 동작). 다시 한 번 확대(다시 일반적인 두 번 탭 동작).축소되면 가로 모드에 맞는 올바른 NEW 스케일로 축소됩니다.

세로로 다시 전환하는 것이 더 일관되게 작동하는 것 같습니다. 즉, 세로로 다시 방향을 바꿀 때 눈금이 정확하도록 확대/축소를 처리합니다.

이게 버그인지 알아내려고 하는데요?아니면 이것이 자바스크립트로 고칠 수 있는 것이라면?

뷰포트 메타 컨텐츠로 초기 스케일을 1.0으로 설정하고 있으며 최소 스케일이나 최대 스케일을 설정하고 있지 않습니다(원하지 않습니다).저는 폭을 장치 폭으로 설정하고 있습니다.

무슨 생각 있어요?지속적인 문제인 것 같아 많은 분들이 해결책을 마련해 주시면 감사할 것으로 알고 있습니다.

Jeremy Keith(@adactio)는 자신의 블로그 오리엔테이션스케일에서 이에 대한 좋은 솔루션을 제공합니다.

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

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

그런 다음 이 스크립트를 사용하여 다시 확장을 허용할 때 제스처가 시작될 때까지 javascript on load로 확장을 비활성화합니다.

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);
    }
}

업데이트 22-12-2014:
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.on orientation change 이벤트를 사용하거나 window.innerWidth 메서드를 플랫폼에 독립적으로 사용(테스트를 위해 handy)할 수 있습니다.

MobileSafari는 에서 이벤트를 지원합니다.window◦. 도 자바스크립트를통해 할 수 있는 같습니다.유감스럽게도 자바스크립트를 통해 줌을 직접 조절할 수 있는 방법은 없는 것 같습니다.아마도 당신은 동적으로 글을 쓰거나 변경할 수 있을 것입니다.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;
}

EventListener를 추가하기만 하면 됩니다.

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

저는 네이티브 iOS 줌을 비활성화하고 대신 자바스크립트에서 줌 기능을 구현함으로써 제가 본 다른 것과는 다른 새로운 해결책을 발견했습니다.

/방향 변경 문제에 대한 다양한 다른 해결책에 대한 훌륭한 배경은 세르지오 로페스(Sérgio Lopes)에 의한 것입니다.

<!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가 탑재된 아이패드2에서 모바일 사파리를 이용해 테스트만 했습니다.

포커스()/블러()는 방향을 변경하거나 몇 번 확대/축소한 후 발생할 수 있는 확대/축소 기능의 간헐적인 잠금을 방지하기 위한 해결책입니다.

document.body.style을 설정하면 전체 화면 재도장이 강제로 수행되므로 확대/축소 후 재도장이 심하게 실패하는 간헐적인 문제가 발생하지 않습니다.

엘리자베스는 메타태그에 "id" 속성을 추가하여 뷰포트 내용을 동적으로 변경할 수 있습니다.

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

그러면 javascript로 전화하면 됩니다.

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

매우 쉽게 구현할 수 있는 해결책을 찾았습니다.양식 완성 시 글꼴 크기가 50px인 텍스트 요소에 포커스를 설정합니다.텍스트 요소를 숨길 경우에는 작동하지 않는 것처럼 보이지만 요소 색상 속성을 불투명하게 설정하면 이 요소를 숨길 수 있습니다.

여기 또 다른 방법이 있는데, 효과가 좋을 것 같습니다.

  1. 뷰포트를 축소=1로 제한하도록 메타 태그를 설정합니다. 그러면 확대/축소가 방지됩니다.

    < meta name="viewport" content="width=장치-폭, 초기규모=1, 최소규모=1, 최대규모=1">

  2. javascript로 메타태그를 1/2초 후에 줌을 허용하도록 변경합니다.

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

  3. 방향 변경 시 javascript를 다시 사용하여 페이지를 다시 로드합니다.

    window.on orientation change = function {function.location.float;};

장치 방향을 다시 잡을 때마다 처음에는 확대/축소 없이 페이지가 다시 로드됩니다.하지만 1/2초 후에는 줌 기능이 복원됩니다.

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

반응형