Browse Source

introduce orthographic camera for `ui.scene` (#2890)

Falko Schindler 1 year ago
parent
commit
c36834a6c1

+ 11 - 1
nicegui/elements/scene.js

@@ -66,7 +66,12 @@ export default {
     window["scene_" + this.$el.id] = this.scene; // NOTE: for selenium tests only
 
     this.look_at = new THREE.Vector3(0, 0, 0);
-    this.camera = new THREE.PerspectiveCamera(75, this.width / this.height, 0.1, 1000);
+    const aspect = this.width / this.height;
+    if (this.camera_type === "perspective") {
+      this.camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
+    } else {
+      this.camera = new THREE.OrthographicCamera(-aspect, aspect, 1, -1, 0.1, 1000);
+    }
     this.camera.lookAt(this.look_at);
     this.camera.up = new THREE.Vector3(0, 0, 1);
     this.camera.position.set(0, -3, 5);
@@ -410,6 +415,10 @@ export default {
       this.text_renderer.setSize(clientWidth, clientHeight);
       this.text3d_renderer.setSize(clientWidth, clientHeight);
       this.camera.aspect = clientWidth / clientHeight;
+      if (this.camera_type === "orthographic") {
+        this.camera.left = -this.camera.aspect;
+        this.camera.right = this.camera.aspect;
+      }
       this.camera.updateProjectionMatrix();
     },
   },
@@ -418,6 +427,7 @@ export default {
     width: Number,
     height: Number,
     grid: Boolean,
+    camera_type: String,
     drag_constraints: String,
   },
 };

+ 4 - 1
nicegui/elements/scene.py

@@ -1,6 +1,6 @@
 import asyncio
 from dataclasses import dataclass
-from typing import Any, Callable, Dict, List, Optional, Union
+from typing import Any, Callable, Dict, List, Literal, Optional, Union
 
 from typing_extensions import Self
 
@@ -71,6 +71,7 @@ class Scene(Element,
                  width: int = 400,
                  height: int = 300,
                  grid: bool = True,
+                 camera_type: Literal['perspective', 'orthographic'] = 'perspective',
                  on_click: Optional[Callable[..., Any]] = None,
                  on_drag_start: Optional[Callable[..., Any]] = None,
                  on_drag_end: Optional[Callable[..., Any]] = None,
@@ -86,6 +87,7 @@ class Scene(Element,
         :param width: width of the canvas
         :param height: height of the canvas
         :param grid: whether to display a grid
+        :param camera_type: type of camera to use (``'perspective'`` or ``'orthographic'``)
         :param on_click: callback to execute when a 3D object is clicked
         :param on_drag_start: callback to execute when a 3D object is dragged
         :param on_drag_end: callback to execute when a 3D object is dropped
@@ -95,6 +97,7 @@ class Scene(Element,
         self._props['width'] = width
         self._props['height'] = height
         self._props['grid'] = grid
+        self._props['camera_type'] = camera_type
         self.objects: Dict[str, Object3D] = {}
         self.stack: List[Union[Object3D, SceneObject]] = [SceneObject()]
         self.camera: SceneCamera = SceneCamera()

+ 8 - 0
website/documentation/content/scene_documentation.py

@@ -113,4 +113,12 @@ async def wait_for_init() -> None:
         scene.move_camera(x=1, y=-1, z=1.5, duration=2)
 
 
+@doc.demo('Orthographic Camera', '''
+    You can use the `camera_type` argument to `ui.scene` to use an orthographic instead of a perspective camera.
+''')
+def orthographic_camera() -> None:
+    with ui.scene(camera_type='orthographic').classes('w-full h-64') as scene:
+        scene.box()
+
+
 doc.reference(ui.scene)