canvas动态网格缩放与吸附核心是精准坐标计算与松手纠偏:只绘视口内自适应网格,鼠标坐标须经getboundingclientrect换算,吸附在mouseup时将图形“掰正”至最近网格中心或对齐线,辅以8锚点动态辅助线对齐。

Canvas 实现动态网格缩放与吸附,核心不在“画得多密”,而在“算得准、判得稳、改得准”。网格要随缩放实时响应,吸附要基于真实坐标逻辑干预——不是视觉跟随,是松手那一刻把图形位置“掰正”到最近的网格中心或对齐线。
网格绘制:只画视口内、缩放自适应
性能关键在于避免全量绘制。只计算当前可视区域(canvas.getBoundingClientRect() 获取视图边界),再结合当前缩放比,推算出需绘制的网格线范围:
- 先获取 canvas 在视口中的实际位置和尺寸(必须用 getBoundingClientRect(),不能依赖 offsetLeft/Top)
- 根据当前 scale 计算逻辑间距:比如基础格距为 32px,则显示间距 = 32 / scale;再按需分级(如 8px、32px、128px)生成大/小网格
- 纵向线从 left - padding 开始,以间距递增,止于 right + padding;横向同理,避免边缘截断
- 线宽始终设为 1 CSS 像素(strokeWidth = 1),不随缩放变粗,靠 canvas 像素密度适配高 DPI
坐标换算:鼠标位置必须转 Canvas 本地坐标
浏览器事件坐标(clientX/clientY)默认相对于视口,而 Canvas 绘图坐标系原点在左上角,且受 CSS 缩放、滚动、外边距影响。直接使用必错。
用户要生成可打印的中文字帖/练习纸、导出多页 A4 PDF 报告,或把 SVG 设计稿零误差还原到 Canvas 时使用。本技能是「Canvas 内容工厂闭环」的总控,编排:网格渲染引擎(13 种教育网格+拼音标注) → 多页 PDF 导出(A4 合成) → SVG 精准复刻(坐标误差<0.001px)。触发词:生成字帖、练习纸、导出 PDF、SVG 转 Canvas、印刷级还原、A4 报告、米字格田字格。
- 每次 mousemove/mousedown 前,调用 canvas.getBoundingClientRect() 获取当前 left/top
- 用 e.clientX - rect.left 和 e.clientY - rect.top 得到鼠标在 canvas 内部的真实像素坐标
- 若 canvas 有 CSS 缩放(如 width: 100%; height: auto),必须同步设置 canvas.width/height 属性 匹配渲染尺寸,否则坐标系与绘图失配
吸附逻辑:分阶段判定,mouseup 才执行纠偏
吸附不是拖拽中实时跳动,而是松手瞬间的坐标重置。分三步闭环:
- 预生成吸附点:如网格中心点数组,每个点含 (x, y, row, col),坐标按逻辑格距 × 行列 + 偏移计算(例:c×32+16, r×32+16)
- 距离判定:松手时,用 Math.hypot(dx, dy) 计算图形锚点(如中心)到各吸附点距离,取最小值且 ≤ 阈值(如 12px)者为候选
- 强制纠偏:将图形坐标更新为最近吸附点坐标,并做边界校验(如不能超出画布或容器限制),再重绘
辅助线对齐:8 锚点 + 动态筛选
除网格吸附外,图形间对齐更依赖辅助线。每个图形抽象出 8 个关键锚点(四角 + 四边中点),延伸出水平/垂直线:
- 拖拽中遍历其他可见图形,收集所有候选线(最多 3 条垂线 + 3 条横线)
- 仅保留与当前图形某边/中心距离 ≤ 阈值(如 3px)的线,再选偏移量最小的 1–2 条作为最终吸附目标
- 视觉反馈:红色虚线表边缘对齐,蓝色实线表中心对齐;长度限于两图形相交区域,松手即消失
- 真正对齐发生在 mouseup:水平吸附改 x 或 centerX,垂直吸附改 y 或 centerY,双轴满足则同步修正










