在iOS Safari中防止屏幕方向改变

34

当iOS设备旋转时,是否有可能避免在Safari中进行横向视图的切换?

iOS Safari具有"orentationchange"事件,我尝试拦截它并禁用默认行为,例如:

<html>
<head>
<script type="text/javascript">
function changeOrientation(event) {
    alert("Rotate");
    event.preventDefault();
}
</script>
</head>
<body onorientationchange="changeOrientation(event);">
PAGE CONTENT
</body>
</html>

但是在iPhone上测试页面时,当我旋转设备时,虽然弹出了警报,但视图却切换到了横向模式。似乎event.preventDefault()无法停止旋转。

有没有办法阻止这种行为?


1
相关链接:https://dev59.com/2HM_5IYBdhLWcg3w1G6N - xdhmoore
1
阅读由@xdhmoore链接的问题。除了这个问题,它非常值得一读。 - Boaz
10个回答

58

Jonathan Snook提供了解决此问题的方法。在他的幻灯片这里,他展示了如何(有点)锁定为竖屏(参见第54和55张幻灯片)。

来自这些幻灯片的JS代码:

window.addEventListener('orientationchange', function () {
    if (window.orientation == -90) {
        document.getElementById('orient').className = 'orientright';
    }
    if (window.orientation == 90) {
        document.getElementById('orient').className = 'orientleft';
    }
    if (window.orientation == 0) {
        document.getElementById('orient').className = '';
    }
}, true);

以及 CSS:

.orientleft #shell {
    -webkit-transform: rotate(-90deg);
    -webkit-transform-origin:160px 160px;
}

.orientright #shell {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin:230px 230px;
} 

我尝试在iPhone上实现横屏,但它从未完全正确地显示。然而,我用了下面这段jQueryian代码,接近实现了。代码应该放在onready函数中。另外请注意:这是在“添加到主屏幕”的上下文环境中使用的,我认为这会改变tranform-origin的位置。

$(window).bind('orientationchange', function(e, onready){
   if(onready){
       $(document.body).addClass('portrait-onready');
   }
   if (Math.abs(window.orientation) != 90){
       $(document.body).addClass('portrait');
   } 
   else {
       $(document.body).removeClass('portrait').removeClass('portrait-onready');
   }
});
$(window).trigger('orientationchange', true); // fire the orientation change event at the start, to make sure 

而且 CSS 代码是:

.portrait {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: 200px 190px;
}
.portrait-onready {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: 165px 150px;
}

希望这能帮助某人接近所需的结果...


你尝试将变换原点更改为0,0了吗? - tim
8
我点赞了这个,只是因为它让我笑得很开心。太巧妙了! - Westie
我有这个想法,但不确定它是否可行... 很高兴听到它确实可行 :D 这应该是被采纳的答案。 - nevelis
这个答案仍然有帮助。 - sayalok
聪明!这太棒了! - jmg
抱歉,如果我不明白,“#shell”是什么意思? - Dimitri Kopriwa

29

在移动版Safari中,无法强制设置特定方向;当用户旋转设备时,它将始终自动旋转。

或许您可以为不支持的方向显示一些内容,提示用户不支持该方向,并需要将设备旋转回来才能使用您的Web应用程序。


6

虽然您无法阻止设备屏幕方向发生变化,但是可以像其他答案中所述一样模拟不进行更改。

首先检测设备的屏幕方向或重新定向,并使用JavaScript向包装元素(在此示例中使用body标记)添加类名。

function deviceOrientation() {
  var body = document.body;
  body.classList = '';
  switch(window.orientation) {
    case 90:
      body.classList.add('rotation90');
      break;
    case -90:
      body.classList.add('rotation-90');
      break;
    default:
      body.classList.add('portrait');
      break;
  }
}
window.addEventListener('orientationchange', deviceOrientation);
deviceOrientation();

如果设备处于横屏状态,则使用CSS将body宽度设置为视口高度,将body高度设置为视口宽度。顺便设置一下变换原点。

@media screen and (orientation: landscape) {
  body {
    width: 100vh;
    height: 100vw;
    transform-origin: 0 0;
  }
}

