Android自定义view之clip裁切以及几何变换

  今天我们来实践下Android部分的裁切就是clip打头的方法以及一些几何矩阵变换,所谓的裁切,顾名思义就是裁剪啊,就是把一个图形按照另外一个图形切成我们想要的样子,例如我们想把一张图片裁剪为圆形或者矩形或者五角星等等我们想要的形状。而矩阵变换是怎么回事呢?矩阵变换就是进行图形的平移啊、缩放啊、旋转啊,或者在某个方向上拉伸形状啊,这类的操作。

裁切部分

  • clipRect(int left, int top, int right, int bottom)
    这个方法作用就是裁切一个矩形出来,但是图形不还是在canvas上面的,所以本质上还是裁切的canvas画布,使图形只是在裁切出来的那块画布上展示,这就达到了裁切效果,同样参数就按照绘制一个矩形的参数传进去就好了,就是可以认为是矩形的左上角以及右下角的坐标
  • clipPath(@NonNull Path path)
    这个方法比上面的方法灵活很多,因为它传入的是一个Path,所以就提供了更多裁切的可能性了,因为Path本身就可以绘制很多不同的形状啊,发挥大家想象力的时候到了

几何变换

  • canvas.translate(float dx, float dy)
    画布的平移,其实就是坐标系的平移,原来坐标系原点是在手机屏幕左上角,如果canvas.translate(200, 0)就代表将坐标系向右移动了200,所以现在的坐标原点变成了(200,0)了,就是这么个意思
  • canvas.rotate(float degrees, float px, float py)
    画布的旋转,degress就是旋转角度,正数为顺时针旋转,负数为逆时针旋转,后面的px和py则是旋转中心,所以坐标系也会进行相应的旋转,所以绘制的图形自然也是被旋转了
  • canvas.scale(float sx, float sy, float px, float py)
    画布的缩放,前面的sx和sy是指在x方向上以及y方向上的缩放是原来的几倍,后面的px和py则是旋转中心,好比缩放为原来的2倍,那么原来的1px相当于现在的2px,那么展示的图形自然会大
  • canvas.skew(float sx, float sy)
    画布的拉伸,sx和sy则是在水平方向和竖直方向上的拉伸,这个拉伸不等于缩放,举个例子,好比现在有一个矩形,我在水平方向上进行拉伸,那么如果sx>0则是图片会向右拉伸,那么原矩形的平行于y轴的边会向左倾斜,矩形变成了什么呢?矩形就变成了一个平行四边形,如果sy>0也满足,那么原来矩形平行于x轴的边会向向下,同样也会变成一个平行四边形
      以上都是通过canvas自带的方法进行的几何变换,但是它的方法是有限的,就是我不只是想变换一下位置,旋转一下、拉伸一下或者缩放一下,我还想有别的操作怎么办?那么只是通过canvas自带的这几个方法的话,canvas该说“臣妾办不到啊”,所以这个时候我们可以通过操作canvas的矩阵Matrix来实现
  • matrix也有跟canvas相同的平移、缩放、旋转、拉伸的方法,用法跟上面的类似就不多说了,那么matrix我们设置了一个matrix是怎么和canvas结合起来的呢?这里我们用canvas.concat(matrix)方法而不是canvas.setMatrix(matrix),因为后者会有兼容性问题,在不同的手机上可能效果会不一致,同时后者会将canvas自己的matrix给替换掉,而concat不是一种替换,只是一种跟canvas原有矩阵相乘的方式,同时setMatrix方法的注释注释也说了:Note: it is recommended to use {@link #concat(Matrix)}, {@link #scale(float, float)}, {@link #translate(float, float)} and {@link #rotate(float)} instead of this method. 人家强烈建议使用除了setMatrix之外的其他方法啦
  • matrix.setPolyToPoly(float[] src, int srcIndex,float[] dst, int dstIndex,int pointCount)
    上面咱们也说了之所以会选择使用matrix来做几何变换,是因为它能够自定义一些东西,那么就主要是用这个方法,这个方法是干嘛的呢?官方注释翻译后是 设置矩阵,使得指定的src点将映射到指定的dst点。 “点”表示为一个浮点数组,顺序为[x0,y0,x1,y1,…],其中每个“点”为2个浮点值,说的通俗点就是自己首先要定义一个源数组(每两个元素组成一个point的横纵坐标),然后需要定义一个目标数组(每两个元素组成一个point的横纵坐标),然后将源数组中的点映射到目标数组中的点,其实就是将原数组中的点移动到对应的目标数组中的对应点上,好比有一个矩形,原数组就是矩形四个顶点,然后目标数组就是操作一下四个顶点(就是上下左右移动一下),自己可以看看效果,一定会很惊艳吧(也可能惊吓),而参数中的srcIndex是指是从源数组中的第几个元素开始算起,dstIndex则是指从目标数组中的第几个元素开始算起,pointCount则是自己构造的数组中的点的个数啦(有个要求Must be [0..4]),同样数组中元素因为要组成point所以个数必须为偶数个,这就是这个方法的作用
      以上就是利用matrix做几何变换的方法,上面的不管canvas也好,matrix也罢,都是在二维层面上的几何变化,也不过是缩放、平移、拉伸之类的,如果想在三维空间上线做几何变换的话那就得用到Camera这个类了
  • camera类主要用于图形的3D变换,其实说白了也是旋转,但是是可以围绕x轴、y轴以及z轴的旋转,所以不单单是平面内的旋转了,二维空间的旋转其实就是围绕x轴的,camera的默认旋转中心是在坐标原点就是手机屏幕左上角的,如果不改变旋转中心的话,那么直接用camera进行旋转会总会出现意想不到的结果,所以一般为了便于想象也便于直观的观察,一般都会将旋转中心进行移动,好比移动至需要旋转的图片的中心,那么再做旋转就会直观很多,好比我们现在在(200,200)的位置绘制了一张图片(图片的左上角就在(200,200))了,我们想让其围绕自己的中心沿着y轴旋转45度,假设图片的中心是(centerX,centerY),然后如下一段代码:
            canvas.save();
            camera.save();
            camera.rotateY(45); // 旋转 Camera 的三维空间
            canvas.translate(centerX, centerY);//旋转之后把投影移动回来(将坐标原点移动至手机左上角)
            camera.applyToCanvas(canvas); // 把旋转投影到 Canvas
            canvas.translate(-centerX, -centerY); // 旋转之前把绘制内容移动到图片中心(其实是现在的坐标原点跑到了图片中心)
            camera.restore();
            canvas.drawBitmap(getBitmap(), 200, 200, paint);
            canvas.restore();

大家应该也发现了我们将旋转中心的代码写在了最后面,而将旋转中心再次移动至手机左上角写在了上面将camera的效果设置给canvas之前,这是因为canvas的几何变换中心是反着的,所以这里的顺序颠倒了,applyToCanvas则是将旋转投影到canvas画布上面,当然自己也可以让其围绕z轴或者x轴旋转,这个看个人的需求了

  以上就是本次关于canvas的裁切以及几何变换的全部内容,有问题欢迎批评指正,同时这也是自己第一次用Markdown编写文件,发现格式是比之前好很多。

你可能感兴趣的:(android小日子记录)