A more reliable method for detecting horizontal and vertical screens on mobile devices

A more reliable method for detecting horizontal and vertical screens on mobile devices

[[171604]]

Not long ago, I did an H5 project and needed to do some processing when the horizontal and vertical screens changed. Of course, I needed to use orientationchange to monitor the changes of the horizontal and vertical screens.

Solution 1:

  1. // Listen for orientation changes
  2. window.addEventListener( "orientationchange" , function (event) {
  3. // Determine the horizontal or vertical screen orientation based on event.orientation|screen.orientation.angle being 0|180, 90|-90 degrees
  4. }, false );

After the code is added, various compatibility issues arise. The compatibility issues arise in two places:

  • orientationchange
  • event.orientation|screen.orientation.angle

The compatibility of orientationchange event is as follows:

The following are the compatibility of screen.orientation:

Option 2:

The above solution doesn't work, so I have to find another way. After searching on Google, I found that it can be achieved by resizing (window.inner/outerWidth, window.inner/outerHeight):

  1. window.addEventListener( "resize" , function (event) {
  2. var orientation=(window.innerWidth > window.innerHeight)? "landscape" : "portrait" ;
  3. if(oritentation === 'portrait' ){
  4. // do something…
  5. } else {
  6. // do something else
  7. }
  8. }, false );

This solution basically meets the needs of most projects, but it still has some shortcomings:

  • As long as the size of the window changes, the resize event will be triggered continuously. You can use setTimeout to optimize it.
  • If multiple places need to monitor the horizontal and vertical screen changes, multiple window.addEventListener("resize", function(event) {……}) need to be registered. Can it be improved through the subscription and publishing mode, and only one resize is registered to monitor the horizontal and vertical screen changes, and the notification subscription object is published as long as the horizontal and vertical changes. Other places that need to monitor the horizontal and vertical screens only need to subscribe.

The key codes are as follows:

  1. var resizeCB = function (){
  2. if(win.innerWidth > win.innerHeight){//initialization judgment
  3. meta.init = 'landscape' ;
  4. meta.current = 'landscape' ;
  5. } else {
  6. meta.init = 'portrait' ;
  7. meta.current = 'portrait' ;
  8. }
  9. return   function (){
  10. if(win.innerWidth > win.innerHeight){
  11. if(meta. current !== 'landscape' ){
  12. meta.current = 'landscape' ;
  13. event.trigger ( '__orientationChange__' , meta);
  14. }
  15. } else {
  16. if(meta. current !== 'portrait' ){
  17. meta.current = 'portrait' ;
  18. event.trigger ( '__orientationChange__' , meta);
  19. }
  20. }
  21. }
  22. }();

Click here for the complete code

Option 3:

However, I think that the detection by window.innerWidth > window.innerHeight is a pseudo detection, which is a bit unreliable. Can the detection be implemented through the browser? For example, based on CSS3@media media query.

@media compatibility is as follows:

As shown in the figure above, mobile browsers all support CSS3 media.

Implementation ideas:

  • Create a specific CSS style that contains the horizontal and vertical screen states
  • Inject CSS code into the page via JS
  • Get the horizontal and vertical screen status in the resize callback function

Here I choose the font-family of the <html></html> node as the detection style attribute. The reasons are as follows:

  • Choose <html></html> mainly to avoid reflow and repaint
  • The font-family style is chosen mainly because font-family has the following characteristics:

1. Give priority to the fonts that are listed first.

2. If the font cannot be found or does not include the text to be rendered, the next font is used.

3. If none of the listed fonts meet your needs, let the operating system decide which font to use.

In this way, we can specify a specific logo to indicate the horizontal and vertical screen status, but the specified logo needs to be placed in front of other fonts so that it will not cause changes in the hmtl font.

The key codes are as follows:

  1. // callback
  2. var resizeCB = function () {
  3. var hstyle = win.getComputedStyle(html, null ),
  4. ffstr = hstyle[ 'font-family' ],
  5. pstr = "portrait, " + ffstr,
  6. lstr = "landscape, " + ffstr,
  7. // Splicing css
  8. cssstr = '@media (orientation: portrait) { .orientation{font-family:' + pstr + ';} } @media (orientation: landscape) { .orientation{font-family:' + lstr + ';}}' ;
  9. // Load the style
  10. loadStyleString(cssstr);
  11. // Add class
  12. html.className = 'orientation' + html.className;
  13. if (hstyle[ 'font-family' ] === pstr) { // Initialization judgment
  14. meta.init = 'portrait' ;
  15. meta.current = 'portrait' ;
  16. } else {
  17. meta.init = 'landscape' ;
  18. meta.current = 'landscape' ;
  19. }
  20. return   function () {
  21. if (hstyle[ 'font-family' ] === pstr) {
  22. if (meta. current !== 'portrait' ) {
  23. meta.current = 'portrait' ;
  24. event.trigger ( '__orientationChange__' , meta);
  25. }
  26. } else {
  27. if (meta. current !== 'landscape' ) {
  28. meta.current = 'landscape' ;
  29. event.trigger ( '__orientationChange__' , meta);
  30. }
  31. }
  32. }
  33. }();

