ChatGPT解决这个技术问题 Extra ChatGPT

如何在 iOS 上使用 Phonegap 正确检测方向变化?

我在下面寻找 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;
  }
}

B
Basheer AL-MOMANI

这就是我所做的:

函数 doOnOrientationChange() { switch(window.orientation) { case -90: case 90: alert('landscape');休息;默认值:警报(“肖像”);休息; } } window.addEventListener('orientationchange', doOnOrientationChange); // 如果需要,初始执行 doOnOrientationChange();

2019 年 5 月更新window.orientation 是一项已弃用的功能,大多数浏览器不支持 according to MDNorientationchange 事件是 associated with window.orientation,因此可能不应该使用。


这是本次讨论中唯一对我有用的解决方案:) +1
我做了window.onorientationchange = function() { setTimeout(functionName, 0); };
出于兴趣,您为什么使用 setTimeout Kirk?
当心!这是特定于设备的 - 度数是指与设备标准方向的差异。换句话说,如果平板电脑设计为横向使用,那么 90 将意味着它处于纵向模式。作为解决此问题的方法,我最初检查窗口的高度与宽度以存储方向,并在有变化时使用orientationchange 来更新它。
此外,我发现在更改宽度和高度之前会触发orientationchange,因此需要一点延迟才能使用宽度和高度正确检测方向。为此,我存储当前方向,当检测到变化时,我检查方向的变化,以 50 毫秒为增量,直到 250 毫秒。一旦发现差异,我就会相应地更新页面。在我的 Nexus 5 上,它通常会在 150 毫秒后检测到宽度与高度的差异。
h
hndcrftd

我使用 window.onresize = function(){ checkOrientation(); } 而在 checkOrientation 中,您可以使用 window.orientation 或 body width 检查,但想法是,“window.onresize”是最跨浏览器的方法,至少对于我的大多数移动和桌面浏览器来说我有机会测试。


这是一个很好的观点。如果您正在使用面向 Web 的技术进行开发,则此方法允许您在浏览器中更轻松地进行调试和测试,而不是每次都进行部署/模拟。
这根本不行......因为当键盘出现时它会调整大小(这不是唯一的情况)。所以这是一个很大的不!
@HellBaby当键盘出现时,该函数将被调用,但是,根据您用于方向检测的方法,它将检测到方向没有改变,就像window.orientation一样。所以我仍然坚持我的答案。
@Raine 我在 Ipad 4 上使用了该方法,但由于该问题而被迫更改它。所以也许它适用于某些设备,但不适用于所有设备..
@MattRay 您可以使用能够模拟此类设备行为的最新开发工具包轻松测试方向更改。
A
Alyssa Reyes
if (window.matchMedia("(orientation: portrait)").matches) {
   // you're in PORTRAIT mode
}

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

您可以将其附加到 resize 事件。但是,IIRC,这些查询将无法在键盘启动时正常工作。
D
Dan

我对 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 组 for the term "orientation" 可能会有一些运气。

我读到的一个关于如何检测方向的例子是 Pie Guy:(game, js file)。它类似于您发布的代码,但像您一样......我无法让它工作。

一个警告: eventListener 为我工作,但我不确定这是否是一种过于密集的方法。到目前为止,这是对我有用的唯一方法,但我不知道是否有更好、更精简的方法。

UPDATE 修复了上面的代码,它现在可以工作了


A
Alexey Grinko

虽然这个问题只涉及 PhoneGap 和 iOS 的使用,虽然已经回答了,但我可以在 2019 年用 JS 检测屏幕方向的更广泛问题补充几点:

window.orientation 属性已弃用且不受 Android 浏览器支持。有一个更新的属性可提供有关方向的更多信息 - screen.orientation。但它仍然是实验性的,iOS Safari 不支持。所以为了达到最好的效果,你可能需要结合使用两者: const angle = screen.orientation ? screen.orientation.angle:window.orientation。正如@benallansmith 在他的评论中提到的那样,window.onorientationchange 事件是在 window.onresize 之前触发的,因此除非在orientationchange 事件之后添加一些延迟,否则您将无法获得屏幕的实际尺寸。有一个 Cordova Screen Orientation Plugin 用于支持旧的移动浏览器,但我相信现在没有必要使用它。还有一个 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 事件也会被触发 when virtual keyboard is toggled,不仅是在方向改变时。


谢谢,那种拯救我的背后!我先尝试了cordova插件,然后是current-device;但是您完全正确,自己构建它非常容易。我对它做了一个指令,并称之为一天
o
oncode

在使用 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)
  });
}

W
WebWanderer

我相信正确的答案已经发布并被接受,但是有一个我自己经历过的问题以及其他一些人在这里提到的问题。

在某些平台上,窗口尺寸(window.innerWidthwindow.innerHeight)和 window.orientation 属性等各种属性在事件 "orientationchange" 触发时不会更新。很多时候,属性 window.orientation"orientationchange" 触发后的几毫秒内是 undefined(至少在 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);

我正在检查方向是否未定义或方向是否等于检测到的最后一个方向。如果其中一个为真,我等待十毫秒,然后再次解析方向。如果方向是合适的值,我调用 showXOrientation 函数。如果方向无效,我继续循环我的检查函数,每次等待十毫秒,直到它有效。

现在,我会像往常一样为此制作一个 JSFiddle,但 JSFiddle 并没有为我工作,我对它的支持错误已关闭,因为没有其他人报告同样的问题。如果其他人想把它变成 JSFiddle,请继续。

谢谢!我希望这有帮助!


仅供参考,在最初的测试中,我发现了一个问题:我顺时针旋转了几次,一个警报说“横向:180”,即使我的设备在物理上是纵向的。
R
Raul Gomez

这是我所做的:

window.addEventListener('orientationchange', doOnOrientationChange);

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

L
Luigi

我找到了这段代码来检测设备是否处于横向,在这种情况下添加一个启动页面,上面写着“更改方向以查看该站点”。它适用于 iOS、android 和 windows 手机。我认为这非常有用,因为它非常优雅并且避免为移动站点设置横向视图。代码运行良好。唯一不完全令人满意的是,如果有人在横向视图中加载页面,则不会出现启动页面。

<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>


M
M Fauzi Riozi
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
    }
}

t
talonmies

以下对我有用:

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 的值不会立即更新


D
Danny Connell

我正在为 iPhone 的 PhoneGap 创建一个 jQTouch 应用程序。这几天我一直在和这个问题作斗争。我已经看过几次建议的事件监听器解决方案,但无法让它工作。

最后我想出了一个不同的解决方案。它基本上使用 settimeout 定期检查 body 的宽度。如果宽度为 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!');
}

将设备硬编码为 320 或 480 将来将无法使用,或者与当前的高分辨率手机一起使用。
1) 您应该使用将立即触发的 onresize 事件,而不是在 500 毫秒内 2) 此代码是 android 特定的,对于 iPhone 使用 onorientationchange 代替 3) 测试浏览器是否支持它:"onorientationchange" in window