Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
framework framework/gsap/draggable.md medium

gsap-draggable

Draggable 插件 — 编辑器画布元素拖拽 / 自定义滑动控件,性能优于手写 mousemove handler。Use when 给画布元素加拖拽 / 需 bounds 限制拖拽范围 / 评审 Draggable.create 用法时。

draggablegsap.draggable拖拽
paths
  • frontend/src/animations/**/*.ts
  • frontend/src/features/editor/**/*.tsx

GSAP · Draggable 插件

何时用

GSAP Draggable 是编辑器画布元素拖拽的标准方案。性能优于自写 mousemove handler。

适用场景

场景
编辑器画布元素移动
演示模式画笔绘制
自定义滑动控件(非 antd Slider)
列表反向拖拽(DnD)— 用 dnd-kit + Flip 更好(见 flip-layout.md

安装

// src/main.tsx
import gsap from "gsap";
import { Draggable } from "gsap/Draggable";
gsap.registerPlugin(Draggable);

编辑器画布元素拖拽

// src/animations/editor.ts
import { Draggable } from "gsap/Draggable";

export function createElementDraggable(
  target: HTMLElement,
  bounds: HTMLElement,
  onDragEnd: (x: number, y: number) => void,
) {
  return Draggable.create(target, {
    type: "x,y",
    bounds,
    inertia: false,                 // 编辑场景禁惯性,要精确停在松手位置
    onPress() {
      target.style.cursor = "grabbing";
    },
    onRelease() {
      target.style.cursor = "grab";
      onDragEnd(this.x, this.y);    // this 是 Draggable 实例
    },
  })[0];
}

React 集成

import { useGSAP } from "@gsap/react";
import { createElementDraggable } from "@/animations/editor";

function CanvasElement({ id, x, y, onMove }: Props) {
  const ref = useRef<HTMLDivElement>(null);
  const canvasRef = useContext(CanvasRef);

  useGSAP(() => {
    if (!ref.current || !canvasRef.current) return;
    gsap.set(ref.current, { x, y });

    const drag = createElementDraggable(
      ref.current,
      canvasRef.current,
      (nx, ny) => onMove(id, nx, ny),
    );

    return () => drag.kill();
  }, { scope: ref });

  return <div ref={ref} className="canvas-element">...</div>;
}

多选拖拽

Draggable.create(targets, {   // 数组 → 每个元素独立 drag
  type: "x,y",
});

禁惯性

inertia 何时
false 编辑器(要精确停在松手位置)
true 卡片轻量滑动(如演示模式画笔)

inertia: true 需要 InertiaPlugin(gsap/InertiaPlugin)或用 ThrowPropsPlugin 替代。

自检

  • [ ] 注册了 Draggable 插件?
  • [ ] bounds 限制拖拽范围?
  • [ ] onRelease 触发持久化?
  • [ ] 编辑场景禁惯性?
  • [ ] 卸载时 drag.kill()?

相关