You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何通过CustomPaint实现拖拽绘制图形功能

Flutter 白板拖拽绘制规则图形实现

这个功能逻辑和你之前写的自由画线不一样,不需要记录拖拽路径上的所有点位,只要记住拖拽动作的起点、实时移动的终点,两个点就能确定图形的位置和尺寸,按下面的步骤写就能做出你截图里的拖拽预览、松手落图的效果:

  • 先定义好需要的状态变量
    在绘制页的State里存这几个值就行:

    • 当前选中的工具类型(自由线/矩形/圆形/箭头等,用枚举存最方便)
    • 拖拽起始点:Offset? _dragStart
    • 拖拽实时点位:Offset? _dragCurrent
    • 已绘制完成的元素列表:每个元素存清楚类型、起点、终点、画笔参数就行,别直接存渲染好的Path,后面要做选中、缩放、删除的时候会很麻烦。
  • 给GestureDetector绑三个拖拽事件
    逻辑非常直接:

    1. onPanStart:手指按到屏幕的时候,把当前触点坐标赋值给_dragStart,同时也给_dragCurrent赋同一个值,调setState刷新界面
    2. onPanUpdate:手指在屏幕上拖的时候,把最新的触点坐标更新给_dragCurrent,每更新一次就刷一次界面,这时候就能看到图形跟着手指变大小变位置的预览效果
    3. onPanEnd:手指抬起来的时候,把_dragStart和_dragCurrent拼起来存成一个正式的图形元素,加到已绘制列表里,然后把两个拖拽点位清空,再刷一次界面就完成落图了。
  • 在CustomPaint里分两层画
    重写CustomPainter的paint方法的时候,按顺序画就行:

    1. 先遍历已绘制的元素列表,根据每个元素的类型、起止点,用正常的不透明实边画笔把所有历史内容画出来
    2. 再判断如果_dragStart和_dragCurrent都不为空,说明用户正在拖动画图形,这时候用两个点生成外接矩形,拿半透明的预览画笔(也可以做虚线效果)画当前的临时图形,就和你截图里的效果一致了。

    画矩形的核心代码就几行:

    // 正在拖拽画矩形的时候
    if (currentTool == ShapeType.rectangle && _dragStart != null && _dragCurrent != null) {
      // fromPoints会自动处理四个拖拽方向的点位顺序,不用自己算坐标大小
      final rect = Rect.fromPoints(_dragStart!, _dragCurrent!);
      // 预览画笔可以设成70%透明度,和正式图形做区分
      canvas.drawRect(rect, previewPaint);
    }
    

    其他图形逻辑完全一样:椭圆/圆形直接把外接矩形传给canvas.drawOval(),直线就连两个点,三角形取外接矩形的三个顶点画路径就行。

小提示:如果要加按住快捷键画正圆、正方形的功能,只要在onPanUpdate里判断按键状态,把_dragCurrent的坐标做等比修正再赋值就行,不用改其他逻辑。

实现效果参考:
拖拽绘制图形示例


内容的提问来源于stack exchange,提问作者Kevin Yang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:15:17