Javascript 在方向更改时重新呈现网页的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7919172/
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
What is the best method of re-rendering a web page on orientation change?
提问by theorise
I have a fluid CSS layout which is rendering badly on an iphone when I change the orientation. (It looks fine when it is refreshed).
我有一个流畅的 CSS 布局,当我改变方向时,它在 iphone 上渲染得很糟糕。(刷新后看起来不错)。
I am using the code below to refresh the page on orientation change, which works fine - it just feels a little wrong doing so. Is there any way of achieving this without having to reload the entire page? It is a mobile site, I don't really want to force the user to load the page twice.
我正在使用下面的代码在方向更改时刷新页面,这工作正常 - 这样做感觉有点错误。有没有什么方法可以实现这一点而不必重新加载整个页面?这是一个移动网站,我真的不想强迫用户加载页面两次。
var supportsOrientationChange = "onorientationchange" in window,
orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
window.addEventListener(orientationEvent, function() {
window.location.reload()
}, false);
Edit:
编辑:
The two main issues when testing on an iphone are:
在 iphone 上测试时的两个主要问题是:
I have a which is 100% width, with a right aligned background image. When I change the orientation from portrait to landscape the body width remains as how it rendered on portrait mode and vice versa. It is more of an issue from landscape to portrait as the page is too wide and it seems to render the images twice.
我有一个 100% 宽度,右对齐的背景图像。当我将方向从纵向更改为横向时,主体宽度保持在纵向模式下的呈现方式,反之亦然。从横向到纵向,这更像是一个问题,因为页面太宽,而且似乎要渲染图像两次。
采纳答案by BenSwayne
Assuming your CSS is already happily rendering on your various size mobile device screens, you need to define the viewport in the <head> of your template.
假设您的 CSS 已经可以在各种尺寸的移动设备屏幕上愉快地呈现,您需要在模板的 <head> 中定义视口。
Example, this sets the page width to be the device's screen width and an initial zoom of 100%. Initial zoom is applied at page load, but not when the orientation is changed.
例如,这将页面宽度设置为设备的屏幕宽度和 100% 的初始缩放。初始缩放在页面加载时应用,但在方向更改时不应用。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
By adding a maximum-scale=1.0 parameter to the viewport you will force the iPad/iPhone to maintain the zoom level and re-layout the page on orientation change. The disadvantage of this is that it will disable zooming. However, the advantage is that you can make layout adjustments with media queries to present the content in a suitable fashion for the current orientation. You can read more about viewport here: Choosing a ViewPort
通过向视口添加一个 max-scale=1.0 参数,您将强制 iPad/iPhone 保持缩放级别并在方向改变时重新布局页面。这样做的缺点是它会禁用缩放。但是,优点是您可以使用媒体查询进行布局调整,以适合当前方向的方式呈现内容。您可以在此处阅读有关视口的更多信息:选择视口
Now onto media queries. You should put media queries at the bottom of your CSS file and in the order of smallest width to largest width for screen widths. For example, taken from the Html5BoilerPlateCSS example:
现在进入媒体查询。您应该将媒体查询放在 CSS 文件的底部,并按照屏幕宽度的最小宽度到最大宽度的顺序。例如,取自Html5BoilerPlateCSS 示例:
@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 */
}
So all your normal styles are above this and applied first, then if the screen is 480px or wider the next block of styles are applied, then if the screen is 768px or wider the last block of styles are applied.
因此,您的所有普通样式都在此之上并首先应用,然后如果屏幕为 480 像素或更宽,则应用下一个样式块,然后如果屏幕为 768 像素或更宽,则应用最后一个样式块。
By combining the fixed zoom level to 1.0 and the media-queries, you can make your site responsively resize to the screen size and orientation without javascript. Obviously you need to make sure the site is then well designed so users don't need zooming. If your site is optimized for mobile this shouldn't be a problem.
通过将固定缩放级别与 1.0 和媒体查询相结合,您可以使您的网站响应式地调整大小以适应屏幕大小和方向,而无需使用 JavaScript。显然,您需要确保网站设计良好,以便用户不需要缩放。如果您的网站针对移动设备进行了优化,这应该不是问题。
Please note: other non-safari mobile browsers may re-layout the page without setting the maximum-scale on the viewport. But this behavior is inconsistent and most developers seem to cater to apple devices even if the implementation is worse than other devices. Some other devices would maintain the zoom level and recenter the viewport when the orientation changes. But all devices are ok to fix the zoom level to 1.0.
请注意:其他非 safari 移动浏览器可能会重新布局页面,而无需在视口上设置最大比例。但是这种行为是不一致的,即使实现比其他设备差,大多数开发人员似乎也迎合了苹果设备。当方向改变时,一些其他设备将保持缩放级别并重新居中视口。但是所有设备都可以将缩放级别固定为 1.0。
回答by Dan Dascalescu
2015 update
2015年更新
All the other answers are incorrect or outdated. Here's what works:
所有其他答案都不正确或过时。这是有效的:
window.addEventListener('orientationchange', function () {
var originalBodyStyle = getComputedStyle(document.body).getPropertyValue('display');
document.body.style.display='none';
setTimeout(function () {
document.body.style.display = originalBodyStyle;
}, 10);
});
The code listens to the orientationchange eventand forces a re-flow of the body
element by hiding it and showing it 10 milliseconds later. It does not depend on any <meta>
tags or media queries.
该代码侦听orientationchange 事件并body
通过隐藏它并在10 毫秒后显示它来强制重新流动元素。它不依赖于任何<meta>
标签或媒体查询。
Other answers suggested using media queries, but you already use them, since you said "It looks fine when it is refreshed".
其他答案建议使用媒体查询,但您已经使用了它们,因为您说“刷新后看起来不错”。
Some otheranswers suggest using location.reload()
. This is very inefficient, because it will reload the entire page, including images etc. Especially on mobile, you don't want to do that.
其他一些答案建议使用location.reload()
. 这是非常低效的,因为它会重新加载整个页面,包括图像等。尤其是在移动设备上,您不想这样做。
Yet other answers suggested adding <meta name="viewport" content="width=device-width, initial-scale=1.0">
or variations thereof. As of Safari 7, this no longer works. Here's a demo. To make sure you see how it doesn't work, start with the iPad in landscape mode, load the page, then rotate. Notice the page doesn't expand to full height, despite using flexbox all the way.
还有其他答案建议添加<meta name="viewport" content="width=device-width, initial-scale=1.0">
或更改它们。从 Safari 7 开始,这不再有效。这是一个演示。为确保您了解它是如何工作的,请先将 iPad 置于横向模式,加载页面,然后旋转。请注意,尽管一直使用 flexbox,但页面并没有扩展到全高。
Compare that to this page, where we use the hide/show body technique in production.
与此页面相比,我们在生产中使用隐藏/显示主体技术。
回答by James Westgate
Used a method that causes a repaint and a reflow in a single javascript stack frame. Not keen on viewport specific answers as it is often a requirement for accessibility to keep pinch zooming etc.
使用了在单个 javascript 堆栈框架中导致重绘和回流的方法。不热衷于视口特定的答案,因为它通常是保持捏缩放等可访问性的要求。
$(window).on('orientationchange', function() {
document.body.style.display='none';
document.body.offsetHeight; //cause a reflow
document.body.style.display='block'; //cause a repaint
});
Or non-jquery equivalent
或非 jquery 等效项
window.addEventListener('orientationchange', function () {
document.body.style.display='none';
document.body.offsetHeight; //cause a reflow
document.body.style.display='block'; //cause a repaint
});
回答by Tommy DC
I had a similar problem and this is how I fixed it with jQuery.
我有一个类似的问题,这就是我用 jQuery 修复它的方法。
In my case the styles were not changing correctly for my <nav>
element. I used a modified version of kidkaos77's code combined with $.get()
to only load a certain part of the page:
在我的情况下,我的<nav>
元素的样式没有正确改变。我使用了kidkaos77代码的修改版本,结合$.get()
只加载页面的特定部分:
$(window).bind("resize",function() {
//on resize reload only nav & replace
$.get("index.php" + ' nav', function(data) {
$("nav").replaceWith($(data).find("nav"));
});
});
With this method you don't have to reload the entire page, but you would have to specify exactly which elements are being affected by the orientation change, which in your case it seems like you just need one div.
使用这种方法,您不必重新加载整个页面,但您必须准确指定哪些元素受到方向更改的影响,在您的情况下,您似乎只需要一个 div。
回答by komu_Mkeya
In my experience the best way is to have it like this
根据我的经验,最好的方法是像这样拥有它
<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"/>
Doing it like @BenSwayne in my experience does not rescale back to the initial scale when you change the orientation. Dont know why that is
根据我的经验,像 @BenSwayne 那样在更改方向时不会重新缩放回初始比例。不知道这是为什么
回答by Paul N
Another option could be to add & remove CSS classes from your html elements (div, var, span, etc). This way you can modify only the elements that are giving you troubles and also you can adjust the content on non-mobile browsers if the user resize the browser window.
另一种选择是从您的 html 元素(div、var、span 等)中添加和删除 CSS 类。通过这种方式,您可以只修改给您带来麻烦的元素,并且如果用户调整浏览器窗口的大小,您还可以调整非移动浏览器上的内容。
Here is the Javascript/JQuery code you will need:
这是您需要的 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);
});
}
});
And here is the CSS class for the sample element "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;
}
This way you can customize the landscape and portrait behavior and you can add more clases like: "landscape_iPhone", "portrait_Android" or whatever you need to control the rendering of the page for each specific device.
通过这种方式,您可以自定义横向和纵向行为,并且可以添加更多类,例如:“landscape_iPhone”、“portrait_Android”或控制每个特定设备的页面呈现所需的任何内容。
Also, you don't need to reload the page, it will adjust it on the fly.
此外,您不需要重新加载页面,它会即时调整它。
Hope it helps you or someone else =), this has enabled me to create web sites customized for each screen size, mobile brand or even browser type with the same HTML but different CSS classes.
希望它对您或其他人有帮助 =),这使我能够使用相同的 HTML 但不同的 CSS 类为每个屏幕尺寸、移动品牌甚至浏览器类型创建定制的网站。
回答by James Johnson
Try something like this:
尝试这样的事情:
$(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);
}
});
回答by kidkaos77
$(window).bind('resize', function() { location.reload(); });
This code worked for me.
这段代码对我有用。