方向改变后的移动视口高度

时间:2012-09-17 02:03:28

标签: javascript html5 mobile viewport orientation-changes

我正在为orientationchange事件附加一个监听器:

window.addEventListener('orientationchange', function () {
    console.log(window.innerHeight);
});

我需要在orientationchange之后获得文档的高度。但是,事件在旋转完成之前触发。因此,记录的高度反映了实际方向变化之前的状态。

如何在方向更改完成后注册一个允许我捕捉元素尺寸的事件?

10 个答案:

答案 0 :(得分:14)

无法捕捉方向更改事件的结束,因为方向更改的处理因浏览器而异。在最可靠和最快速的检测方向变化结束方式之间取得平衡需要比赛间隔和超时。

监听器附加到orientationchange。调用侦听器会启动一个间隔。时间间隔正在跟踪window.innerWidthwindow.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);
    });

我正在维护orientationchangeend的实现,该实现扩展了上述逻辑。

答案 1 :(得分:13)

Gajus'和burtelli的解决方案非常强大,但开销很高。这是一个使用requestAnimationFrame

在2017年相当快的超薄版本
// 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);
  });
}

像这样使用:

window.addEventListener('orientationchange', function () {
    orientationChanged().then(function() {
      // Profit
    });
});

答案 2 :(得分:12)

使用调整大小事件

调整大小事件将在 orientationchange 后包含适当的宽度和高度,但您不希望侦听所有调整大小事件。因此,我们在方向更改后添加一次性调整大小事件侦听器:

的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

$(window).on('orientationchange', function() {
    // After orientationchange, add a one-time resize event
    $(window).one('resize', function() {
        // YOUR POST-ORIENTATION CODE HERE
    });
});

请勿使用超时

超时不可靠 - 某些设备无法在您的硬编码超时内捕获其方向变化;这可能是出于不可预见的原因,或者因为设备很慢。快速设备将在代码中反向产生不必要的延迟。

答案 3 :(得分:10)

方向变化需要延迟才能获得新的高度和宽度。这有80%的时间都有效。

window.setTimeout(function() {
    //insert logic with height or width calulations here.
}, 200);

答案 4 :(得分:2)

我使用了Gajus Kuizunas提出的解决方法一段时间,虽然有点慢但可靠。谢谢,无论如何,它完成了这项工作!

如果你正在使用Cordova或Phonegap,我找到了一个更快的解决方案 - 以防其他人将来遇到这个问题。此插件会立即返回正确的宽度/高度值:https://github.com/pbakondy/cordova-plugin-screensize

返回的高度和宽度反映了实际的分辨率,因此您可能必须使用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);
};

在您的方向更改事件处理程序中,您可以使用:

height = result.height/ratio - settings.titleBar;

立即获得内心高度。希望这有助于某人!

答案 5 :(得分:1)

我也遇到了同样的问题。所以我最终使用了:

window.onresize = function(){ getHeight(); }

答案 6 :(得分:1)

这是一项实验性功能,可在更改屏幕方向后提供正确的innerHeight和innerWidth。

window.screen.orientation.addEventListener('change', function(){
    console.log(window.innerHeight)
})

我认为,监听窗口调整大小是实现屏幕方向更改逻辑的最安全方法。

答案 7 :(得分:1)

请务必注意,方向更改不会在更改后获得高度,而是在更改之前。使用调整大小来完成此操作。

$(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);
    });
});

答案 8 :(得分:1)

我结合了以上两个解决方案解决了这个问题。调整大小会触发4-5次。使用.one,它触发得太早了。克里斯托弗·布尔(Christopher Bull)的解决方案中花了很短的时间就能解决问题。

$(window).on('orientationchange', function () {
  $(window).one('resize', function () {
    setTimeout(reference_to_function, 100);
  });
});

答案 9 :(得分:-1)

对于只需要innerHeight之后的orientationchange窗口对象的人来说,有一个简单的解决方案。使用window.innerWidthinnerWidth事件期间的orientationchangeinnerHeight完成后的orientationchange

window.addEventListener('orientationchange', function () {
    var innerHeightAfterEvent = window.innerWidth;
    console.log(innerHeightAfterEvent);
    var innerWidthAfterEvent = window.innerHeight;
    console.log(innerWidthAfterEvent);
    console.log(screen.orientation.angle);
});

我不确定是否以两个90度的步幅进行180度的更改。在开发人员工具的帮助下,无法在浏览器中进行模拟。但是,如果您想防止180、270或360度的旋转,可以使用screen.orientation.angle来计算角度并使用正确的高度和宽度。事件期间的screen.orientation.angleorientationchange事件的目标角度。