7

二维图形学的变换

使用过前端的css3,canva,svg的小伙伴应该对平移,旋转,缩放,剪切这些效果变换应该很熟悉了,但应该大部分小伙伴应该不清楚其中的原理,在二维图形方面如果能熟练使用图形学的基础算法,结合canva,svg会有意想不到的惊喜。

计算机图形学中的应用非常广泛的变换是一种称为仿射变换的特殊变换,在仿射变换中的基本变换包括平移、旋转、缩放、剪切这几种。

平移

设某点向x方向移动dx,y方向移动dy ,[x,y]为变换前坐标,[X,Y]为变换后坐标。

 X = x+dx;  Y = y+dy;

以矩阵表示:
图片描述

旋转

首先要明确旋转在二维中是绕着某一个点进行旋转,三维中是绕着某一个轴进行旋转。二维旋转中最简单的场景是绕着坐标原点进行的旋转,如下图所示:

图片描述

如图所示点v 绕 原点旋转θ角,得到点v’,假设 v点的坐标是(x, y) ,那么可以推导得到 v’点的坐标(x’, y’),设原点到v的距离是r,原点到v点的向量与x轴的夹角是ϕ

x=rcosϕy=rsinϕ
 
x′=rcos(θ+ϕ)y′=rsin(θ+ϕ)

通过三角函数展开得到

x′=rcosθcosϕ−rsinθsinϕ
 
y′=rsinθcosϕ+rcosθsinϕ

带入x和y表达式得到

x′=xcosθ−ysinθ
 
y′=xsinθ+ycosθ

写成矩阵的形式是:
图片描述

尽管图示中仅仅表示的是旋转一个锐角θ的情形,但是我们推导中使用的是三角函数的基本定义来计算坐标的,因此当旋转的角度是任意角度(例如大于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θ

实例

svg

canvas

只贴上旋转的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();

梵鹿
246 声望37 粉丝