自定义View学习笔记05—Canvas下操作画布

为什么要有画布操作?
疑问======>>>以默认的坐标系圆点为起点,画一条与X轴呈45°的射线,你会怎么操作?

以常规的数学思路来看,先使用三角函数计算出射线上任一点的坐标,然后调用drawLine即可。
有没有更加简单的方法?这个问题留在本笔记最后来解答。
现在进入操作画布的主题:

1、位移translate(float dx, float dy):

注意:这里的位移都是相对性的,基于当前位置的移动,不是每次基于屏幕左上角的(0,0)点移动。另外,移动是可叠加的。
这里我们暂且不管canvas的save()和restore()方法,这两个方法我们后面细讲。

private void drawTranslate(Canvas canvas){
    canvas.save();
    mPaint.setColor(Color.CYAN);
    canvas.drawCircle(100, 100, 60, mPaint);
    //位移(translate)是可以叠加的。
    canvas.translate(width/2, height/2);
    mPaint.setColor(Color.BLUE);
    canvas.drawCircle(0, 0, 60, mPaint);

    mPaint.setStyle(Paint.Style.STROKE);
    canvas.translate(width/2 - 100, height/2 - 100);
    mPaint.setColor(Color.GRAY);
    canvas.drawCircle(0, 0, 60, mPaint);

    canvas.restore();
    mPaint.setColor(Color.BLACK);
    canvas.drawCircle(500, 100, 60, mPaint);
    
    canvas.translate(150, 150);
    mPaint.setColor(Color.BLACK);
    canvas.drawCircle(0, 0, 75, mPaint);

    canvas.translate(150, 150);
    mPaint.setColor(Color.BLUE);
    canvas.drawCircle(0, 0, 75, mPaint);

    canvas.translate(200, -120);
    mPaint.setColor(Color.CYAN);
    canvas.drawCircle(0, 0, 75, mPaint);
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
位移

2、缩放:
scale(float sx, float sy):默认的缩放中心为坐标原点, 而缩放中心轴就是坐标轴;
scale(float sx, float sy, float px, float py):该方法比前一种多了两个参数,用来指定缩放中心的位置;
缩放比例(sx,sy)取值范围详解:
缩放比例(sx,sy)取值范围详解

private void drawScale(Canvas canvas){
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(10);
    canvas.translate(width/2, height/2);
    canvas.save();

    RectF rectF = new RectF(0, -220, 350, 0);
    canvas.drawRect(rectF, mPaint);

    //缩放是可以叠加的。
    canvas.scale(0.5f, 0.5f);
    mPaint.setColor(Color.YELLOW);
    canvas.drawRect(rectF, mPaint);

    canvas.scale(0.5f, 0.5f, 100, -100);
    mPaint.setColor(Color.BLUE);
    canvas.drawRect(rectF, mPaint);

    canvas.restore();
    canvas.save();
    mPaint.setColor(Color.GREEN);
    RectF rectF2 = new RectF(0, -200, 200, 0);
    canvas.drawRect(rectF2, mPaint);

    mPaint.setColor(Color.LTGRAY);
    canvas.scale(-0.5f, -0.5f);
    canvas.drawRect(rectF2, mPaint);

    canvas.restore();
    canvas.save();
    mPaint.setColor(Color.DKGRAY);
    canvas.scale(-0.5f, -0.5f, 100, 0);
    canvas.drawRect(rectF2, mPaint);
    canvas.restore();
    canvas.save();

    mPaint.setColor(Color.RED);
    mPaint.setStrokeWidth(8);
    RectF rectF3 = new RectF(0, -280, -280, 0);
    canvas.drawRect(rectF3, mPaint);
    for (int i = 0; i < 15; i++){//缩放叠加;
        canvas.scale(0.9f, -0.9f);
        canvas.drawRect(rectF3, mPaint);
    }
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
缩放
注意:和位移(translate)一样,缩放也是可以叠加的。

3、旋转:
rotate(float degrees):默认的旋转中心为坐标原点,Android中旋转时以顺时针方向为正。
rotate(float degrees, float px, float py):多处的两个参数px、py用于指定旋转中心。
同样的,旋转也是可以叠加的。

private void drawRotate(Canvas canvas){
    mPaint.setColor(Color.DKGRAY);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(4);
    //移动坐标中心至View的正中间。
    canvas.translate(width/2, height/2);
    mPaint.setColor(Color.parseColor("#93a5f4"));
    for (int i = 0; i <= 270; i += 3){
        if(i > 250){
            mPaint.setColor(Color.RED);
        }
        // 绘制圆形之间的连接线
        canvas.drawLine(0, 235, 0, 255, mPaint);
        canvas.rotate(3);
    }
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
旋转

4、错切:skew(float sx, float sy)
特殊类型的线性变换,用的很少,但有意想不到的效果。
错切也是可叠加的, 不过要特别注意,调用顺序不同绘制结果也会不同。

private void drawSkew(Canvas canvas){
    //错切也是可叠加的
    mPaint.setColor(Color.DKGRAY);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(4);
    canvas.translate(width/2, height/2);

    RectF rect = new RectF(0,0,100,100);// 矩形区域
    mPaint.setColor(Color.BLACK);// 绘制黑色矩形
    canvas.drawRect(rect, mPaint);
	//越接近于0,则错切之后的图形越接近于原图,数字越大,错切度越大
    canvas.skew(1f,2f);
    mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
    canvas.drawRect(rect,mPaint);
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
错切效果图

现在来回答本文开头的疑问:有没有更加简单的方法,以默认的坐标系圆点为起点画一条与X轴呈45°的射线。方法肯定是有的 ,那就是先画一条与X轴呈45°的射线,然后我们再用rotate方法旋转45°即可得到想要的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值