美文网首页
自定义View绘图篇(一)-Canvas

自定义View绘图篇(一)-Canvas

作者: Active_Loser | 来源:发表于2018-10-09 21:35 被阅读0次

    前言

    View的绘制相当于我们平时根据需求去画出各种图案,而Canvas 和 Paint 就像我们平时画画需要的画笔和画纸一样,也就是我们的 Paint(画笔)和 Canvas(画纸,通常称为画布),所以凡是跟要画的东西设置相关的,比如颜色、大小、宽度、样式、透明度等都是在 Paint 中设置的。而凡是跟要画的成品,比如想画一个矩形、圆形、文字、路径等都是通过 Canvas 操作的。

    一、基本方法

    Canvas我们可以看做一个坐标系,坐标系是左正下正,因此坐标中心就是画布左上角

    使用方法:初始化画笔,重写 View 的 onDraw 方法,在 onDraw 方法中通过 Canvas 来实现我们想要实现的效果,最后在布局中使用:

    public class CustomView extends View {
    
        private Paint paint;
    
        public CustomView(Context context) {
            this(context, null);
        }
    
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        private void init() {
            //初始化画笔
            paint = new Paint();
            //设置抗锯齿
            paint.setAntiAlias(true);
            //设置画笔宽度
            paint.setStrokeWidth(5);
            //设置画笔颜色
            paint.setColor(Color.RED);
            //设置画笔样式
            paint.setStyle(Paint.Style.STROKE);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
        }
    }
    

    1、画圆

    参数:

    • cx:圆心点的 X 轴坐标
    • cy:圆心点的 Y 轴坐标
    • radius:圆的半径
    • paint:画笔

    2、画矩形

    参数:

    • RectF:矩形辅助类

      常用构造函数RectF(float left, float top, float right, float bottom),即由四个点构造一个矩形

    • left、top、right、bottom顾名思义即距离左边、上边、右边、下边的距离。

    canvas.drawRect(new RectF(50,60,200,200),paint);
    

    3、画圆角矩形

    drawRoundRect (RectF rect, float rx, float ry, Paint paint) 
    drawRoundRect (float left, float top, float right, float bottom, float rx, float ry, Paint paint)
    

    参数:

    • rect:要画的矩形
    • rx:生成圆角的椭圆的 X 轴半径
    • ry:生成圆角的椭圆的 Y 轴半径

    4、画椭圆

    5、画圆弧

    drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
    drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, Paint paint)
    

    参数:

    • RectF oval:生成圆弧的矩形
    • float startAngle :圆弧开始的角度,以 X 轴正方向为 0 度 ,顺时针为正角度
    • float sweepAngle:圆弧持续的角度
    • boolean useCenter:是否显示弧的两边,true,显示,false 不显示,只有一条弧线
    paint.setColor(Color.RED);
    RectF rectF=new RectF(100, 400, 300, 600);
    canvas.drawRect(rectF, paint);
    paint.setColor(Color.BLUE);
    canvas.drawArc(rectF, 0, 90, false, paint);
    
    paint.setColor(Color.RED);
    RectF rectF1=new RectF(350, 400, 500, 600);
    canvas.drawRect(rectF1, paint);
    paint.setColor(Color.BLUE);
    canvas.drawArc(rectF1, 0, 90, true, paint);
    

    6、画直线

    参数:

    • float startX:开始点 X 坐标
    • float startY:开始点 Y 坐标
    • float stopX:结束点 X 坐标
    • float stopY:结束点 Y 坐标
    • pts:坐标数组,每四个为一组,不够则舍弃
    • offset:要跳过坐标点数组中几个值才开始画(必须是4的倍数)
    • count:至少为2,offset 之后数组的大小。

    7、画图像

    参数:

    • bitmap:要画在画布上的位图
    • matrix:构建的矩阵作用于将要画出的位图【后面整理】
    • src:可为 null,表示画整个位图,否则只花出位图的一块矩形区域图
    • dst:定义的一个矩形范围,位图会平移或缩放来将自身放入矩形内
    Rect src = new Rect(20, 20, 40, 40);//取bitmap上src区域的部分图像
    Rect dst = new Rect(100, 100, 200, 200);//填满矩形
    mPaint.setAntiAlias(true);
    mPaint.setColor(Color.RED);
       canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),src,dst,mPaint);
    

    8、画背景

    drawColor(int color, PorterDuff.Mode mode) ;
    drawRGB(int r, int g, int b);
    

    9、画点

    drawPoint(s)
    

    10、画文字

    绘制出文本的基本样式(粗细、大小、颜色、下划线等),可以查看Paint的一些属性

    11、画路径

    重点方法

    • moveTo(float x1,float y1):直线的开始点,即将直线路径的绘制点定在(x1,y1)的位置;
    • lineTo(float x2,float y2):直线的结束点,又是下一次绘制路径的开始点,lineTo() 可以一直调用
    • close():调用 close() 方法会自动将路径的首尾连接起来,形成闭环。

    11.1、基本用法

    Path path=new Path();
    path.moveTo(100, 200);
    path.lineTo(200, 200);
    path.lineTo(100, 400);
    path.lineTo(0, 400);
    path.close();
    canvas.drawPath(path, paint);
    

    11.2、图形路径

    创建不同的图形路径。


    参数:

    • dir:Direction 由2个取值(Path.Direction.CCW:创建逆时针方向的矩形路径;Path.Direction.CW:创建顺时针方向的矩形路径)
     private void init() {
            //初始化画笔
            paint = new Paint();
            paint.setTextSize(30);
            paint.setColor(Color.RED);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            String text = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            Path CCWPath = new Path();
            RectF rect = new RectF(100, 200, 350, 400);
            CCWPath.addRect(rect, Path.Direction.CCW);
            canvas.drawPath(CCWPath, paint);
            canvas.drawTextOnPath(text, CCWPath, 0, 0, paint);
    
            Path CWPath = new Path();
            RectF rect1 = new RectF(400, 200, 650, 400);
            CWPath.addRect(rect1, Path.Direction.CW);
            canvas.drawPath(CWPath, paint);
            canvas.drawTextOnPath(text, CWPath, 0, 0, paint);
        }
    

    ps:贝塞尔曲线后面具体整理

    二、图形裁切与变换

    常用方法

    • Canvas.save();保存状态
    • Canvas.restore();恢复保存状态

    1、图形裁切

    1.1、clipRect()

    canvas.clipRect(left, top, right, bottom);  
    canvas.drawBitmap(bitmap, x, y, paint);  
    

    示例:

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.city, null);
    canvas.save();
    canvas.clipRect(50, 150, 500, 400);
    canvas.drawBitmap(bitmap,0, 0, paint);
    canvas.restore();
    

    1.2、clipPath()

    canvas.clipPath(path);
    clipPath(Path path, Region.Op op);//不支持硬件加速
    

    参数:

    • op:
      DIFFRENCE是第一次不同于第二次的部分显示A-B
      REPLAC是显示第二次的B
      REVERSE_DIFFRENCE是第二次不同于第一次的部分显示
      INTERSECT是交集显示
      UNION是全部显示A+B
      XOR是补集(全集减去交集剩余部分)显示

    示例:

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.city, null);
    canvas.save();
    Path path=new Path();
    path.addCircle(300,300,100,Path.Direction.CCW);
    canvas.clipPath(path);
    canvas.drawBitmap(bitmap,0, 0, paint);
    canvas.restore();
    

    2、变换

    2.1、Canvas二维变换

    canvas内部还是由Matrix 实现

    注意:Canvas的几何变换是倒序的,即操作顺序与代码相反

    • 平移

      Canvas.translate(float dx, float dy)

      参数:

      • dx:横向位移距离
      • dy:纵行位移距离
    • 旋转

      Canvas.rotate(float degrees, float px, float py)

      参数:

      • degrees:旋转角度,方向是顺时针为正向
      • px:轴心x坐标
      • py:轴心y坐标
    • 缩放

      Canvas.scale(float sx, float sy, float px, float py)

      参数:

      • sx:横向缩放倍数
      • sy:纵向缩放倍数
      • px:缩放轴心x坐标
      • py:缩放轴心y坐标
    • 错切

      skew(float sx, float sy)

      参数:

      • sx:x 方向错切系数
      • sy: y 方向错切系数
      引自百度

    2.2、Matrix 二维变换

    前面说到canvas内部还是由Matrix 实现,因此Matrix 也可以实现上述的变换,所不同的是:Matrix可以自定义变换顺序,自定义变换规则

    逆序变换:preTranslate()、preRotate()、preScale()、preSkew()

    正序变换:postTranslate()、postRotate()、postScale()、postSkew()

    2.3、Camera三维变换

    Camera 的三维变换有三类:旋转、平移、移动相机,坐标系如下图,通过camera将物体进行投影,实现三维变换。

    常用操作:

    • 旋转:rotateX(deg) rotateY(deg) rotateZ(deg) rotate(x, y, z)
    • 移动:translate(float x, float y, float z)
    • 设置虚拟相机的位置:setLocation(x, y, z)---->移动相机可以实现图片的放大缩小

    注意:三维旋转是按照中心点旋转,为了方便操作,我们可以通过通过canvas的translate方法,将画布移动至原点进行操作,然后在移动回去,记得顺序是反的,因为canvas是逆序操作的。

    最后:简单实现下面简单的效果,github

    相关文章

      网友评论

          本文标题:自定义View绘图篇(一)-Canvas

          本文链接:https://www.haomeiwen.com/subject/rvzyaftx.html