现在,重新定位 body 元素并将其滑动(平移)到指定位置。
body.rotation-90 {
  transform: rotate(90deg) translateY(-100%);
}
body.rotation90 {
  transform: rotate(-90deg) translateX(-100%);
}

5

已经提出了一个实现此功能的规范

此外,还可以参考这个Chromium bug获取更多信息(尚不清楚它是否将在WebKit或Chromium中实现)。


3

也许在不久的未来...

截至2015年5月,有一项实验性功能可以做到这一点。但是它只能在Firefox 18+,IE11+和Chrome 38+上运行。

然而,它目前还不能在Opera或Safari上工作。

https://developer.mozilla.org/en-US/docs/Web/API/Screen/lockOrientation#Browser_compatibility

以下是兼容浏览器的当前代码:

var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation;

lockOrientation("landscape-primary");

3

以下解决方案似乎在2016年6月份对iPhone4、5、6和6+有效。

<script>
  /**
   * we are locking mobile devices orientation to portrait mode only
   */
  var devWidth, devHeight;
  window.addEventListener('load', function() {
    devWidth  = screen.width;
    devHeight = screen.height;
  });
  window.addEventListener('orientationchange', function () {
    if (devWidth < 768 && (window.orientation === 90 || window.orientation == -90)) {
      document.body.style.width = devWidth + 'px';
      document.body.style.height = devHeight + 'px';
      document.body.style.transform = 'rotate(90deg)';
      document.body.style.transformOrigin = ''+(devHeight/2)+'px '+(devHeight/2)+'px';
    } else {
      document.body.removeAttribute('style');
    }
  }, true);
</script>

1
我认为对于我们需要在屏幕上显示医学调查数据并提供一致视图的情况,设备屏幕的旋转是不允许的。我们将应用程序设计为仅支持竖屏模式。因此,最好的解决方案是要么锁定屏幕(无法通过浏览器完成),要么显示错误/消息,指示应用程序在方向固定之前无法使用。

0
我测试了这种方式,对我有效:
@media (orientation: portrait) {
  body {
    transform: rotate(-90deg);
  }
}

这是一个好主意,但有点不稳定 - 所以我使用了body display none而不是rotate。 - Tarek Adam

0

我还没有在iPhone上测试过,但你可以试试看

screen.orientation.lock('portrait');
screen.orientation.unlock();

更多信息请参考MDN


-6
如果可能的话(我不相信这是可能的),我强烈建议不要这样做。用户讨厌被强制以特定方式查看页面。如果他们正在使用iPhone坞站并且不能忍受横向模式而不将其取消对接,或者如果他们更喜欢横向键盘版本,因为键更大呢?如果您的设计需要特定方向,则可能需要重新考虑您的设计。

2
我正在构建的Web应用程序面向在城市步行的用户,因此我认为默认的竖屏视图可能是更自然的体验方式。我需要考虑不同的情况,感谢您指出这一点。 - Davide Gualano
13
如果你的应用程序使用设备方向事件,例如,当用户将设备在一个方向上移动得太远时,你不希望它自动旋转,对于游戏来说这会变得非常恼人。 - Adam M-W
9
这些评论非常傲慢。大多数非极客用户只使用这些“自定义视图”选项,因为他们所浏览的网页具有可用性和布局上的问题,或字体太小等。仅仅陈述用户想要灵活性是不太有帮助的。添加一个元标记以防止自动旋转内容是非常必要的-应用程序可以做到... - tim
4
如果你想让手机的界面看起来像一个实体物品,比如一张扑克牌,那么屏幕的方向变化就会显得无关紧要而且会分散注意力。换句话说,如果你的设计需要特定的屏幕方向,那么你可能发现了一个新的使用情景,这可能需要使用不同的技术来实现。 - Dean Radcliffe
2
另一个合理的用例是制作一个临时网站,它将被丢弃,因此我们不想花时间在一个完全响应式的网站上工作,但我们希望演示在客户的iPhone上看起来很好。同时,我不太喜欢那些只回答“不要这样做”的回答,而没有尝试回答提问者的问题以及对提问者表示尊重。 - xdhmoore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接