Canvas之图形变换

Canvas之图形变换

图形变换可以分为移动,旋转,放缩,以及矩阵斜切。

图形移动

js 复制代码
ctx.fillRect(0,0,100,100)
ctx.translate(100, 100);
ctx.beginPath();
ctx.moveTo(-400, 0);
ctx.lineTo(400, 0);
ctx.moveTo(0, -400);
ctx.lineTo(0, 400);
ctx.stroke();

ctx.beginPath();
ctx.arc(0, 0, 6, 0, Math.PI * 2)
ctx.fill()

ctx.beginPath();
for(let i=-400; i<=400; i+=10){
    ctx.moveTo(i, -5);
    ctx.lineTo(i, 5);
    ctx.moveTo(-5, i);
    ctx.lineTo(5, i);
    ctx.stroke();
}

ctx.fillRect(100, 100, 100, 100)

这里模拟了一个坐标系,可以看到,当使用 ctx.translate 时,整个坐标系都会进行移动,第一个参数是x偏移,第二个参数是y偏移。这种移动是进行位置变化,是瞬间完成的,不是动画。

当整个坐标系都跟着移动时,可以发现,设置在 translate 之前的图形不受影响,并没有发生移动。

图形放缩

js 复制代码
ctx.translate(0, 400);
ctx.scale(1, -1);

可以使用 ctx.scale 进行图形放缩,参数为x,y放缩比例。还是对坐标系进行放缩,如果小于1,表示缩小,大于1,表示放大。如果是负数,则改变了原来的坐标系方向。

上面的代码代表了将计算机坐标系变换为数学坐标系。只需要进行y轴坐标系的反转。

图像旋转

js 复制代码
ctx.beginPath();
// ctx.strokeStyle = '#f00';
// ctx.setLineDash([10]);
ctx.strokeRect(100, 100, 50, 50)

ctx.translate(125, 125);
ctx.rotate(Math.PI / 4);

ctx.fillRect(-25, -25, 50, 50)

可以进行图形旋转,旋转和 css 类似,不过旋转的是坐标系。传入需要旋转的角度,逻辑上需要角度,实际上传入弧度。旋转时按顺时针旋转。

由于是坐标系进行旋转,所以设置移动和旋转的顺序不同,最后的效果也不相同。并且要根据实际情况改变坐标系的位置以及图形的坐标。

矩阵变换

想要更好地实现变换效果需要使用矩阵变换。矩阵变换就是将一个原始的坐标通过一定的规则变为一个新坐标。这个新坐标为了更好的实现平移操作,将原来的坐标变为了齐次坐标,也就是增加了一个维度,最后一个维度和平移相关。

text 复制代码
|x|	  |a	c	e|		|x'|
|y|	* |b	d	f|	=	|y'|
|1|	  |0	0	1|		|1 |

x' = x*a + y*c + 1*e
y' = x*b + y*d * 1*f
1 =  x*0 + y*0 + 1*1

一列坐标对应一行矩阵,三行矩阵对应三个结果。为了保证两个坐标的x,y坐标一致,所以最后的一行统一为 0 0 1 。

使用 ctx.transform(a , b , c , d , e , f) 来进行一一对应。斜切只能通过矩阵变换的方式实现。

text 复制代码
1 0 e
0 1 f

平移变换,不改变x,y的大小,只改变最后的数值大小。

text 复制代码
a 0 0
0 d 0

放缩变换,x行和y行都对应具体的放缩大小。

text 复制代码
	1		tan(angle)	0
tan(angle) 		1		0

斜切变换,沿着x轴或者y轴进行拉扯,拉扯之后会有一个对应角度,x行会后一个y的拉扯角度,y行也一样。

text 复制代码
和角公式
sin(a+b) = sin(a) * cos(b) + cos(a) * sin(b)
cos(a+b) = cos(a) * cos(b) - sin(a) * sin(b)

cos(angle) -sin(angle) 0
sin(angle) cos(angle) 0

旋转变换,需要用到和角公式。a为原位置的旋转角度,b为原位置与x轴的夹角。因为旋转从x轴正方向开始,沿着顺时针进行旋转。

第一行x是余弦的和角公式,第二行y是正弦的和角公式,保留了旋转的角度对应的三角函数,原始位置的角度被消掉。

相关推荐
止观止3 分钟前
Remix框架:高性能React全栈开发实战
前端·react.js·前端框架·remix
萌萌哒草头将军22 分钟前
🚀🚀🚀 深入探索 Node.js v22.18.0 新特性;默认支持运行 ts 文件了!
前端·typescript·node.js
安心不心安37 分钟前
React ahooks——副作用类hooks之useThrottleFn
前端·javascript·react.js
秋田君1 小时前
Vue3 + WebSocket网页接入弹窗客服功能的完整实现
前端·javascript·websocket·网络协议·学习
浪里行舟1 小时前
一网打尽 Promise 组合技:race vs any, all vs allSettled,再也不迷糊!
前端·javascript·vue.js
Antonio9151 小时前
【网络编程】WebSocket 实现简易Web多人聊天室
前端·网络·c++·websocket
德育处主任Pro2 小时前
p5.js 用 beginGeometry () 和 endGeometry () 打造自定义 3D 模型
开发语言·javascript·3d
tianzhiyi1989sq3 小时前
Vue3 Composition API
前端·javascript·vue.js
今禾3 小时前
Zustand状态管理(上):现代React应用的轻量级状态解决方案
前端·react.js·前端框架