iOS에서 Phonegap을 사용하여 방향 변경을 올바르게 감지하려면 어떻게합니까?


178

JQTouch 참조 자료를 찾고있는이 오리엔테이션 테스트 코드를 아래에서 찾았습니다. 이것은 모바일 Safari의 iOS 시뮬레이터에서는 올바르게 작동하지만 Phonegap에서는 올바르게 처리되지 않습니다. 내 프로젝트 가이 테스트 페이지를 죽이는 것과 동일한 문제가 발생했습니다. Phonegap에서 JavaScript를 사용하여 방향 변경을 감지하는 방법이 있습니까?

window.onorientationchange = function() {
  /*window.orientation returns a value that indicates whether iPhone is in portrait mode, landscape mode with the screen turned to the
    left, or landscape mode with the screen turned to the right. */
  var orientation = window.orientation;
  switch (orientation) {
    case 0:
      /* If in portrait mode, sets the body's class attribute to portrait. Consequently, all style definitions matching the body[class="portrait"] declaration
         in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "portrait");

      /* Add a descriptive message on "Handling iPhone or iPod touch Orientation Events"  */
      document.getElementById("currentOrientation").innerHTML = "Now in portrait orientation (Home button on the bottom).";
      break;

    case 90:
      /* If in landscape mode with the screen turned to the left, sets the body's class attribute to landscapeLeft. In this case, all style definitions matching the
         body[class="landscapeLeft"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the left (Home button to the right).";
      break;

    case -90:
      /* If in landscape mode with the screen turned to the right, sets the body's class attribute to landscapeRight. Here, all style definitions matching the
         body[class="landscapeRight"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the right (Home button to the left).";
      break;
  }
}

답변:


297

이것이 제가하는 것입니다:

function doOnOrientationChange() {
    switch(window.orientation) {  
      case -90: case 90:
        alert('landscape');
        break; 
      default:
        alert('portrait');
        break; 
    }
}
  
window.addEventListener('orientationchange', doOnOrientationChange);
  
// Initial execution if needed
doOnOrientationChange();


2019 년 5 월 업데이트 : window.orientation 는 더 이상 사용되지 않으며 MDN에 따라 대부분의 브라우저에서 지원되지 않습니다 . orientationchange이벤트입니다 window.orientation과 관련된 때문에 아마 사용하지 않아야합니다.



9
내가 한window.onorientationchange = function() { setTimeout(functionName, 0); };
Kirk Strobeck

11
관심이 없으면 setTimeout Kirk를 사용한 이유는 무엇입니까?
backdesk 2016 년

10
조심해! 이것은 장치마다 다릅니다. 도는 장치 표준 방향과의 차이를 나타냅니다. 다시 말해, 태블릿이 가로로 사용되도록 설계된 경우 90은 세로 모드임을 의미합니다. 이 문제를 해결하기 위해 처음에는 창의 높이 대 너비를 확인하여 방향을 저장하고 방향 변경을 사용하여 방향을 업데이트합니다.
benallansmith

15
또한 너비와 높이가 변경되기 전에 방향 변경이 발생한다는 것을 알았습니다. 따라서 너비와 높이를 사용하여 방향을 올바르게 감지하려면 약간의 지연이 필요합니다. 이를 위해 현재 방향을 저장하고 변경이 감지되면 250ms까지 50ms 단위로 방향 변경을 확인합니다. 차이가 발견되면 그에 따라 페이지를 업데이트합니다. Nexus 5에서는 일반적으로 150ms 후 너비와 높이 차이를 감지합니다.
benallansmith

24

나는 window.onresize = function(){ checkOrientation(); } checkOrientation에서 window.orientation 또는 body widthChecking을 사용할 수 있지만 아이디어는 "window.onresize"는 적어도 내가 가지고있는 모바일 및 데스크탑 브라우저의 대부분에서 가장 크로스 브라우저 방법입니다. 시험 기회.


1
이것은 좋은 지적입니다. 웹 연결 기술을 사용하여 개발하는 경우이 방법을 사용하면 매번 배포 / 시뮬레이션하는 대신 브라우저에서 더 쉽게 디버깅하고 테스트 할 수 있습니다.
Matt Ray

2
키보드가 나타나면 크기가 조정되기 때문에 이것이 유일한 것은 아닙니다. 그래서 이것에 대한 큰 아니오!
HellBaby

2
@HellBaby 키보드가 나타나면 방향 감지에 사용하는 방법에 따라 함수가 호출됩니다. window.orientation의 경우와 같이 방향이 변경되지 않았 음을 감지합니다. 그래서 나는 여전히 내 대답을 기다립니다.
hndcrftd

1
@Raine Ipad 4에서 해당 방법을 사용했으며 해당 문제의 원인을 변경해야했습니다. 따라서 일부 장치에서는 작동하지만 일부 장치에서는 작동하지 않을 수 있습니다.
HellBaby

1
@MattRay 이러한 종류의 장치 동작을 에뮬레이트 할 수있는 최신 개발 툴킷으로 방향 변경을 쉽게 테스트 할 수 있습니다.
kontur

14
if (window.matchMedia("(orientation: portrait)").matches) {
   // you're in PORTRAIT mode
}

if (window.matchMedia("(orientation: landscape)").matches) {
  // you're in LANDSCAPE mode
}

1
resize이벤트에 첨부 할 수 있습니다 . 그러나 IIRC, 이러한 쿼리는 키보드를 위로 올바로 작동하지 않습니다.
adi518 2016 년

12

나는 iOS와 Phonegap을 처음 접했지만 eventListener를 추가하여이를 수행 할 수있었습니다. 나는 당신이 참조 한 예제를 사용하여 같은 일을했고, 그것을 작동시키지 못했습니다. 그러나 이것은 트릭을 수행하는 것처럼 보였습니다.

// Event listener to determine change (horizontal/portrait)
window.addEventListener("orientationchange", updateOrientation); 

function updateOrientation(e) {
switch (e.orientation)
{   
    case 0:
        // Do your thing
        break;

    case -90:
        // Do your thing
        break;

    case 90:
        // Do your thing
        break;

    default:
        break;
    }
}

PhoneGap Google 그룹 에서 '동향'이라는 용어를 검색하면 운이 좋을 수 있습니다 .

오리엔테이션을 감지하는 방법에 대한 예제로 읽은 예는 Pie Guy : ( game , js file )입니다. 게시 한 코드와 비슷하지만 당신처럼 ... 나는 그것을 작동시킬 수 없었습니다.

한 가지주의 사항 : eventListener가 나를 위해 일했지만 이것이 지나치게 집중적 인 접근인지 확실하지 않습니다. 지금까지 그것은 나를 위해 일한 유일한 방법 이었지만 더 좋고 능률적 인 방법이 있는지 모르겠습니다.


업데이트 는 위의 코드를 수정하여 이제 작동합니다.


plese 이벤트 이름 수정
Dan

5

orientationchange이벤트로 작업하는 동안 페이지에서 요소의 정확한 크기를 얻으려면 시간 초과가 필요했지만 matchMedia는 정상적으로 작동했습니다. 내 최종 코드 :

var matchMedia = window.msMatchMedia || window.MozMatchMedia || window.WebkitMatchMedia || window.matchMedia;

if (typeof(matchMedia) !== 'undefined') {
  // use matchMedia function to detect orientationchange
  window.matchMedia('(orientation: portrait)').addListener(function() {
    // your code ...
  });
} else {
  // use orientationchange event with timeout (fires to early)
  $(window).on('orientationchange', function() {
    window.setTimeout(function() {
      // your code ...
    }, 300)
  });
}

3

정답이 이미 게시되어 승인되었지만 본인이 직접 경험 한 문제가 있으며 다른 사람들이 여기에 언급 한 문제가 있습니다.

특정 플랫폼에서 창 크기 ( window.innerWidth, window.innerHeight) 및 속성과 같은 다양한 속성 window.orientation은 이벤트 "orientationchange"가 시작된 시간까지 업데이트되지 않습니다 . 여러 번이 속성 window.orientationundefined발사 후 몇 밀리 초 동안 지속됩니다 "orientationchange"(적어도 iOS의 Chrome에 있음).

이 문제를 처리하는 가장 좋은 방법은 다음과 같습니다.

var handleOrientationChange = (function() {
    var struct = function(){
        struct.parse();
    };
    struct.showPortraitView = function(){
        alert("Portrait Orientation: " + window.orientation);
    };
    struct.showLandscapeView = function(){
        alert("Landscape Orientation: " + window.orientation);
    };
    struct.parse = function(){
        switch(window.orientation){
            case 0:
                    //Portrait Orientation
                    this.showPortraitView();
                break;
            default:
                    //Landscape Orientation
                    if(!parseInt(window.orientation) 
                    || window.orientation === this.lastOrientation)
                        setTimeout(this, 10);
                    else
                    {
                        this.lastOrientation = window.orientation;
                        this.showLandscapeView();
                    }
                break;
        }
    };
    struct.lastOrientation = window.orientation;
    return struct;
})();
window.addEventListener("orientationchange", handleOrientationChange, false);

방향이 정의되어 있지 않은지 또는 방향이 마지막으로 감지 된 방향과 같은지 확인하고 있습니다. 어느 쪽이든 참이면 10 밀리 초 기다린 다음 방향을 다시 구문 분석합니다. 방향이 적절한 값이면 showXOrientation함수를 호출합니다 . 방향이 유효하지 않으면 확인 기능을 계속 반복하여 유효 할 때까지 매번 10 밀리 초 동안 기다립니다.

이제는 평소처럼 JSFiddle을 만들 것입니다.하지만 JSFiddle은 저에게 효과적이지 않으며 다른 사람이 같은 문제를보고하지 않으므로 지원 버그가 마감되었습니다. 다른 사람이 이것을 JSFiddle로 바꾸고 싶다면 계속하십시오.

감사! 이게 도움이 되길 바란다!


참고로, 초기 테스트에서 문제가 발생했습니다. 시계 방향으로 두 번 회전하고 장치가 물리적으로 세로 방향 인 경우에도 "경치 방향 : 180"이라는 경고가 표시됩니다.
MarsAndBack

2

여기 내가 한 일이 있습니다.

window.addEventListener('orientationchange', doOnOrientationChange);

function doOnOrientationChange()
{
      if (screen.height > screen.width) {
         console.log('portrait');
      } else {
         console.log('landscape');
      }
}

2

이 질문은 PhoneGap 및 iOS 사용만을 언급하고 있지만 이미 답변되었지만 2019 년 JS로 화면 방향을 감지하는 더 넓은 질문에 몇 가지 사항을 추가 할 수 있습니다.

  1. window.orientation이 속성 은 더 이상 사용되지 않으며 Android 브라우저에서 지원되지 않습니다screen.orientation . 방향에 대한 자세한 정보를 제공하는 새로운 속성이 있습니다. 그러나 여전히 실험적이며 iOS Safari 에서는 지원되지 않습니다 . 따라서 최상의 결과를 얻으려면 다음 두 가지 조합을 사용해야합니다 const angle = screen.orientation ? screen.orientation.angle : window.orientation.

  2. 에서 언급 @benallansmith으로 자신의 의견 , window.onorientationchange이벤트 전에 해고 window.onresize하면 위해서 orientationchange 이벤트 후 약간의 지연을 추가하지 않으면 화면의 실제 크기를하지 않도록.

  3. 거기이다 플러그인 코르도바 화면 방향 오래된 모바일 브라우저를 지원하는,하지만 나는 요즘 사용에 필요가 없다 생각합니다.

  4. screen.onorientationchange이벤트 도 있었지만 더 이상 사용되지 않으며 사용 해서는 안됩니다. 답변의 완성을 위해 추가되었습니다.

내 유스 케이스에서는 실제 방향에 신경 쓰지 않고 창의 실제 너비와 높이에 대해 신경 쓰지 않았으며 방향에 따라 분명히 바뀝니다. 그래서 이벤트와 실제 윈도우 크기 resize사이의 지연을 처리하지 않기 위해 이벤트를 사용 했습니다 orientationchange.

window.addEventListener('resize', () => {
  console.log(`Actual dimensions: ${window.innerWidth}x${window.innerHeight}`);
  console.log(`Actual orientation: ${screen.orientation ? screen.orientation.angle : window.orientation}`);
});

참고 1 : 여기에서 EcmaScript 6 구문을 사용했습니다. 필요한 경우 ES5로 컴파일하십시오.

참고 2 : 방향이 변경 될뿐만 아니라 가상 키보드가 전환 될 때도window.onresize 이벤트가 발생 합니다.


1

기기가 가로 방향인지 여부를 감지하는이 코드를 찾았으며이 경우 "사이트를 보려면 방향 변경"이라는 스플래시 페이지를 추가하십시오. iOS, Android 및 Windows Phone에서 작동합니다. 나는 이것이 매우 우아하고 모바일 사이트의 가로보기를 설정하지 않기 때문에 매우 유용하다고 생각합니다. 코드가 잘 작동합니다. 완전히 만족스럽지 않은 유일한 방법은 누군가 가로 방향으로 페이지를로드하면 스플래시 페이지가 나타나지 않는다는 것입니다.

<script>
(function() {
    'use strict';

    var isMobile = {
        Android: function() {
            return navigator.userAgent.match(/Android/i);
        },
        BlackBerry: function() {
            return navigator.userAgent.match(/BlackBerry/i);
        },
        iOS: function() {
            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
        },
        Opera: function() {
            return navigator.userAgent.match(/Opera Mini/i);
        },
        Windows: function() {
            return navigator.userAgent.match(/IEMobile/i);
        },
        any: function() {
            return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
        }
    };
    if (isMobile.any()) {
        doOnOrientationChange();
        window.addEventListener('resize', doOnOrientationChange, 'false');
    }

    function doOnOrientationChange() {
        var a = document.getElementById('alert');
        var b = document.body;
        var w = b.offsetWidth;
        var h = b.offsetHeight;
        (w / h > 1) ? (a.className = 'show', b.className = 'full-body') : (a.className = 'hide', b.className = '');
    }
})();
</script>

그리고 HTML : <div id="alert" class="hide"> <div id="content">This site is not thought to be viewed in landscape mode, please turn your device </div> </div>


1
if (window.DeviceOrientationEvent) {
    // Listen for orientation changes
    window.addEventListener("orientationchange", orientationChangeHandler);
    function orientationChangeHandler(evt) {
        // Announce the new orientation number
        // alert(screen.orientation);
        // Find matches
        var mql = window.matchMedia("(orientation: portrait)");

        if (mql.matches)  //true
    }
}

-2

다음은 나를 위해 일했습니다.

function changeOrientation(){
switch(window.orientation) {
case 0: // portrait, home bottom
case 180: // portrait, home top
 alert("portrait H: "+$(window).height()+" W: "+$(window).width());       
 break;
          case -90: // landscape, home left
          case 90: // landscape, home right
        alert("landscape H: "+$(window).height()+" W: "+$(window).width());
            break;
        }
    }

 window.onorientationchange = function() { 
            //Need at least 800 milliseconds
            setTimeout(changeOrientation, 1000);
        }

값이 window.orientation즉시 업데이트되지 않기 때문에 시간 초과가 필요 했습니다.


-3

iPhone 용 PhoneGap에서 jQTouch 앱을 만들고 있습니다. 나는 며칠 동안이 문제와 싸우고있다. 이벤트 리스너 솔루션이 몇 번 제안했지만, 작동하지 못했습니다.

결국 나는 다른 해결책을 생각해 냈습니다. 기본적으로 settimeout을 사용하여 본문의 너비를 정기적으로 확인합니다. 너비가 320이면 방향은 세로이고 480이면 가로입니다. 그런 다음 마지막 확인 이후 방향이 변경된 경우 세로 방향 기능 또는 가로 방향 기능을 실행하여 각 방향에 대해 작업을 수행 할 수 있습니다.

코드 (참고로 코드에 반복이 있다는 것을 알고 있습니다. 아직 코드를 정리하지 않아도됩니다!) :

// get original orientation based on body width
deviceWidth = $('body').width();
if (deviceWidth == 320) {
    currentOrientation = "portrait";
}
else if (deviceWidth == 480) {
    currentOrientation = "landscape";
}

// fire a function that checks the orientation every x milliseconds
setInterval(checkOrientation, 500);

// check orientation
function checkOrientation() {
    deviceWidth = $('body').width();
    if (deviceWidth == '320') {
        newOrientation = "portrait";
    }
    else if (deviceWidth == '480') {
        newOrientation = "landscape";
    }
    // if orientation changed since last check, fire either the portrait or landscape function
    if (newOrientation != currentOrientation) {
        if (newOrientation == "portrait") {
            changedToPortrait();
        }
        else if (newOrientation == "landscape") {
            changedToLandscape();
        }
        currentOrientation = newOrientation;
    }
}

// landscape stuff
function changedToLandscape() {
    alert('Orientation has changed to Landscape!');
}

// portrait stuff
function changedToPortrait() {
    alert('Orientation has changed to Portrait!');
}

8
320 또는 480으로 장치를 하드 코딩하면 향후 또는 현재 고해상도 전화에서 작동하지 않습니다.
Fresheyeball

1
1) onresize500 밀리 초가 아닌 즉시 실행되는 이벤트를 사용해야합니다. 2)이 코드는 Android 전용이며 onorientationchangeiPhone 대신 사용 합니다. 3) 브라우저에서 지원되는지 테스트합니다."onorientationchange" in window
Dan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.