使用过前端的css3,canva,svg的小伙伴应该对平移,旋转,缩放,剪切这些效果变换应该很熟悉了,但应该大部分小伙伴应该不清楚其中的原理,在二维图形方面若是能熟练使用图形学的基础算法,结合canva,svg会有意想不到的惊喜。css
计算机图形学中的应用很是普遍的变换是一种称为仿射变换的特殊变换,在仿射变换中的基本变换包括平移、旋转、缩放、剪切这几种。前端
设某点向x方向移动dx,y方向移动dy ,[x,y]为变换前坐标,[X,Y]为变换后坐标。
则css3
X = x+dx; Y = y+dy;
以矩阵表示:算法
首先要明确旋转在二维中是绕着某一个点进行旋转,三维中是绕着某一个轴进行旋转。二维旋转中最简单的场景是绕着坐标原点进行的旋转,以下图所示:canvas
如图所示点v 绕 原点旋转θ角,获得点v’,假设 v点的坐标是(x, y) ,那么能够推导获得 v’点的坐标(x’, y’),设原点到v的距离是r,原点到v点的向量与x轴的夹角是ϕsvg
x=rcosϕy=rsinϕ x′=rcos(θ+ϕ)y′=rsin(θ+ϕ)
经过三角函数展开获得函数
x′=rcosθcosϕ−rsinθsinϕ y′=rsinθcosϕ+rcosθsinϕ
带入x和y表达式获得spa
x′=xcosθ−ysinθ y′=xsinθ+ycosθ
写成矩阵的形式是:code
尽管图示中仅仅表示的是旋转一个锐角θ的情形,可是咱们推导中使用的是三角函数的基本定义来计算坐标的,所以当旋转的角度是任意角度(例如大于180度,致使v’点进入到第四象限)结论仍然是成立的。图片
简单缩放能够直接经过将缩放系数sx,sy与对应x,y坐标相乘:
x’=x*sx,y’=y*sy
x’ = x * sx + sy(1-sx) y’ = y * sy + yf(1-sy)
其中sx,sy属于缩放系数。0~1表示缩小,>1表示放大
图像错切变换在图像几何形变方面很是有用,常见的错切变换分为X方向与Y方向的错切变换。对应的数学矩阵分别以下:
根据上述矩阵假设P(x1, y1)为错切变换以前的像素点,则错切变换之后对应的像素
P’(x2, y2)当X方向错切变换时:
x2 = x1 - y1 * tanθ y2 = y1
当Y方向错切变换时:
x2 = x1 y2 = y1 - x1 * tanθ
只贴上旋转的demo,其余均可以仿照套用
橘色的点围绕蓝色旋转
var canvas = document.getElementById("canvas"); var context = canvas.getContext('2d'); context.beginPath(); context.fillStyle = "#3399ff"; context.arc(100, 75, 5, 0, 2 * Math.PI); context.fill(); //点a围绕(100,75) 顺时针90度旋转 var a = { x: 150, y: 75 } //套用上文公式 //- 0.5 * Math.PI 由于canvas的0 var x = 100 + (a.x - 100) * Math.cos(Math.PI / 2) - (a.y - 75) * Math.sin(Math.PI / 2); //y为简化后 var y = 75 + (a.x - 100) * Math.sin(Math.PI / 2); context.beginPath(); context.fillStyle = "#fe9901"; context.arc(x, y, 5, 0, 2 * Math.PI); context.fill(); //围绕100,75 60度旋转 var x = 100 + 50 * Math.cos(Math.PI / 3); var y = 75 + 50 * Math.sin(Math.PI / 3); context.beginPath(); context.fillStyle = "#fe9901"; context.arc(x, y, 5, 0, 2 * Math.PI); context.fill();