轻量级 Infinite Canvas 用原生 Canvas 实现拖拽与缩放
一个关于无限画布的教程,帮助开发者理解和实现无限画布的概念与功能。
无限画布是一种允许用户以非线性方式自由组织内容的界面,支持缩放、直观编辑基本图形(如移动、分组和修改样式)等功能。”
当然可以!我来给你分成三部分讲解 xiaoiver/infinite-canvas-tutorial 项目的核心内容,让你更清晰地理解它的设计思路:
1. 项目目的:打造一个基本的「无限画布」
- 目标是让画布可以被拖动(pan)、缩放(zoom),并且画面上的元素(比如点、矩形)随着拖拽或缩放正确跟随变换。
- 重点是操作的是视图,而不是操作元素本身。也就是说,图形坐标是固定的,用户是在「移动摄像机」看画布。
2. 主要功能点讲解
3. 核心代码逻辑梳理
一个标准的渲染流程大概是这样:
function draw() {
ctx.save(); // 保存当前变换状态
ctx.setTransform(scale, 0, 0, scale, offsetX, offsetY); // 应用平移和缩放
ctx.clearRect(-offsetX/scale, -offsetY/scale, canvas.width/scale, canvas.height/scale); // 清除画布
// 绘制固定在世界坐标下的图形
drawAllElements();
ctx.restore(); // 恢复变换状态
}
scale
控制缩放大小。offsetX
和offsetY
控制画布的平移。- 每次绘制前,先应用缩放和平移的变换,再绘制图形。
交互时,例如:
- 鼠标拖动 -> 更新
offsetX/offsetY
- 鼠标滚轮 -> 更新
scale
- 然后重新调用
draw()
重绘
补充细节
- 画布初始化时,需要根据设备像素比(DPR)调整
canvas.width
和canvas.height
,保证高分屏下画质清晰。 - 缩放时为了做到以鼠标指针为中心,需要用一些简单的坐标换算公式。
小结
这个项目可以看作是:
- 极简版白板引擎
- 交互式 2D 编辑器的基础
- 理解 Canvas 变换矩阵的实践
它只是基础版,但如果想扩展,比如加上:
- 元素选择、拖拽、删除
- 连线、分组
- 多人协作同步
- 保存和恢复画布内容
就可以慢慢做成类似 Figma / Miro / Excalidraw 这样的复杂应用了!
GitHub:https://github.com/xiaoiver/infinite-canvas-tutorial
油管:https://youtu.be/Sj0sZU0eKx8
留言
發佈留言