给图片加水印,想让文字斜着排。写了 rotate,结果整张图转到画布外面去了。查了半天参数,问题不在角度上。

canvas 的 rotate 转的是坐标系,不是某个元素。它没有中心点参数,默认绕原点,也就是画布左上角。

绕左上角转,所以一定跑偏

画布左上角是坐标原点。直接调 rotate 传 45 度,整个坐标系跟着转,你后面画的东西自然被甩到视野外。看起来像图片消失,其实是画到了看不见的区域。

解决办法只有一个:先把原点挪到要旋转的中心,再转,画完再挪回来。

标准三步

第一步平移,把原点移到目标中心点;第二步旋转,角度换算成弧度;第三步把图形按中心在原点的方式画出来,最后恢复上下文。

角度单位是弧度,不是度。常见写法是角度乘圆周率再除以 180。直接传 45,转的是 45 弧度,转七圈多,看着像没转。

用保存和恢复兜住状态

  • 旋转会改变之后所有绘制,一定包在保存和恢复之间;
  • 多层嵌套时每层各存各的,别指望一次恢复管全部;
  • 画文字要同时设对齐方式,否则基线会偏一截;
  • 旋转后的坐标系里,宽高方向也换了,布局要重新想。

第四点最容易被忽略。竖着写的文字,在旋转后的坐标系里是按横向排的,别拿旋转前的坐标硬套。

高清屏还要处理缩放

画布按样式尺寸显示时,在高分屏上会糊。做法是把画布实际像素放大到设备像素比,再用缩放把绘制坐标压回原来的比例。

缩放和旋转叠在一起时,调用顺序会改变结果:先缩放后旋转,和先旋转后缩放,出来的位置不一样。推不清顺序就用变换矩阵一次设好,把平移、旋转、缩放合成一组,可读性差一点,但结果确定。

调试的小办法

临时给画布加个边框,再在原点画一个十字标记,能直观看出坐标系被转到哪去了,比盯着代码猜快得多。刚开始调的时候,把要画的内容换成一个方块,比拿真图试省时间。

另外,开发者工具里改样式是实时的,但画布内容不会跟着重绘。改完参数得手动重跑一次绘制,否则盯着看的还是旧画面,很容易以为改动没生效。

说到底,canvas 里所有变换都是对坐标系动手。想通这一点,缩放、镜像、倾斜都是同一套逻辑。