Browse Source

Introduce method _aspectRatioOfScreen(). Add comment

customisations
alemart 2 months ago
parent
commit
27b5ba78b9
1 changed files with 66 additions and 7 deletions
  1. 66
    7
      src/core/viewport.ts

+ 66
- 7
src/core/viewport.ts View File

626
 
626
 
627
         Ultimately, the size of the viewport is dependent on the size of the
627
         Ultimately, the size of the viewport is dependent on the size of the
628
         underlying media (typically a camera feed). When the device is rotated,
628
         underlying media (typically a camera feed). When the device is rotated,
629
-        the browser should rotate the camera feed automatically*. In addition,
629
+        the browser should rotate the camera feed automatically[1]. In addition,
630
         it will trigger a resize event on the window, which will, in time,
630
         it will trigger a resize event on the window, which will, in time,
631
         resize the viewport. If the order of events is such that the viewport
631
         resize the viewport. If the order of events is such that the viewport
632
         is resized before the camera feed is rotated, then we will observe a
632
         is resized before the camera feed is rotated, then we will observe a
635
         Let's correct the issue by first detecting the situation and then by
635
         Let's correct the issue by first detecting the situation and then by
636
         triggering a new resize event.
636
         triggering a new resize event.
637
 
637
 
638
-        (*) at the time of this writing, when testing on Android devices, I see
638
+        [1] at the time of this writing, when testing on Android devices, I see
639
             that Chrome does it. Firefox 139 does it in one device but doesn't
639
             that Chrome does it. Firefox 139 does it in one device but doesn't
640
             do it in another (it's a browser bug - see below). Safari/iOS does
640
             do it in another (it's a browser bug - see below). Safari/iOS does
641
             it (tested on the cloud).
641
             it (tested on the cloud).
644
 
644
 
645
         */
645
         */
646
 
646
 
647
-        const MAX_ATTEMPTS = 3;
647
+        const MAX_ATTEMPTS = 3; //5;
648
         const canvas = this._viewport._backgroundCanvas;
648
         const canvas = this._viewport._backgroundCanvas;
649
 
649
 
650
         for(let i = 0; i < MAX_ATTEMPTS; i++) {
650
         for(let i = 0; i < MAX_ATTEMPTS; i++) {
651
 
651
 
652
+            // this is polling
652
             await Utils.wait(RESIZE_THROTTLE_DELAY);
653
             await Utils.wait(RESIZE_THROTTLE_DELAY);
653
 
654
 
654
             // After one delay, this._viewport.aspectRatio will likely be
655
             // After one delay, this._viewport.aspectRatio will likely be
655
             // correct, but the canvas will not reflect that if, instants ago,
656
             // correct, but the canvas will not reflect that if, instants ago,
656
             // it was resized using the previous aspect ratio of the media.
657
             // it was resized using the previous aspect ratio of the media.
657
             const a = canvas.width / canvas.height;
658
             const a = canvas.width / canvas.height;
658
-            const b = screen.width / screen.height;
659
+            const b = this._aspectRatioOfScreen();
659
 
660
 
660
             // if there is a mismatch between the aspect ratios, then the last
661
             // if there is a mismatch between the aspect ratios, then the last
661
             // resize of the viewport took place with the previous aspect ratio
662
             // resize of the viewport took place with the previous aspect ratio
663
             // and that the previous viewport resize event was ineffective.
664
             // and that the previous viewport resize event was ineffective.
664
             if((a-1) * (b-1) < 0) { //if((a < 1 && b > 1) || (a > 1 && b < 1))
665
             if((a-1) * (b-1) < 0) { //if((a < 1 && b > 1) || (a > 1 && b < 1))
665
                 this._triggerResizeEvent();
666
                 this._triggerResizeEvent();
666
-                break;
667
+                //break; // keep listening; see [2]
667
             }
668
             }
668
 
669
 
669
             // Note: when using a canvas or a video file as a source of data,
670
             // Note: when using a canvas or a video file as a source of data,
670
-            // its aspect ratio is not expected to change. We will trigger an
671
-            // additional resize event on mobile in this case. Unlikely to be
671
+            // its aspect ratio is not expected to change. We will trigger
672
+            // additional resize events on mobile in this case. Unlikely to be
672
             // an issue.
673
             // an issue.
673
 
674
 
674
         }
675
         }
676
+
677
+        /*
678
+
679
+        [2] is this order of events possible when changing the orientation?
680
+
681
+        1. orientationchange event is fired and handled
682
+        2. resize event is fired and handled
683
+        3. camera feed is rotated
684
+
685
+        If so, increasing the throttling will likely make the camera feed be
686
+        rotated first, but then the user will more easily notice the delay.
687
+        Increasing MAX_ATTEMPTS is a simple alternative that makes this
688
+        callback be executed after the video rotation, which is what we want.
689
+        About listening to video resize: the Viewport doesn't know about it
690
+        and has no access to the source of data. The Session does, however.
691
+
692
+        */
675
     }
693
     }
676
 
694
 
677
     /**
695
     /**
698
         // Call strategy
716
         // Call strategy
699
         this._resizeStrategy.resize(viewport);
717
         this._resizeStrategy.resize(viewport);
700
     }
718
     }
719
+
720
+    /**
721
+     * The current aspect ratio of the screen
722
+     * @returns a value greater than 1 if the device is in landscape mode
723
+     */
724
+    private _aspectRatioOfScreen(): number
725
+    {
726
+        // When changing the orientation of a mobile device, screen.width and
727
+        // screen.height are flipped on Chrome and on Firefox, but not on Safari
728
+        //return screen.width / screen.height;
729
+
730
+        // These are the width and the height of the screen in landscape mode
731
+        const width = Math.max(screen.width, screen.height);
732
+        const height = Math.min(screen.width, screen.height);
733
+
734
+        // use screen.orientation if possible
735
+        if(typeof screen.orientation === 'object') {
736
+            if(screen.orientation.type.startsWith('landscape'))
737
+                return width / height;
738
+            else
739
+                return height / width;
740
+        }
741
+
742
+        // fallback for older iOS
743
+        // https://developer.apple.com/documentation/webkitjs/domwindow/1632568-orientation
744
+        if(typeof window.orientation === 'number') {
745
+            if(Math.abs(window.orientation) == 90)
746
+                return width / height;
747
+            else
748
+                return height / width;
749
+        }
750
+
751
+        // general fallback
752
+        // note: before evaluating clientWidth & clientHeight, a setTimeout(fn,
753
+        // t >= 100?) is necessary immediately after a change of orientation.
754
+        // mobile devices should not fall in this case, so no worries.
755
+        if(document.documentElement.clientWidth > document.documentElement.clientHeight)
756
+            return width / height;
757
+        else
758
+            return height / width;
759
+    }
701
 }
760
 }
702
 
761
 
703
 
762
 

Loading…
Cancel
Save