Click here for the complete code

Test results

  • Portrait effect:

  • Landscape effect:

Option 4:

It can be improved further. When orientationchange is supported, use the native orientationchange. If it is not supported, use solution three.

The key codes are as follows:

  1. // Whether to support orientationchange event
  2. var isOrientation = ( 'orientation'   in window && 'onorientationchange'   in window);
  3. // callback
  4. var orientationCB = function (e) {
  5. if (win.orientation === 180 || win.orientation === 0) {
  6. meta.init = 'portrait' ;
  7. meta.current = 'portrait' ;
  8. }
  9. if (win.orientation === 90 || win.orientation === -90) {
  10. meta.init = 'landscape' ;
  11. meta.current = 'landscape' ;
  12. }
  13. return   function () {
  14. if (win.orientation === 180 || win.orientation === 0) {
  15. meta.current = 'portrait' ;
  16. }
  17. if (win.orientation === 90 || win.orientation === -90) {
  18. meta.current = 'landscape' ;
  19. }
  20. event.trigger (eventType, meta);
  21. }
  22. };
  23. var callback = isOrientation ? orientationCB() : ( function () {
  24. resizeCB();
  25. return   function () {
  26. timer && win.clearTimeout(timer);
  27. timer = win.setTimeout(resizeCB, 300);
  28. }
  29. })();
  30. // Listen
  31. win.addEventListener(isOrientation? eventType: 'resize' , callback, false );

Click here for the complete code

Option 5:

At present, the above solutions are all implemented through customized subscription and publishing event modes. Here, we can simulate orientationchange based on the browser's event mechanism, that is, fix the incompatibility of orientationchange.

The key codes are as follows:

  1. var eventType = 'orientationchange' ;
  2. // Trigger native orientationchange
  3. var fire = function () {
  4. var e;
  5. if (document.createEvent) {
  6. e = document.createEvent( 'HTMLEvents' );
  7. e.initEvent(eventType, true , false );
  8. win.dispatchEvent(e);
  9. } else {
  10. e = document.createEventObject();
  11. e.eventType = eventType;
  12. if (win[eventType]) {
  13. win[eventType]();
  14. } else if (win[ 'on' + eventType]) {
  15. win[ 'on' + eventType]();
  16. } else {
  17. win.fireEvent(eventType, e);
  18. }
  19. }
  20. }

Click here for the complete code

Through the above five solutions, I have a deeper understanding of mobile terminal horizontal and vertical screen detection. Some things can only be understood by yourself when you have experienced them. I also recorded the reasons in the article, hoping to help everyone. After the evolution of five solutions, the final orientationchange-fix was obtained, github address: https://github.com/zhansingsong/orientationchange-fix

<<:  What are Alibaba and JD.com’s VR+ shopping waiting for?

>>:  iOS development history: from iPhone OS 1.0 to iOS10, finally supports harassment blocking

Recommend

Fiction or reality? What species are the "strange fish" in "Avatar 2"?

Review expert: Ancient Mingdi Lian (He Lin) Zhihu...

What is the secret behind TikTok’s explosive user growth?

Think first: How do you measure user growth ? Wha...

Even Tesla is not immune to charging problems

As the saying goes, "the army has not yet mo...

A century of advertising and marketing!

On the day JWT was merged with digital marketing ...

What do target keywords mean? What are target keywords?

Target keywords refer to the "main" key...

The fabric as thin as a cicada's wing is actually a "silencer"!

Produced by: Science Popularization China Author:...

How to fix PC game lag issues? Try these tips

Many friends like to play games on their computer...

When doing user operations, it is important to learn some psychology!

1. Why write this article? I am often asked what ...

3 loops that Tik Tok uses to retain users!

This article divides the operation of Douyin into...

Is it true that dogs can see all the colors in Bluey?

I heard that dogs all over the world are obsessed...