Bläddra i källkod

New viewport style: crop. Closes #13

customisations
alemart 2 månader sedan
förälder
incheckning
8d55c9d0e0
2 ändrade filer med 45 tillägg och 22 borttagningar
  1. 3
    2
      docs/api/viewport.md
  2. 42
    20
      src/core/viewport.ts

+ 3
- 2
docs/api/viewport.md Visa fil

@@ -79,8 +79,9 @@ The `<canvas>` on which the virtual scene is drawn.
79 79
 
80 80
 The style determines the way the viewport appears on the screen. Different styles are applicable to different [session modes](session.md#mode). The following are valid styles:
81 81
 
82
-* `"best-fit"`: an immersive viewport that is scaled in a way that covers the page while preserving the aspect ratio of the augmented scene.
83
-* `"stretch"`: an immersive viewport that is scaled in a way that covers the entire page, stretching the augmented scene if necessary.
82
+* `"best-fit"`: an immersive viewport that is scaled in a way that covers the page while preserving the aspect ratio of the augmented scene. This is known as letterboxing or pillarboxing.
83
+* `"stretch"`: an immersive viewport that is scaled in a way that fills the entire page, stretching the augmented scene if necessary.
84
+* `"crop"`: an immersive viewport that is scaled in a way that fills the entire page, cropping the augmented scene if necessary to maintain its aspect ratio. *Since:* 0.4.4
84 85
 * `"inline"`: an inline viewport that follows the typical flow of a web page.
85 86
 
86 87
 The default style is `"best-fit"` in immersive mode, or `"inline"` in inline mode.

+ 42
- 20
src/core/viewport.ts Visa fil

@@ -52,7 +52,7 @@ class ViewportEvent extends AREvent<ViewportEventType> { }
52 52
 class ViewportEventTarget extends AREventTarget<ViewportEventType> { }
53 53
 
54 54
 /** Viewport style (immersive mode) */
55
-type ViewportStyle = 'best-fit' | 'stretch' | 'inline';
55
+type ViewportStyle = 'best-fit' | 'stretch' | 'crop' | 'inline';
56 56
 
57 57
 
58 58
 
@@ -308,6 +308,7 @@ class ViewportCanvases
308 308
         canvas.style.width = '100%';
309 309
         canvas.style.height = '100%';
310 310
         canvas.style.zIndex = String(zIndex);
311
+        canvas.style.objectFit = 'unset';
311 312
 
312 313
         return canvas;
313 314
     }
@@ -586,6 +587,10 @@ class ViewportResizer
586 587
                 this.setStrategy(new StretchResizeStrategy());
587 588
                 break;
588 589
 
590
+            case 'crop':
591
+                this.setStrategy(new CropResizeStrategy());
592
+                break;
593
+
589 594
             case 'inline':
590 595
                 this.setStrategy(new InlineResizeStrategy());
591 596
                 break;
@@ -786,6 +791,8 @@ abstract class ViewportResizeStrategy
786 791
     {
787 792
         viewport.container.style.cssText = '';
788 793
         viewport._subContainer.style.cssText = '';
794
+        viewport._backgroundCanvas.style.objectFit = 'unset';
795
+        viewport.canvas.style.objectFit = 'unset';
789 796
     }
790 797
 }
791 798
 
@@ -843,8 +850,8 @@ abstract class ImmersiveResizeStrategy extends ViewportResizeStrategy
843 850
 }
844 851
 
845 852
 /**
846
- * Immersive viewport with best-fit style: it occupies the entire page and
847
- * preserves the aspect ratio of the media
853
+ * Immersive viewport with best-fit style: it preserves the aspect ratio of the
854
+ * media. This is also known as letterboxing or pillarboxing
848 855
  */
849 856
 class BestFitResizeStrategy extends ImmersiveResizeStrategy
850 857
 {
@@ -883,8 +890,8 @@ class BestFitResizeStrategy extends ImmersiveResizeStrategy
883 890
 }
884 891
 
885 892
 /**
886
- * Immersive viewport with stretch style: it occupies the entire page and
887
- * fully stretches the media, possibly distorting it
893
+ * Immersive viewport with stretch style: it fully fills the viewport with the
894
+ * media, possibly distorting it
888 895
  */
889 896
 class StretchResizeStrategy extends ImmersiveResizeStrategy
890 897
 {
@@ -906,6 +913,35 @@ class StretchResizeStrategy extends ImmersiveResizeStrategy
906 913
     }
907 914
 }
908 915
 
916
+/**
917
+ * Immersive viewport with crop style: it fully fills the viewport with the
918
+ * media, possibly cropping and scaling it to maintain its aspect ratio
919
+ */
920
+class CropResizeStrategy extends ImmersiveResizeStrategy
921
+{
922
+    /**
923
+     * Resize the viewport
924
+     * @param viewport
925
+     */
926
+    resize(viewport: Viewport): void
927
+    {
928
+        const subContainer = viewport._subContainer;
929
+        const backgroundCanvas = viewport._backgroundCanvas;
930
+        const foregroundCanvas = viewport.canvas;
931
+
932
+        subContainer.style.position = 'absolute';
933
+        subContainer.style.left = '0px';
934
+        subContainer.style.top = '0px';
935
+        subContainer.style.width = window.innerWidth + 'px';
936
+        subContainer.style.height = window.innerHeight + 'px';
937
+
938
+        backgroundCanvas.style.objectFit = 'cover';
939
+        foregroundCanvas.style.objectFit = 'cover';
940
+
941
+        super.resize(viewport);
942
+    }
943
+}
944
+
909 945
 
910 946
 
911 947
 
@@ -990,20 +1026,6 @@ export class Viewport extends ViewportEventTarget
990 1026
     }
991 1027
 
992 1028
     /**
993
-     * Set viewport style
994
-     */
995
-    /*
996
-    set style(value: ViewportStyle)
997
-    {
998
-        // note: the viewport style is independent of the session mode!
999
-        if(value !== this._style) {
1000
-            this._resizer.setStrategyByName(value);
1001
-            this._style = value;
1002
-        }
1003
-    }
1004
-    */
1005
-
1006
-    /**
1007 1029
      * HUD
1008 1030
      */
1009 1031
     get hud(): HUD
@@ -1182,7 +1204,7 @@ export class Viewport extends ViewportEventTarget
1182 1204
     {
1183 1205
         // validate if the viewport style matches the session mode
1184 1206
         if(sessionMode == 'immersive') {
1185
-            if(this._style != 'best-fit' && this._style != 'stretch') {
1207
+            if(this._style != 'best-fit' && this._style != 'stretch' && this._style != 'crop') {
1186 1208
                 Utils.warning(`Invalid viewport style \"${this._style}\" for the \"${sessionMode}\" mode`);
1187 1209
                 this._style = 'best-fit';
1188 1210
                 this._resizer.setStrategyByName(this._style);

Laddar…
Avbryt
Spara