浏览代码

add drag constraints

Falko Schindler 1 年之前
父节点
当前提交
9304fb458a
共有 2 个文件被更改,包括 15 次插入3 次删除
  1. 12 3
      nicegui/elements/scene.js
  2. 3 0
      nicegui/elements/scene.py

+ 12 - 3
nicegui/elements/scene.js

@@ -120,7 +120,14 @@ export default {
     }
     this.controls = new OrbitControls(this.camera, this.renderer.domElement);
     this.drag_controls = new DragControls(this.draggable_objects, this.camera, this.renderer.domElement);
-    const handle_drag = (event) => {
+    const applyConstraint = (constraint, position) => {
+      if (!constraint) return;
+      const [variable, expression] = constraint.split("=").map((s) => s.trim());
+      position[variable] = eval(expression.replace(/x|y|z/g, (match) => `(${position[match]})`));
+    };
+    const handleDrag = (event) => {
+      this.drag_constraints.split(",").forEach((constraint) => applyConstraint(constraint, event.object.position));
+      if (event.type === "drag") return;
       this.$emit(event.type, {
         type: event.type,
         object_id: event.object.object_id,
@@ -131,8 +138,9 @@ export default {
       });
       this.controls.enabled = event.type == "dragend";
     };
-    this.drag_controls.addEventListener("dragstart", handle_drag);
-    this.drag_controls.addEventListener("dragend", handle_drag);
+    this.drag_controls.addEventListener("dragstart", handleDrag);
+    this.drag_controls.addEventListener("drag", handleDrag);
+    this.drag_controls.addEventListener("dragend", handleDrag);
 
     const render = () => {
       requestAnimationFrame(() => setTimeout(() => render(), 1000 / 20));
@@ -393,5 +401,6 @@ export default {
     width: Number,
     height: Number,
     grid: Boolean,
+    drag_constraints: String,
   },
 };

+ 3 - 0
nicegui/elements/scene.py

@@ -61,6 +61,7 @@ class Scene(Element,
                  on_click: Optional[Callable[..., Any]] = None,
                  on_drag_start: Optional[Callable[..., Any]] = None,
                  on_drag_end: Optional[Callable[..., Any]] = None,
+                 drag_constraints: str = '',
                  ) -> None:
         """3D Scene
 
@@ -75,6 +76,7 @@ class Scene(Element,
         :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
+        :param drag_constraints: comma-separated JavaScript expression for constraining positions of dragged objects (e.g. ``'x = 0, z = y / 2'``)
         """
         super().__init__()
         self._props['width'] = width
@@ -91,6 +93,7 @@ class Scene(Element,
         self.on('click3d', self.handle_click)
         self.on('dragstart', self.handle_drag)
         self.on('dragend', self.handle_drag)
+        self._props['drag_constraints'] = drag_constraints
 
     def __enter__(self) -> 'Scene':
         Object3D.current_scene = self