自定义View之几何变换

589 阅读2分钟

今天记录一个几何变换的计算原理以及两种写法

两种方法

现在先看图

image.png

我们绘制两个方块,一个在坐标(100, 100) ,另一个在它向右移动300,向下移动100,再绕中心顺时针旋转15°

paint.style = Paint.Style.STROKE
paint.color = Color.RED
paint.strokeWidth = 5f

// 方法一
canvas.drawRect(100f, 100f, 300f, 200f, paint)

canvas.save()
canvas.translate(300f, 100f)
canvas.rotate(15f, 200f, 150f)
canvas.drawRect(100f, 100f, 300f, 200f, paint)
canvas.restore()

// 方法二
canvas.drawRect(100f, 100f, 300f, 200f, paint)

canvas.save()
canvas.rotate(15f, 500f, 250f)
canvas.translate(300f, 100f)
canvas.drawRect(100f, 100f, 300f, 200f, paint)
canvas.restore()

大家可以看到,这里两种方法就是这两行不一样,其他都一样

// 方法一
canvas.translate(300f, 100f)
canvas.rotate(15f, 200f, 150f)

// 方法二
canvas.rotate(15f, 500f, 250f)
canvas.translate(300f, 100f)

第一种是先平移,再旋转
第二种是先旋转,再平移

看一下结果

image.png

可以看到,和我们预想的一样

现在来分析两种写法:

分析

第一种

canvas.translate(300f, 100f)
这行是平移,并且平移的是 canvas

canvas.rotate(15f, 200f, 150f) 这个行是旋转,并且旋转的是canvas

也就是这样(绿色为canvas)

先绘制 未经过几何变换的矩形

image.png

这是平移

image.png

这是旋转

image.png

最后绘制几何变换后的矩形

image.png

可以看到,我们调用 rotate() 方法时,填写的是canvas(绿色)对应的坐标,而不是手机屏幕对应的坐标,也就是说,canvas的移动是会带着canvas的坐标一起移动的,也就是这样

image.png

到这里应该就明白了,第一种方法的在rotate() 方法填写的值,是canvas的坐标 并且是先平移,再旋转

第二种

先旋转
canvas.rotate(15f, 500f, 250f)

image.png

然后再平移绘制
canvas.translate(300f, 100f)

image.png

两种方法都可以

第二种方法看似抽象,但其实可以想成移动View ,并且坐标全用手机屏幕的坐标,然后倒着写

// 想要先平移再旋转,就倒着写,然后坐标用手机屏幕的坐标
// 比如:canvas坐标 (200, 150),在手机屏幕坐标就是 (500,250),因为你移动了多以要加上移动的像素长度
// 可以想一下,看成先绘制 View,然后移动它

canvas.rotate(15f, 500f, 250f)
canvas.translate(300f, 100f)
canvas.draw()