阻止移动网页上的设备旋转

64

我能否使用Javascript在我的页面上检测到用户以纵向模式使用移动设备访问,并在用户将其手机旋转到横向时停止方向更改? 我的页面上有一款游戏,仅针对纵向显示进行了优化,我不希望它在横向模式下显示。


9
好的,但我在我的网页上用HTML5和JS制作了手机游戏,在横向旋转时不可能看到整个屏幕。 - qqryq
3
为什么不检测屏幕旋转,然后向用户显示只能在竖屏模式下查看的消息,而不是阻止旋转呢? - MrBliz
我不同意“像那样接管用户设备”总是不好的说法。随着现代手机传感器功能如此强大,我们能够编写依赖于手机方向和移动的应用程序。当利用这些传感器功能时,屏幕翻转会成为一个阻碍问题!现在是解决这个问题的时候了。 - lonce
58
@MrBliz - 哎呀,这里有太多自以为是的评论,这些人认为每个网站都像博客一样。你好吗?现在已经是2015年了。响应式设计很酷,但对于那些设计为固定方向的成千上万个网络应用和游戏来说是不合适的。开发者完全没有责任让复杂的HTML5游戏或应用程序在所有方向上都能工作。 - Bangkokian
1
当用户希望锁定方向时的示例:如果网站设计用于与连接到屏幕(模拟触摸)的操纵杆一起使用。例如,使用手机控制遥控汽车。您不希望屏幕旋转,因此操纵杆的触摸区域应该始终位于操纵杆所在位置,无论设备认为需要哪种方向。该网站始终可以为用户提供“解锁/锁定”设备方向更改的选项,因此,在这种情况下,锁定方向的API将提供最佳的用户体验。 - Jodes
显示剩余6条评论
9个回答

47

新的API正在开发中(目前已经可用)!

screen.orientation.lock();   // webkit only

screen.lockOrientation("orientation");

“方向”可以是以下任意一种:

portrait-primary - 表示屏幕在其主要纵向模式下的方向。如果设备以垂直方式保持在其正常位置,并且该位置为纵向,则被认为屏幕处于其主纵向模式。或者,如果设备的正常位置为横向并且将其顺时针旋转90度,则设备被认为处于其主纵向模式中。 正常位置取决于设备。

portrait-secondary - 表示屏幕在其次要纵向模式下的方向。如果将设备从其正常位置反转180º并且该位置为纵向,则被认为屏幕处于其次要纵向模式。或者,如果设备的正常位置为横向并将其逆时针旋转90度,则设备被认为处于其次要纵向模式中。 正常位置取决于设备。

landscape-primary - 表示屏幕在其主要横向模式下的方向。如果设备以横向方式保持在其正常位置,并且该位置为横向,则被认为屏幕处于其主横向模式。或者,如果设备的正常位置为纵向并将其顺时针旋转90度,则设备被认为处于其主横向模式中。 正常位置取决于设备。

landscape-secondary - 表示屏幕在其次要横向模式下的方向。如果将设备从其正常位置反转180º并且该位置为横向,则被认为屏幕处于其次要横向模式。或者,如果设备的正常位置为纵向并将其逆时针旋转90度,则设备被认为处于其次要横向模式中。 正常位置取决于设备。

portrait - 表示纵向模式(包括主要和次要)。

landscape - 表示横向模式(包括主要和次要)。

default - 表示根据设备的自然方向选择纵向或横向(主要模式)。例如,如果面板分辨率为1280 * 800,默认值将使其成为横向,如果分辨率为800 * 1280,则默认值将使其成为纵向。

Mozilla建议向屏幕添加lockOrientationUniversal以使其更具跨浏览器兼容性。

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

获取更多信息,请访问此处(已弃用的API):https://developer.mozilla.org/en-US/docs/Web/API/Screen/lockOrientation


现代API文档在MDN的这里: https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock


5
在安卓版Chrome中似乎没有任何影响。 - Mark
2
API又变了(再次)。这里显示的“仅限webkit”的内容现在是官方API:https://w3c.github.io/screen-orientation/#examples - zhirzh
6
Safari(iOS)怎么办? - N.K
这个答案需要根据新的规范进行更新。 - Paulo Galdo Sandoval
Screen.lockOrientation已被弃用,请更新您的答案。 - Tomás

22
在启用JavaScript的浏览器中,很容易确定屏幕是横向还是纵向,并使用CSS进行补偿。给用户提供禁用此功能的选项或者至少警告他们设备旋转将无法正常工作可能会有帮助。

编辑

检查浏览器宽度与高度之间的差异是检测浏览器方向的最简单方法。这也有一个优点,您将知道游戏是否在自然横向模式下播放(如PSP等某些移动设备)。这比尝试禁用设备旋转更有意义。

编辑2

Daz已经展示了如何检测设备方向,但仅检测方向只是解决问题的一半。如果想要反转自动方向更改,则需要将所有内容旋转90°或270°/-90°,例如:
$(window).bind('orientationchange resize', function(event){
  if (event.orientation) {
    if (event.orientation == 'landscape') {
      if (window.rotation == 90) {
        rotate(this, -90);
      } else {
        rotate(this, 90);
      }
    }
  }
});

function rotate(el, degs) {
  iedegs = degs/90;
  if (iedegs < 0) iedegs += 4;
  transform = 'rotate('+degs+'deg)';
  iefilter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+iedegs+')';
  styles = {
    transform: transform,
    '-webkit-transform': transform,
    '-moz-transform': transform,
    '-o-transform': transform,
    filter: iefilter,
    '-ms-filter': iefilter
  };
  $(el).css(styles);
}

