|
@@ -626,7 +626,7 @@ class ViewportResizer
|
626
|
626
|
|
627
|
627
|
Ultimately, the size of the viewport is dependent on the size of the
|
628
|
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
|
630
|
it will trigger a resize event on the window, which will, in time,
|
631
|
631
|
resize the viewport. If the order of events is such that the viewport
|
632
|
632
|
is resized before the camera feed is rotated, then we will observe a
|
|
@@ -635,7 +635,7 @@ class ViewportResizer
|
635
|
635
|
Let's correct the issue by first detecting the situation and then by
|
636
|
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
|
639
|
that Chrome does it. Firefox 139 does it in one device but doesn't
|
640
|
640
|
do it in another (it's a browser bug - see below). Safari/iOS does
|
641
|
641
|
it (tested on the cloud).
|
|
@@ -644,18 +644,19 @@ class ViewportResizer
|
644
|
644
|
|
645
|
645
|
*/
|
646
|
646
|
|
647
|
|
- const MAX_ATTEMPTS = 3;
|
|
647
|
+ const MAX_ATTEMPTS = 3; //5;
|
648
|
648
|
const canvas = this._viewport._backgroundCanvas;
|
649
|
649
|
|
650
|
650
|
for(let i = 0; i < MAX_ATTEMPTS; i++) {
|
651
|
651
|
|
|
652
|
+ // this is polling
|
652
|
653
|
await Utils.wait(RESIZE_THROTTLE_DELAY);
|
653
|
654
|
|
654
|
655
|
// After one delay, this._viewport.aspectRatio will likely be
|
655
|
656
|
// correct, but the canvas will not reflect that if, instants ago,
|
656
|
657
|
// it was resized using the previous aspect ratio of the media.
|
657
|
658
|
const a = canvas.width / canvas.height;
|
658
|
|
- const b = screen.width / screen.height;
|
|
659
|
+ const b = this._aspectRatioOfScreen();
|
659
|
660
|
|
660
|
661
|
// if there is a mismatch between the aspect ratios, then the last
|
661
|
662
|
// resize of the viewport took place with the previous aspect ratio
|
|
@@ -663,15 +664,32 @@ class ViewportResizer
|
663
|
664
|
// and that the previous viewport resize event was ineffective.
|
664
|
665
|
if((a-1) * (b-1) < 0) { //if((a < 1 && b > 1) || (a > 1 && b < 1))
|
665
|
666
|
this._triggerResizeEvent();
|
666
|
|
- break;
|
|
667
|
+ //break; // keep listening; see [2]
|
667
|
668
|
}
|
668
|
669
|
|
669
|
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
|
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,6 +716,47 @@ class ViewportResizer
|
698
|
716
|
// Call strategy
|
699
|
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
|
|