跳到主要内容
← 返回文章列表
开发实战2026/09/15约 5 分钟读完

构建可靠的自由画布交互:VueMovableBox 项目介绍

VueMovableBox 是一个面向 Vue 3 的可拖拽、可缩放、可旋转容器组件。它不仅提供基础的位置与尺寸调整,还覆盖边界约束、网格和元素吸附、旋转碰撞、多选组合移动、键盘操作与完整交互事件,适合低代码编辑器、可视化搭建、画布设计器、标注工具等需要直接操作元素的前端项目。

构建可靠的自由画布交互:VueMovableBox 项目介绍
文章目录 6

在普通业务页面中,拖动一个元素往往只需要监听指针位置;但到了可视化编辑器,问题会迅速变复杂:元素不能越过画布,需要吸附到参考对象,旋转后仍要正确判断边界和碰撞,多选元素还必须保持相对位置。缩放、百分比坐标、触摸输入和键盘控制叠加后,简单的 left、top 更新已经不足以保证交互正确。

VueMovableBox 正是为这类场景设计的。组件以受控数据为核心,通过 v-model 管理位置和尺寸,通过 v-model:rotate 管理旋转角度。业务层始终持有最终状态,组件负责把指针、键盘、边界、吸附和碰撞等交互转换成可预测的数据更新。

一个组件覆盖常见画布交互

VueMovableBox 的基础能力包括:

  • 拖拽与八方向缩放,可限制允许操作的方向和手柄。

  • 顺时针旋转、角度吸附以及自定义 transform-origin。

  • 像素与百分比坐标,支持页面缩放比例和小数精度控制。

  • 父容器边界、独立边距、网格吸附和元素对齐吸附。

  • 旋转矩形精确碰撞,也保留 AABB 兼容模式作为迁移入口。

  • Pointer Events 统一鼠标、触摸和触控笔输入。

  • 键盘移动、缩放、旋转以及 Escape 取消交互。

  • 完整的开始、过程、结束、取消、吸附和碰撞事件。

这些能力不是彼此孤立的开关。组件内部按照“方向限制 → 网格吸附 → 元素吸附 → 边界限制 → 碰撞校验”的顺序处理交互,避免一个功能的计算结果绕过另一个功能的安全约束。

复杂交互背后的设计重点

VueMovableBox 的重点不是简单堆叠功能开关,而是让边界、吸附、碰撞、旋转与组合移动在同一套交互流程中稳定协作。

首先是旋转几何。启用精确碰撞后,方框与目标会按照真实旋转轮廓参与检测,而不是只比较未旋转矩形。旋转、缩放或快速拖动时,组件还会检查变化路径,降低单帧位移较大时直接穿过薄障碍物的风险。

其次是组合移动。MovableGroup 可以协调多个 MovableBox,让选中元素保持相对位置共同移动。groupCollision="all" 会让任意成员与外部障碍物的最早接触限制整个组合,而不是只检查鼠标所在的引导元素。需要注意的是,它当前负责的是组合移动,并不等同于组合缩放或组合旋转工具。

旋转输出与其他交互数据使用相同的精度规则:关闭 isKeepDecimals 时输出整数;开启后按照 decimalPlaces 保留小数。指针旋转、键盘旋转和角度吸附都会遵循该规则,而父组件传入的 rotate 仍是权威值,不会被子组件擅自纠正回写。

在工程层面,项目提供碰撞诊断页、完整接入示例、三浏览器 E2E、包消费验证和性能基线。它们用于验证组件在真实浏览器、不同模块格式和复杂场景下的行为,而不是只依赖演示页面判断功能是否可用。

最小接入示例

安装组件:

pnpm add vue-movable-box

在 Vue 3 单文件组件中直接使用:

<script setup lang="ts">
import { ref } from 'vue';
import { MovableBox, type MovableBoxRect } from 'vue-movable-box';
import 'vue-movable-box/style.css';

const rect = ref<MovableBoxRect>({
  left: 40,
  top: 40,
  width: 240,
  height: 140
});
const angle = ref(0);
</script>

<template>
  <div class="canvas">
    <MovableBox
      v-model="rect"
      v-model:rotate="angle"
      active
      rotatable
      keyboard-enabled
      limit-area-for-parent
    >
      拖动、缩放或旋转我
    </MovableBox>
  </div>
</template>

<style scoped>
.canvas {
  position: relative;
  width: 800px;
  height: 480px;
  overflow: hidden;
  border: 1px solid #dcdfe6;
}
</style>

这个示例已经包含受控位置、尺寸、旋转、键盘操作和父容器边界。业务需要保存画布时,只需持久化 rect 与 angle;需要撤销重做时,也可以直接围绕这两个状态建立历史记录。

它适合哪些项目

VueMovableBox 比较适合以下场景:

  • 低代码或零代码页面搭建器。

  • 海报、流程图、看板和可视化画布。

  • 图片标注、区域框选和素材排版工具。

  • 需要拖拽、旋转、吸附和碰撞约束的业务编辑器。

  • 需要多选元素整体移动,同时由业务层保存布局状态的 Vue 3 应用。

如果需求只有列表排序,应该优先选择专门的 sortable 组件;如果目标是自由画布中的位置、尺寸和旋转交互,VueMovableBox 才更贴近问题本身。

使用时需要理解的边界

组件能够处理复杂几何,但业务仍需要提供正确的数据契约。snapTargets 和 collisionTargets 应与当前方框使用同一坐标体系;百分比模式下数值表示百分点,而不是像素。精确碰撞适合旋转轮廓明显的场景,如果旧项目依赖轴对齐矩形判断,可以通过 collision-mode="aabb" 逐步迁移。

强制禁用组件与主动取消交互也有区别:disabled、initRect 或外部取消激活会让当前操作就地结束;Escape、pointercancel 或 cancelInteraction() 才会恢复交互开始前的值并发出取消事件。理解这一区别,才能正确实现撤销、保存和协同编辑。

总结

VueMovableBox 解决的并不是“让一个 div 跟着鼠标移动”这么简单的问题,而是自由画布中多种约束同时存在时,如何持续输出可靠、可保存、可测试的布局状态。它把旋转碰撞、组合移动、精度控制和工程验证纳入统一设计,为 Vue 3 可视化编辑场景提供了一套相对完整的交互基础。

评论

0 条

评论会在审核后展示,邮箱不会公开。

正在确认登录状态

5000 / 5000