浏览代码

introduce drag events

Falko Schindler 1 年之前
父节点
当前提交
c1bb5806eb
共有 3 个文件被更改,包括 51 次插入6 次删除
  1. 13 2
      nicegui/elements/scene.js
  2. 27 3
      nicegui/elements/scene.py
  3. 11 1
      nicegui/events.py

+ 13 - 2
nicegui/elements/scene.js

@@ -120,8 +120,19 @@ export default {
     }
     this.controls = new OrbitControls(this.camera, this.renderer.domElement);
     this.drag_controls = new DragControls(this.draggable_objects, this.camera, this.renderer.domElement);
-    this.drag_controls.addEventListener("dragstart", () => (this.controls.enabled = false));
-    this.drag_controls.addEventListener("dragend", () => (this.controls.enabled = true));
+    const handle_drag = (event) => {
+      this.$emit(event.type, {
+        type: event.type,
+        object_id: event.object.object_id,
+        object_name: event.object.name,
+        x: event.object.position.x,
+        y: event.object.position.y,
+        z: event.object.position.z,
+      });
+      this.controls.enabled = event.type == "dragend";
+    };
+    this.drag_controls.addEventListener("dragstart", handle_drag);
+    this.drag_controls.addEventListener("dragend", handle_drag);
 
     const render = () => {
       requestAnimationFrame(() => setTimeout(() => render(), 1000 / 20));

+ 27 - 3
nicegui/elements/scene.py

@@ -3,7 +3,8 @@ from typing import Any, Callable, Dict, List, Optional, Union
 
 from .. import binding, globals
 from ..element import Element
-from ..events import GenericEventArguments, SceneClickEventArguments, SceneClickHit, handle_event
+from ..events import (GenericEventArguments, SceneClickEventArguments, SceneClickHit, SceneDragEventArguments,
+                      handle_event)
 from ..helpers import KWONLY_SLOTS
 from .scene_object3d import Object3D
 
@@ -58,10 +59,12 @@ class Scene(Element,
                  height: int = 300,
                  grid: bool = True,
                  on_click: Optional[Callable[..., Any]] = None,
+                 on_drag_start: Optional[Callable[..., Any]] = None,
+                 on_drag_end: Optional[Callable[..., Any]] = None,
                  ) -> None:
         """3D Scene
 
-        Display a 3d scene using `three.js <https://threejs.org/>`_.
+        Display a 3D scene using `three.js <https://threejs.org/>`_.
         Currently NiceGUI supports boxes, spheres, cylinders/cones, extrusions, straight lines, curves and textured meshes.
         Objects can be translated, rotated and displayed with different color, opacity or as wireframes.
         They can also be grouped to apply joint movements.
@@ -69,7 +72,9 @@ class Scene(Element,
         :param width: width of the canvas
         :param height: height of the canvas
         :param grid: whether to display a grid
-        :param on_click: callback to execute when a 3d object is clicked
+        :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
         """
         super().__init__()
         self._props['width'] = width
@@ -79,9 +84,13 @@ class Scene(Element,
         self.stack: List[Union[Object3D, SceneObject]] = [SceneObject()]
         self.camera: SceneCamera = SceneCamera()
         self.on_click = on_click
+        self.on_drag_start = on_drag_start
+        self.on_drag_end = on_drag_end
         self.is_initialized = False
         self.on('init', self.handle_init)
         self.on('click3d', self.handle_click)
+        self.on('dragstart', self.handle_drag)
+        self.on('dragend', self.handle_drag)
 
     def handle_init(self, e: GenericEventArguments) -> None:
         self.is_initialized = True
@@ -115,6 +124,21 @@ class Scene(Element,
         )
         handle_event(self.on_click, arguments)
 
+    def handle_drag(self, e: GenericEventArguments) -> None:
+        arguments = SceneDragEventArguments(
+            sender=self,
+            client=self.client,
+            type=e.args['type'],
+            object_id=e.args['object_id'],
+            object_name=e.args['object_name'],
+            x=e.args['x'],
+            y=e.args['y'],
+            z=e.args['z'],
+        )
+        if arguments.type == 'dragend':
+            self.objects[arguments.object_id].move(arguments.x, arguments.y, arguments.z)
+        handle_event(self.on_drag_start if arguments.type == 'dragstart' else self.on_drag_end, arguments)
+
     def __len__(self) -> int:
         return len(self.objects)
 

+ 11 - 1
nicegui/events.py

@@ -1,6 +1,6 @@
 from dataclasses import dataclass
 from inspect import Parameter, signature
-from typing import TYPE_CHECKING, Any, Awaitable, BinaryIO, Callable, Dict, List, Optional
+from typing import TYPE_CHECKING, Any, Awaitable, BinaryIO, Callable, Dict, List, Literal, Optional
 
 from . import background_tasks, globals
 from .helpers import KWONLY_SLOTS
@@ -53,6 +53,16 @@ class SceneClickEventArguments(ClickEventArguments):
     hits: List[SceneClickHit]
 
 
+@dataclass(**KWONLY_SLOTS)
+class SceneDragEventArguments(ClickEventArguments):
+    type: Literal['dragstart', 'dragend']
+    object_id: str
+    object_name: str
+    x: float
+    y: float
+    z: float
+
+
 @dataclass(**KWONLY_SLOTS)
 class ColorPickEventArguments(EventArguments):
     color: str