Not long ago, I did an H5 project and needed to do some processing when the horizontal and vertical screen changes. There is no doubt that the orientationchange needs to be used to monitor changes in horizontal and vertical screens.
Plan 1:
// Listen to orientation changeswindow.addEventListener("orientationchange", function(event) { // Judging horizontal and vertical screens based on event.orientation|screen.orientation.angle is equal to 0|180, 90|-90 degrees}, false);After the code is added, there are various compatibility issues. Compatibility issues occur here in two places:
orientationchange
event.orientation|screen.orientation.angle
The following is the compatibility of the orientationchange event:
The following is the compatibility of screen.orientation:
Plan 2:The above plan does not work, so you can only do other methods. Google and learn that it can be achieved through resize (window.inner/outerWidth, window.inner/outerHeight):
window.addEventListener("resize", function(event) {var orientation=(window.innerWidth > window.innerHeight)? "landscape":"portrait";if(oritentation === 'portrait'){// do something …} else {// do something else …}}, false);This solution basically meets the needs of most projects, but there are still some shortcomings:
As long as the size of the window changes, the resize event will be triggered continuously. You can use setTimeout to optimize
If there are multiple places that need to monitor horizontal and vertical screens, you need to register multiple windows.addEventListener("resize", function(event) {...}). Can you improve it through the subscription and publishing modes? Only register a resize to monitor changes in horizontal and vertical screens, and publish notifications to the subscribed object as long as the horizontal and vertical changes occur. Other places that need to monitor horizontal and vertical screens are just a subscribe.
The key code is as follows:
var resizeCB = function(){ if(win.innerWidth > win.innerHeight){//Initialize judgment meta.init = 'landscape'; meta.current = 'landscape'; } else { meta.init = 'portrait'; meta.current = 'portrait'; } return function(){ if(win.innerWidth > win.innerHeight){ if(meta.current !== 'landscape'){ meta.current = 'landscape'; event.trigger('__orientationChange__', meta); } } else { if(meta.current !== 'portrait'){ meta.current = 'portrait'; event.trigger('__orientationChange__', meta); } } } } } } }();The full code is clicked here
Plan 3:
However, I personally think that the implementation of window.innerWidth > window.innerHeight is a kind of pseudo detection, which is a bit unreliable. Can detection be achieved through a browser? This is based on CSS3@media media query.
As follows @media compatibility:
As shown in the above figure, mobile browsers support CSS3 media.
Implementation ideas:
Create a specific css style that identifies the horizontal and vertical screen status
Inject CSS code into pages via JS
The resize callback function gets the status of the horizontal and vertical screen
Here I select the node font-family of <html></html> as the detection style attribute. The reasons are as follows:
Select <html></html> mainly to avoid reflow and repaint
The font-family style is mainly because font-family has the following characteristics:
In this way, we can specify a specific logo to identify the status of the horizontal and vertical screen, but the specified logo needs to be placed in front of other fonts, so that the hmtl font changes will not be caused.
The key code is as follows:
// callback var resizeCB = function() { var hstyle = win.getComputedStyle(html, null), ffstr = hstyle['font-family'], pstr = "portrait, " + ffstr, lstr = "landscape, " + ffstr, // Splicing css cssstr = '@media (orientation: portrait) { .orientation{font-family:' + pstr + ';} } @media (orientation: landscape) { .orientation{font-family:' + lstr + ';}}'; // Load style loadStyleString(cssstr); // Add class html.className = 'orientation' + html.className; if (hstyle['font-family'] === pstr) { //Initialize judgment meta.init = 'portrait'; meta.current = 'portrait'; } else { meta.init = 'landscape'; meta.current = 'landscape'; } return function() { if (hstyle['font-family'] === pstr) { if (meta.current !== 'portrait') { meta.current = 'portrait'; event.trigger('__orientationChange__', meta); } } else { if (meta.current !== 'landscape') { meta.current = 'landscape'; event.trigger('__orientationChange__', meta); } } } } } }();The full code is clicked here
Test results
Portrait effect:
Landscape effect:
Plan 4:
You can improve it. When supporting orientationchange , use the native orientationchange. If not, use Solution 3.
The key code is as follows:
// Whether the orientationchange event is supported isOrientation = ('orientation' in window && 'onorientationchange' in window);// callbackvar orientationCB = function(e) { if (win.orientation === 180 || win.orientation === 0) { meta.init = 'portrait'; meta.current = 'portrait'; } if (win.orientation === 90 || win.orientation === -90) { meta.init = 'landscape'; meta.current = 'landscape'; } return function() { if (win.orientation === 180 || win.orientation === 0) { meta.current = 'portrait'; } if (win.orientation === 90 || win.orientation === -90) { meta.current = 'landscape'; } event.trigger(eventType, meta); }};var callback = isOrientation ? orientationCB() : (function() { resizeCB(); return function() { timer && win.clearTimeout(timer); timer = win.setTimeout(resizeCB, 300); }})();// Listen to win.addEventListener(isOrientation ? eventType : 'resize', callback, false);The full code is clicked here
Plan 5:
At present, the above solutions are all implemented through customized subscription and publish event modes. Here, the orientationchange can be simulated based on the browser's event mechanism. That is, fix the incompatibility of orientationchange.
The key code is as follows:
var eventType = 'orientationchange';// Trigger native orientationchangevar fire = function() { var e; if (document.createEvent) { e = document.createEvent('HTMLEvents'); e.initEvent(eventType, true, false); win.dispatchEvent(e); } else { e = document.createEventObject(); e.eventType = eventType; if (win[eventType]) { win[eventType](); } else if (win['on' + eventType]) { win['on' + eventType](); } else { win.fireEvent(eventType, e); } }}The full code is clicked here
Through the above five solutions, I have a further understanding of horizontal and vertical screen detection on mobile terminals. I only know why I write about some things myself after I have experienced them myself. I also recorded the reasons in the article, hoping that they will be helpful to everyone. After five solutions evolved to the final orientation change-fix, github address: https://github.com/zhansingsong/orientationchange-fix
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.