Javascript 方向改变后的移动视口高度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12452349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mobile viewport height after orientation change
提问by Dan Kanze
I am attaching a listener to the orientationchange
event:
我正在为orientationchange
事件附加一个侦听器:
window.addEventListener('orientationchange', function () {
console.log(window.innerHeight);
});
I need to get the height of the document after the orientationchange
. However, the event is triggered before the rotation is complete. Therefore, the recorded height reflects the state before the actual orientation change.
我需要在orientationchange
. 但是,该事件在轮换完成之前被触发。因此,记录的高度反映了实际方向改变之前的状态。
How do I register an event that would allow me to capture element dimensions after the orientation change has been completed?
如何注册允许我在方向更改完成后捕获元素尺寸的事件?
采纳答案by Dan Kanze
Orientation change needs a delay to pick up on the new heights and widths. This works 80% of the time.
方向变化需要延迟才能适应新的高度和宽度。这在 80% 的情况下都有效。
window.setTimeout(function() {
//insert logic with height or width calulations here.
}, 200);
回答by Christopher Bull
Use the resize event
使用调整大小事件
The resizeevent will include the appropriate width and height after an orientationchange, but you do not want to listen for all resize events. Therefore, we add a one-off resize event listener after an orientation change:
该调整大小事件将包括一个经过适当的宽度和高度orientationchange,但你不希望监听所有的调整大小事件。因此,我们在方向更改后添加一次性调整大小事件侦听器:
Javascript:
Javascript:
window.addEventListener('orientationchange', function() {
// After orientationchange, add a one-time resize event
var afterOrientationChange = function() {
// YOUR POST-ORIENTATION CODE HERE
// Remove the resize event listener after it has executed
window.removeEventListener('resize', afterOrientationChange);
};
window.addEventListener('resize', afterOrientationChange);
});
jQuery:
jQuery:
$(window).on('orientationchange', function() {
// After orientationchange, add a one-time resize event
$(window).one('resize', function() {
// YOUR POST-ORIENTATION CODE HERE
});
});
Do NOT use timeouts
不要使用超时
Timeouts are unreliable - some devices will fail to capture their orientation change within your hard-coded timeouts; this can be for unforeseen reasons, or because the device is slow. Fast devices will inversely have an unnecessary delay in the code.
超时是不可靠的——某些设备将无法在您的硬编码超时内捕获它们的方向变化;这可能是由于不可预见的原因,或者是因为设备速度很慢。相反,快速设备会在代码中产生不必要的延迟。
回答by kizzx2
Gajus' and burtelli's solutions are robust but the overhead is high. Here is a slim version that's reasonably fast in 2017, using requestAnimationFrame
:
Gajus 和 burtelli 的解决方案很健壮,但开销很高。这是一个在 2017 年相当快的超薄版本,使用requestAnimationFrame
:
// Wait until innerheight changes, for max 120 frames
function orientationChanged() {
const timeout = 120;
return new window.Promise(function(resolve) {
const go = (i, height0) => {
window.innerHeight != height0 || i >= timeout ?
resolve() :
window.requestAnimationFrame(() => go(i + 1, height0));
};
go(0, window.innerHeight);
});
}
Use it like this:
像这样使用它:
window.addEventListener('orientationchange', function () {
orientationChanged().then(function() {
// Profit
});
});
回答by Gajus
There is no way to capture the end of the orientation change event because handling of the orientation change varies from browser to browser. Drawing a balance between the most reliable and the fastest way to detect the end of orientation change requires racing interval and timeout.
无法捕获方向更改事件的结束,因为对方向更改的处理因浏览器而异。在检测方向变化结束的最可靠和最快方法之间取得平衡需要比赛间隔和超时。
A listener is attached to the orientationchange
. Invoking the listener starts an interval. The interval is tracking the state of window.innerWidth
and window.innerHeight
. The orientationchangeend
event is fired when noChangeCountToEnd
number of consequent iterations do not detect a value mutation or after noEndTimeout
milliseconds, whichever happens first.
侦听器附加到orientationchange
. 调用侦听器开始一个间隔。的间隔被跟踪的状态window.innerWidth
和window.innerHeight
。orientationchangeend
当noChangeCountToEnd
后续迭代次数未检测到值突变或在noEndTimeout
几毫秒后(以先发生者为准)时,将触发该事件。
var noChangeCountToEnd = 100,
noEndTimeout = 1000;
window
.addEventListener('orientationchange', function () {
var interval,
timeout,
end,
lastInnerWidth,
lastInnerHeight,
noChangeCount;
end = function () {
clearInterval(interval);
clearTimeout(timeout);
interval = null;
timeout = null;
// "orientationchangeend"
};
interval = setInterval(function () {
if (global.innerWidth === lastInnerWidth && global.innerHeight === lastInnerHeight) {
noChangeCount++;
if (noChangeCount === noChangeCountToEnd) {
// The interval resolved the issue first.
end();
}
} else {
lastInnerWidth = global.innerWidth;
lastInnerHeight = global.innerHeight;
noChangeCount = 0;
}
});
timeout = setTimeout(function () {
// The timeout happened first.
end();
}, noEndTimeout);
});
I am maintaining an implementation of orientationchangeend
that extends upon the above described logic.
我正在维护一个orientationchangeend
扩展到上述逻辑的实现。
回答by burtelli
I used the workaround proposed by Gajus Kuizunas for a while which was reliable albeit a bit slow. Thanks, anyway, it did the job!
我使用了 Gajus Kuizunas 提出的解决方法一段时间,虽然有点慢,但它是可靠的。谢谢,无论如何,它完成了工作!
If you're using Cordova or Phonegap I found a faster solution - just in case someone else faces this problem in the future. This plugin returns the correct width/height values right away: https://github.com/pbakondy/cordova-plugin-screensize
如果您使用 Cordova 或 Phonegap,我找到了一个更快的解决方案 - 以防其他人将来遇到这个问题。此插件立即返回正确的宽度/高度值:https: //github.com/pbakondy/cordova-plugin-screensize
The returned height and width reflect the actual resolution though, so you might have to use window.devicePixelRatio to get viewport pixels. Also the title bar (battery, time etc.) is included in the returned height. I used this callback function initally (onDeviceReady)
不过,返回的高度和宽度反映了实际分辨率,因此您可能必须使用 window.devicePixelRatio 来获取视口像素。标题栏(电池、时间等)也包含在返回的高度中。我最初使用了这个回调函数(onDeviceReady)
var successCallback = function(result){
var ratio = window.devicePixelRatio;
settings.titleBar = result.height/ratio-window.innerHeight;
console.log("NEW TITLE BAR HEIGHT: " + settings.titleBar);
};
In your orientation change event handler you can then use:
在您的方向更改事件处理程序中,您可以使用:
height = result.height/ratio - settings.titleBar;
to get the innerHeight right away. Hope this helps someone!
立即获得innerHeight。希望这可以帮助某人!
回答by Coisox
I also faced the same problem. So I ended up using:
我也面临同样的问题。所以我最终使用了:
window.onresize = function(){ getHeight(); }
回答by sudazzle
It is an experimental feature and gives the right innerHeight and innerWidth after screen orientation is changed.
这是一项实验性功能,可在屏幕方向更改后提供正确的innerHeight 和innerWidth。
window.screen.orientation.addEventListener('change', function(){
console.log(window.innerHeight)
})
I think listening to window resize is the safest way to implement screen orientation change logic.
我认为听窗口调整大小是实现屏幕方向更改逻辑的最安全方法。
回答by Kevin
It is important to note that orientationchange will not get the height after the change, but rather before. Use resize to accomplish this.
需要注意的是,orientationchange 不会得到改变后的高度,而是得到改变之前的高度。使用调整大小来完成此操作。
$(window).bind('orientationchange', function (e) {
var windowHeight = $(window).innerHeight();
console.log('Before Orientation: Height = ' + windowHeight);
$(window).resize(function () {
windowHeight = $(window).innerHeight();
console.log('After Orientation: Height = ' + windowHeight);
});
});
回答by Meursault
I solved this issue combining a couple of the above solutions. Resize would fire 4-5 times. Using .one, it fired too early. A short time out added to Christopher Bull's solution did the trick.
我结合上述几个解决方案解决了这个问题。调整大小会触发 4-5 次。使用 .one,它触发得太早了。添加到 Christopher Bull 的解决方案中的短暂暂停起到了作用。
$(window).on('orientationchange', function () {
$(window).one('resize', function () {
setTimeout(reference_to_function, 100);
});
});
回答by coderuby
For people who just want the innerHeight
of the window object after the orientationchange
there is a simple solution. Use window.innerWidth
. The innerWidth
during the orientationchange
event is the innerHeight
after completion of the orientationchange
:
对于那些只想要innerHeight
窗口对象之后的人来说,orientationchange
有一个简单的解决方案。使用window.innerWidth
. 在innerWidth
该过程中orientationchange
的事件是innerHeight
的建成后orientationchange
:
window.addEventListener('orientationchange', function () {
var innerHeightAfterEvent = window.innerWidth;
console.log(innerHeightAfterEvent);
var innerWidthAfterEvent = window.innerHeight;
console.log(innerWidthAfterEvent);
console.log(screen.orientation.angle);
});
I am not sure if 180-degree changes are done in two 90 degree steps or not. Can't simulate that in the browser with the help of developer tools. But If you want to safeguard against a full 180, 270 or 360 rotation possibility it should be possible to use screen.orientation.angle
to calculate the angle and use the correct height and width. The screen.orientation.angle
during the event is the target angle of the orientationchange
event.
我不确定 180 度的变化是否以两个 90 度的步骤完成。无法借助开发人员工具在浏览器中模拟。但是,如果您想防止完全 180、270 或 360 度旋转的可能性,则应该可以使用screen.orientation.angle
来计算角度并使用正确的高度和宽度。在screen.orientation.angle
活动期间是目标角orientationchange
事件。