注意:如果您想在IE中以任意角度旋转(用于其他目的),则需要使用矩阵变换,例如:
rads = degs * Math.PI / 180;
m11 = m22 = Math.cos(rads);
m21 = Math.sin(rads);
m12 = -m21;
iefilter = "progid:DXImageTransform.Microsoft.Matrix("
  + "M11 = " + m11 + ", "
  + "M12 = " + m12 + ", "
  + "M21 = " + m21 + ", "
  + "M22 = " + m22 + ", sizingMethod = 'auto expand')";
styles['filter'] = styles['-ms-filter'] = iefilter;

—或者使用CSS Sandpaper。此外,这将应用旋转样式到窗口对象,我实际上从未测试过,也不知道是否有效。您可能需要将样式应用于文档元素。

无论如何,我仍然建议简单地显示一条消息,要求用户在纵向模式下玩游戏。


2
你在 $(window).bind 函数中漏掉了一个闭合括号,并且在 rotation() 函数中有一个多余的括号。 - Raptor
"window.rotation == 90" 这是机器特定的代码吗? - N.K
@N.K 我认为这个值实际上对于不同的设备是不同的。而且,事实上,它甚至不叫做 window.rotation。我能找到的所有参考都是关于 window.orientation 的。我可能打错了字,或者可用的 API 在7年前是不同的。等我有空闲时间时,我将尝试调试并修订代码。 - Lèse majesté
我有一个React App。我希望在移动设备上保持它的竖屏视图。能否得到一个直截了当的答案? - MadHatter

17

1
媒体查询似乎是可行的方式。 - bholben
这不会只是在其他方向上隐藏用户界面吗?理想情况下,用户界面将保持在首选方向中,但不会被隐藏。 - Paul Razvan Berg
这将仅针对纵向方向使用 style_p.css 样式表,您不应该为主要的样式表添加它。 - Facundo Colombier

7

简单的Javascript代码可以让移动浏览器在纵向或横向显示。

(虽然在两个DIV中必须输入html代码两次(每种模式一个),但可以说这比使用JavaScript更改样式表加载速度更快...)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Mobile Device</title>
<script type="text/javascript">
// Detect whether device supports orientationchange event, otherwise fall back to
// the resize event.
var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    if(window.orientation==0)
    {
      document.getElementById('portrait').style.display = '';
      document.getElementById('landscape').style.display = 'none';
    }
    else if(window.orientation==90)
    {
      document.getElementById('portrait').style.display = 'none';
      document.getElementById('landscape').style.display = '';
    }
}, false);
</script>
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no" />
</head>
<body>
<div id="portrait" style="width:100%;height:100%;font-size:20px;">Portrait</div>
<div id="landscape" style="width:100%;height:100%;font-size:20px;">Landscape</div>

<script type="text/javascript">
if(window.orientation==0)
{
  document.getElementById('portrait').style.display = '';
  document.getElementById('landscape').style.display = 'none';
}
else if(window.orientation==90)
{
  document.getElementById('portrait').style.display = 'none';
  document.getElementById('landscape').style.display = '';
}
</script>
</body>
</html>

已在Android HTC Sense和Apple iPad上进行测试并可用。


5

通过新的CSS3特性,您可以旋转页面以相反的方向旋转。很抱歉,不支持IE7-。:(.

var rotate = 0 - window.orientation;
setAttribute("transform:rotate("+rotate+"deg);-ms-transform:rotate("+rotate+"deg);-webkit-transform:rotate("+rotate+"deg)", "style");

1
你会如何将此实现到代码中?(在index.html文件中) - basickarl
@KarlMorrison 在 JavaScript 中 - Qvcool
5
呵呵,我真的很喜欢这个修复方案的邪恶感 :) - Justus Romijn

1
这个解决方案对我很有用,它只是在横向时将整个页面旋转90度(有效地锁定屏幕为纵向)。我不能选择其他一些选项,因为我需要支持Safari。
@media screen and (min-width: 320px) and (max-width: 767px) and (orientation: landscape) {
  html {
    transform: rotate(-90deg);
    transform-origin: left top;
    width: 100vh;
    overflow-x: hidden;
    position: absolute;
    top: 100%;
    left: 0;
  }
}

在这里找到它:https://css-tricks.com/snippets/css/orientation-lock/


0

#rotate-device {
    width: 100%;
    height: 100%;
    position: fixed;
    z-index: 9999;
    top: 0;
    left: 0;
    background-color: #000;
    background-image: url(/path to img/rotate.png);
    background-size: 100px 100px;
    background-position: center;
    background-repeat: no-repeat;
    display: none;
}

@media only screen and (max-device-width: 667px) and (min-device-width: 320px) and (orientation: landscape){
 #rotate-device {
  display: block;
 }
}
<div id="rotate-device"></div>



0

您可以使用screenSize.width和screenSize.height属性,并检测宽度>高度的情况,然后处理该情况,可以通过让用户知道或根据需要调整屏幕来实现。

但最好的解决方案是@Doozer1979所说的...为什么要覆盖用户的偏好?


3
用户表示:很多时候当我的手机从竖屏旋转到横屏时,这是意料之外且不期望的。我可以列出一份网站清单,其中我永远不想使用横屏模式,如果这些网站锁定旋转功能,对我来说会是一个好事。 - user1172763

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