Каков наилучший метод повторного рендеринга веб-страницы при изменении ориентации? - PullRequest
28 голосов
/ 27 октября 2011

У меня текучий макет CSS, который плохо рендерится на iphone, когда я меняю ориентацию. (Выглядит хорошо, когда обновляется).

Я использую приведенный ниже код, чтобы обновить страницу при изменении ориентации, которая работает нормально - она ​​просто чувствует себя немного не так. Есть ли способ достичь этого без перезагрузки всей страницы? Это мобильный сайт, я не хочу заставлять пользователя загружать страницу дважды.

var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    window.location.reload()
}, false);   

Edit:

Две основные проблемы при тестировании на iphone:

У меня есть ширина 100% с фоновым изображением, выровненным по правому краю. Когда я меняю ориентацию с портретной на альбомную, ширина тела остается такой же, как и в портретном режиме, и наоборот. Это скорее проблема от пейзажа к портрету, так как страница слишком широкая, и кажется, что изображения отрисовываются дважды.

Ответы [ 8 ]

24 голосов
/ 04 ноября 2011

Предполагая, что ваш CSS уже успешно рендерится на экранах мобильных устройств различного размера, вам нужно определить область просмотра в вашего шаблона.

Например, в этом случае ширина страницы устанавливается равной ширине экрана устройства и начальному масштабированию 100%.Начальное масштабирование применяется при загрузке страницы, но не при изменении ориентации.

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

Добавив параметр max-scale = 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.Очевидно, что вы должны убедиться, что сайт хорошо спроектирован, чтобы пользователи не нуждались в масштабировании.Если ваш сайт оптимизирован для мобильных устройств, это не должно быть проблемой.

Обратите внимание: другие мобильные браузеры без сафари могут изменить макет страницы без установки максимального масштаба в окне просмотра.Но такое поведение противоречиво, и большинство разработчиков, кажется, обслуживают устройства Apple, даже если реализация хуже, чем на других устройствах.Некоторые другие устройства поддерживают уровень масштабирования и повторно изменяют область просмотра при изменении ориентации.Но все устройства в порядке, чтобы установить уровень масштабирования до 1,0.

11 голосов
/ 11 июля 2015

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

Код прослушивает событие directionchange и инициирует повторный поток элемента body, скрывая его и показывая его через 10 миллисекунд. Он не зависит от тегов <meta> или медиазапросов.

В других ответах предлагалось использовать медиазапросы, но вы уже используете их, так как сказали: «Выглядит прекрасно, когда обновляется».

В некоторых других ответах предлагается использовать location.reload(). Это очень неэффективно, потому что это перезагрузит всю страницу, включая изображения и т. Д. Особенно на мобильных устройствах, вы не хотите этого делать.

В других ответах предлагалось добавить <meta name="viewport" content="width=device-width, initial-scale=1.0"> или их варианты. Начиная с Safari 7 это больше не работает. Вот демоверсия . Чтобы убедиться, что вы видите, как это не работает, начните с iPad в альбомном режиме, загрузите страницу, а затем поверните ее. Обратите внимание, что страница не увеличивается до полной высоты, несмотря на то, что она полностью использует flexbox.

Сравните это с этой страницей , где мы используем технику скрытия / показа тела в производстве.

3 голосов
/ 22 апреля 2016

Использовал метод, который вызывает перерисовку и перекомпоновку в одном кадре стека 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
});
0 голосов
/ 17 декабря 2015

У меня была похожая проблема, и вот как я исправил ее с помощью 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.

0 голосов
/ 30 июля 2014
$(window).bind('resize', function() { location.reload(); });

Этот код работал для меня.

0 голосов
/ 06 февраля 2014

По моему опыту, лучший способ это сделать

<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 в моем опыте, не масштабируется обратно к исходному масштабу, когда вы меняете ориентацию. Не знаю, почему это

0 голосов
/ 08 ноября 2011

Попробуйте что-то вроде этого:

$(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);
    }     
});
0 голосов
/ 08 ноября 2011

Другим вариантом может быть добавление и удаление классов CSS из ваших HTML-элементов (div, var, span и т. Д.). Таким образом, вы можете изменять только те элементы, которые доставляют вам неприятности, а также вы можете настроить содержимое в не мобильных браузерах, если пользователь изменит размер окна браузера.

Вот код 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);
        });
    }
});

А вот CSS-класс для примера элемента "background":

#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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...