1
0
Эх сурвалжийг харах

Allow specifying the list of click events for `ui.scene` (#3463)

* introduce `click_events` argument for `ui.scene`

* demonstrate context menus for 3D objects
Falko Schindler 9 сар өмнө
parent
commit
5f52a8a61e

+ 2 - 2
nicegui/elements/scene.js

@@ -195,8 +195,7 @@ export default {
         shift_key: mouseEvent.shiftKey,
         shift_key: mouseEvent.shiftKey,
       });
       });
     };
     };
-    this.$el.onclick = click_handler;
-    this.$el.ondblclick = click_handler;
+    this.click_events.forEach((event) => this.$el.addEventListener(event, click_handler));
 
 
     this.texture_loader = new THREE.TextureLoader();
     this.texture_loader = new THREE.TextureLoader();
     this.stl_loader = new STLLoader();
     this.stl_loader = new STLLoader();
@@ -475,6 +474,7 @@ export default {
     grid: Object,
     grid: Object,
     camera_type: String,
     camera_type: String,
     camera_params: Object,
     camera_params: Object,
+    click_events: Array,
     drag_constraints: String,
     drag_constraints: String,
     background_color: String,
     background_color: String,
   },
   },

+ 4 - 1
nicegui/elements/scene.py

@@ -75,6 +75,7 @@ class Scene(Element,
                  grid: Union[bool, Tuple[int, int]] = True,
                  grid: Union[bool, Tuple[int, int]] = True,
                  camera: Optional[SceneCamera] = None,
                  camera: Optional[SceneCamera] = None,
                  on_click: Optional[Callable[..., Any]] = None,
                  on_click: Optional[Callable[..., Any]] = None,
+                 click_events: List[str] = ['click', 'dblclick'],  # noqa: B006
                  on_drag_start: Optional[Callable[..., Any]] = None,
                  on_drag_start: Optional[Callable[..., Any]] = None,
                  on_drag_end: Optional[Callable[..., Any]] = None,
                  on_drag_end: Optional[Callable[..., Any]] = None,
                  drag_constraints: str = '',
                  drag_constraints: str = '',
@@ -91,7 +92,8 @@ class Scene(Element,
         :param height: height of the canvas
         :param height: height of the canvas
         :param grid: whether to display a grid (boolean or tuple of ``size`` and ``divisions`` for `Three.js' GridHelper <https://threejs.org/docs/#api/en/helpers/GridHelper>`_, default: 100x100)
         :param grid: whether to display a grid (boolean or tuple of ``size`` and ``divisions`` for `Three.js' GridHelper <https://threejs.org/docs/#api/en/helpers/GridHelper>`_, default: 100x100)
         :param camera: camera definition, either instance of ``ui.scene.perspective_camera`` (default) or ``ui.scene.orthographic_camera``
         :param camera: camera definition, either instance of ``ui.scene.perspective_camera`` (default) or ``ui.scene.orthographic_camera``
-        :param on_click: callback to execute when a 3D object is clicked
+        :param on_click: callback to execute when a 3D object is clicked (use ``click_events`` to specify which events to subscribe to)
+        :param click_events: list of JavaScript click events to subscribe to (default: ``['click', 'dblclick']``)
         :param on_drag_start: callback to execute when a 3D object is dragged
         :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
         :param on_drag_end: callback to execute when a 3D object is dropped
         :param drag_constraints: comma-separated JavaScript expression for constraining positions of dragged objects (e.g. ``'x = 0, z = y / 2'``)
         :param drag_constraints: comma-separated JavaScript expression for constraining positions of dragged objects (e.g. ``'x = 0, z = y / 2'``)
@@ -108,6 +110,7 @@ class Scene(Element,
         self.objects: Dict[str, Object3D] = {}
         self.objects: Dict[str, Object3D] = {}
         self.stack: List[Union[Object3D, SceneObject]] = [SceneObject()]
         self.stack: List[Union[Object3D, SceneObject]] = [SceneObject()]
         self._click_handlers = [on_click] if on_click else []
         self._click_handlers = [on_click] if on_click else []
+        self._props['click_events'] = click_events
         self._drag_start_handlers = [on_drag_start] if on_drag_start else []
         self._drag_start_handlers = [on_drag_start] if on_drag_start else []
         self._drag_end_handlers = [on_drag_end] if on_drag_end else []
         self._drag_end_handlers = [on_drag_end] if on_drag_end else []
         self.is_initialized = False
         self.is_initialized = False

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

@@ -60,6 +60,35 @@ def click_events() -> None:
         scene.box().move(x=1, z=1).with_name('box')
         scene.box().move(x=1, z=1).with_name('box')
 
 
 
 
+@doc.demo('Context menu for 3D objects', '''
+    This demo shows how to create a context menu for 3D objects.
+    By setting the `click_events` argument to `['contextmenu']`, the `handle_click` function will be called on right-click.
+    It clears the context menu and adds items based on the object that was clicked.
+''')
+def context_menu_for_3d_objects():
+    from nicegui import events
+
+    def handle_click(e: events.SceneClickEventArguments) -> None:
+        context_menu.clear()
+        name = next((hit.object_name for hit in e.hits if hit.object_name), None)
+        with context_menu:
+            if name == 'sphere':
+                ui.item('SPHERE').classes('font-bold')
+                ui.menu_item('inspect')
+                ui.menu_item('open')
+            if name == 'box':
+                ui.item('BOX').classes('font-bold')
+                ui.menu_item('rotate')
+                ui.menu_item('move')
+
+    with ui.element():
+        context_menu = ui.context_menu()
+        with ui.scene(width=285, height=220, on_click=handle_click,
+                      click_events=['contextmenu']) as scene:
+            scene.sphere().move(x=-1, z=1).with_name('sphere')
+            scene.box().move(x=1, z=1).with_name('box')
+
+
 @doc.demo('Draggable objects', '''
 @doc.demo('Draggable objects', '''
     You can make objects draggable using the `.draggable` method.
     You can make objects draggable using the `.draggable` method.
     There is an optional `on_drag_start` and `on_drag_end` argument to `ui.scene` to handle drag events.
     There is an optional `on_drag_start` and `on_drag_end` argument to `ui.scene` to handle drag events.