在方向改变时重新呈现网页的最佳方法是什么

What is the best method of re-rendering a web page on orientation change?

本文关键字:最佳 方法 是什么 网页 新呈现 方向 改变      更新时间:2023-09-26

我有一个流畅的CSS布局,当我改变方向时,它在iphone上的表现很糟糕。(刷新后看起来很好(。

我正在使用下面的代码来刷新方向更改页面,这很好-只是感觉这样做有点错误。有什么方法可以在不重新加载整个页面的情况下实现这一点吗?这是一个移动网站,我真的不想强迫用户加载页面两次。

var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
window.addEventListener(orientationEvent, function() {
    window.location.reload()
}, false);   

编辑:

在iphone上测试时的两个主要问题是:

我有一个100%宽的,有一个右对齐的背景图像。当我将方向从纵向更改为横向时,身体宽度保持为在纵向模式下的渲染方式,反之亦然。从横向到纵向,这更像是一个问题,因为页面太宽,而且似乎要渲染两次图像。

假设您的CSS已经在各种大小的移动设备屏幕上愉快地呈现,则需要在<头部>的模板。

例如,这将页面宽度设置为设备的屏幕宽度和100%的初始缩放。初始缩放在页面加载时应用,但在方向更改时不应用。

<meta name="viewport" content="width=device-width, initial-scale=1.0">

通过在视口中添加最大比例=1.0参数,您将强制iPad/iPhone保持缩放级别,并在方向更改时重新布局页面。这样做的缺点是它将禁用缩放。但是,其优点是可以通过媒体查询进行布局调整,以适合当前方向的方式呈现内容。你可以在这里阅读更多关于viewport的信息:选择viewport

现在转到媒体查询。您应该将媒体查询放在CSS文件的底部,并按照屏幕宽度从最小到最大的顺序。例如,取自Html5BoilerPlate CSS示例:

@media only screen and (min-width: 480px) {
  /* Style adjustments for viewports 480px and over go here */
}
@media only screen and (min-width: 768px) {
  /* Style adjustments for viewports 768px and over go here */
}

所以你所有的普通样式都在这之上,并且首先应用,然后如果屏幕是480px或更宽,则应用下一个样式块,然后如果页面是768px或更广,则应用最后一个样式区块。

通过将固定缩放级别合并为1.0和媒体查询,您可以在没有javascript的情况下根据屏幕大小和方向调整网站的大小。显然,你需要确保网站设计良好,这样用户就不需要缩放。如果你的网站针对移动设备进行了优化,这应该不会成为问题。

请注意:其他非safari移动浏览器可能会在不设置视口最大比例的情况下重新布局页面。但这种行为是不一致的,大多数开发人员似乎都在迎合苹果设备,即使实现比其他设备更糟糕。其他一些设备将保持缩放级别,并在方向更改时重新居中视口。但所有设备都可以将缩放级别固定为1.0。

2015更新

所有其他答案都不正确或过时了。以下是有效的:

  window.addEventListener('orientationchange', function () {
    var originalBodyStyle = getComputedStyle(document.body).getPropertyValue('display');
    document.body.style.display='none';
    setTimeout(function () {
      document.body.style.display = originalBodyStyle;
    }, 10);
  });

该代码侦听orientationchange事件,并通过隐藏body元素并在10毫秒后显示它来强制其重新流动。它不依赖于任何<meta>标签或媒体查询。

其他答案建议使用媒体查询,但您已经使用了,因为您说过"刷新后看起来很好"。

其他一些答案建议使用location.reload()。这是非常低效的,因为它会重新加载整个页面,包括图像等。特别是在移动设备上,你不想这样做。

然而,其他答案建议添加<meta name="viewport" content="width=device-width, initial-scale=1.0">或其变体。从Safari 7开始,此功能不再有效。这是一个演示。为了确保你看到它是如何不起作用的,从横向模式下的iPad开始,加载页面,然后旋转。请注意,尽管一直使用flexbox,但页面并没有完全展开。

将其与我们在生产中使用隐藏/显示主体技术的本页进行比较。

使用了一种方法,该方法会在单个javascript堆栈帧中导致重新绘制和回流。不热衷于视口特定的答案,因为保持缩放等通常是对可访问性的要求。

$(window).on('orientationchange', function() {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
}); 

或非jquery等效

window.addEventListener('orientationchange', function () {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
});

根据我的经验,最好的方法是像这样使用

<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width /">
<meta name="apple-mobile-web-app-capable" content="yes"/>

根据我的经验,像@BenSwayne那样操作不会在更改方向时重新缩放回初始比例。不知道为什么是

我也遇到过类似的问题,这就是我使用jQuery解决问题的方法。

在我的情况下,<nav>元素的样式没有正确更改。我使用了kidkaos77代码的修改版本和$.get(),只加载页面的某个部分:

$(window).bind("resize",function() {
    //on resize reload only nav & replace
    $.get("index.php" +  ' nav', function(data) {
        $("nav").replaceWith($(data).find("nav"));
    });
});

使用这种方法,您不必重新加载整个页面,但您必须准确地指定哪些元素受到方向更改的影响,在您的情况下,似乎只需要一个div。

另一个选项可以是添加&从html元素(div、var、span等(中删除CSS类。这样,您可以只修改给您带来麻烦的元素,如果用户调整浏览器窗口的大小,您还可以调整非移动浏览器上的内容。

以下是您需要的Javascript/JQuery代码:

// Code to run when page has finished loading
$(function() {
    // Add CSS-class to body depending on device platform using user agent string
    // You can add more validations here and/or separate Android from iPhone or add more customized classes like "landscape_iPad", "landscape_iPhone", etc.
   // You can also validate browser types and add classes like "background_IE" or "background_Chrome", etc
    if ((navigator.userAgent.indexOf("iPad") != -1)) {
        $("#background").addClass("landscape");
    } else if ((navigator.userAgent.indexOf("Android") != -1) || (navigator.userAgent.indexOf("iPhone") != -1) || 
    (navigator.userAgent.indexOf("iPhone") != -1)) {
        $("body").addClass("iPhone");
    }
    // Get the initial orientation on iOS devices
    if (!isNaN(window.orientation)) {
        var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
        // Index php
        $("#background").addClass(orientation);
    } else {
        // Choose layout depending on viewport/window width
        var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
        // Index php
        $("#background").addClass(orientation);
    }
    // Bind orientationChange (or viewport/window size changes)
    if (window.onorientationchange != undefined) {
        window.onorientationchange = function() {
            var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
            // Index php
            $("#background").removeClass("portrait landscape").addClass(orientation);
        }
    } else {
        // Use landscape styling if it's wider than 980 pixels. 
        // This is for non mobile browsers, this way if the user resize the browser window, content will adjust too.
        $(window).bind('resize', function(){
            var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
            // Index php
            $("#background").removeClass("portrait landscape").addClass(orientation);
        });
    }
});

下面是示例元素"background"的CSS类:

#background.portrait {
    position:absolute;
    top:0px;
    left:0px;
    width:768px;
    height:946px;
    z-index:0;
    background:url(background.png) top center no-repeat;
}
#background.landscape {
    position:absolute;
    top:10px;
    left:20px;
    width:1024px;
    height:724px;
    z-index:0;
    background:url(background_landscape.png) top center no-repeat;
}

通过这种方式,您可以自定义横向和纵向行为,还可以添加更多类,如:"landscape_iPhone"、"portrait_Android"或控制每个特定设备的页面渲染所需的任何类。

此外,您不需要重新加载页面,它会动态调整页面。

希望它能帮助你或其他人=(,这使我能够使用相同的HTML但不同的CSS类为每个屏幕大小、移动品牌甚至浏览器类型创建自定义网站。

试试这样的东西:

$(function(){
    changeOrientation(window.orientation == 0 ? "portrait" : "landscape");
    $('body').bind('orientationchange',function(event){
        changeOrientation(event.orientation)
    });
    function changeOrientation(ori){
        $("#orientation").removeClass('portrait landscape');
        $("#orientation").addClass(ori);
    }     
});
$(window).bind('resize', function() { location.reload(); });

这个代码对我有效。