欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于canvas画布的操作,看这一篇就足够了!

程序员文章站 2022-07-12 23:23:40
...

canvas

canvas是Android中自定义绘图中特别重要的一部分,如果你想画出想要的图形,canvas操作能帮你轻松许多。

canvas.save()和canvas.restore() 

这两个方法是最先应该了解的,save方法是将现在的画布状态保存,restore方法是将画布的状态退回到上个画布的状态,所以当我们画一些小的需要画布操作的图形的时候,先save再restore,然后在两个方法中间写上对画布的操作。

准备工作:

新建java文件MyView,定义画笔,做一些简单的初始化
private Paint mPaint;


    public MyView(Context context) {
        super(context);
        initSomeThing();
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initSomeThing();
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initSomeThing();
    }

private void initSomeThing() {
        mPaint = new Paint();
        initPaint(mPaint);
    }

    private void initPaint(Paint paint) {
        mPaint.setStrokeWidth(0);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.rgb(0x00, 0x00, 0x00));
    }

平移

先画一个圆,再按照步骤平移画布画一个一样的圆

canvas.drawCircle(100, 100, 100, mPaint);
canvas.save();
canvas.translate((float) 141.42135623731, (float) 141.42135623731);
mPaint.setColor(Color.rgb(0x91, 0xbe, 0xf0));
canvas.drawCircle(100, 100, 100, mPaint);
mPaint.setColor(Color.BLACK);
canvas.restore();

运行一下,效果如下:
关于canvas画布的操作,看这一篇就足够了!

同样是画两个一样的圆,结果却出现这种情况,原因是画布进行操作的时候,对应的坐标轴也跟着改变,其实我更加喜欢理解的是,我们操作的坐标轴。

canvas.translate这个方法里面的两个参数分别是向XY平移的距离,这个很简单就不赘述了

缩放

先做准备工作,把画布平移到平移到屏幕中间,画一个坐标轴,然后画一个方便比较的矩形
mPaint.setStrokeWidth(10);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);

        canvas.save();

        canvas.translate(getWidth() / 2, getHeight() / 2);
        canvas.drawLine(-550, 0, 550, 0, mPaint);
        canvas.drawLine(0, -800, 0, 800, mPaint);


        canvas.restore();
        mPaint.setStrokeWidth(0);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL);

//X中心轴是Y轴   Y中心轴是X轴

//        [-∞, -1)	        先根据缩放中心放大n倍,再根据中心轴进行翻转
//        -1	            根据缩放中心轴进行翻转
//        (-1, 0)	        先根据缩放中心缩小到n,再根据中心轴进行翻转
//        0	                不会显示,若sx为0,则宽度为0,不会显示,sy同理
//        (0, 1)	        根据缩放中心缩小到n
//        1	                没有变化
//        (1, +∞)	        根据缩放中心放大n倍


        mPaint.setStrokeWidth(5);
        mPaint.setStyle(Paint.Style.STROKE);

        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);


        RectF rectF = new RectF(0, -300, 300, 0);
        canvas.drawRect(rectF, mPaint);
        //缩放
        canvas.scale(0.5f, 0.5f);

        mPaint.setColor(Color.BLUE);
        canvas.drawRect(rectF, mPaint);
        mPaint.setColor(Color.BLACK);

        canvas.restore();

        mPaint.setStrokeWidth(0);
        mPaint.setStyle(Paint.Style.FILL);

运行效果如下:
关于canvas画布的操作,看这一篇就足够了!


可以看到蓝色的矩形就是XY两个方向都缩小一半的后的矩形
缩放这个方法里面的参数范围如下
        [-∞, -1)          先根据缩放中心放大n倍,再根据中心轴进行翻转
        -1               根据缩放中心轴进行翻转
       (-1, 0)          先根据缩放中心缩小到n,再根据中心轴进行翻转
        0                    不会显示,若sx为0,则宽度为0,不会显示,sy同理
        (0, 1)           根据缩放中心缩小到n
        1                    没有变化
        (1, +∞)          根据缩放中心放大n倍
上面也有写

缩放还有一个是四参的方法,后两个是旋转中心的点的坐标,个人感觉,这种不好记得操作其实可以分成两步,先把画布平移到旋转中心,然后在用上面的方法旋转效果是一样的,还好理解。不过我还是写了这个
 mPaint.setStrokeWidth(10);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.GREEN);

        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);

        canvas.scale(0.5f, 0.5f, 150, 0);
        RectF rectF = new RectF(0, -300, 300, 0);
        canvas.drawRect(rectF, mPaint);

        canvas.restore();

        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(0);
        mPaint.setStyle(Paint.Style.FILL);

运行效果如下:
关于canvas画布的操作,看这一篇就足够了!

绿色矩形就是新画出的矩形

旋转

 mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(15);
        mPaint.setColor(Color.GRAY);

        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);
        canvas.rotate(45);
        //区域是距离页面左上右下    所以不是之前说的对边两个点,X2要>X1 ,Y2要>Y1   0,0,400,-400   不符合就画不出矩形
        RectF rectF = new RectF(0, -300, 300, 0);
        canvas.drawRect(rectF , mPaint);

        canvas.restore();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(0);
        mPaint.setColor(Color.BLACK);

需要注意的是,旋转里面填的那个参数是旋转角度,不是旋转的弧度,是360度那个角度不是2π那个角度,
还有就是正方向是顺时针,填负数就是逆时针旋转。

运行效果如下:
关于canvas画布的操作,看这一篇就足够了!

还有一个三参的方法,和缩放一样,个人建议还是先平移再旋转吧,懒得写了

对了,缩放还有一个比较有意思的玩法,先新建一个类,直接贴代码

public class ViewScaleFun extends View {

    private Paint mPaint;

    public ViewScaleFun(Context context) {
        super(context);
        initPaint();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
    }

    public ViewScaleFun(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    public ViewScaleFun(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.save();

        canvas.translate(getWidth() / 2, getHeight() / 2);

        RectF rectF = new RectF(-500, -500, 500, 500);

        for (int i = 0; i < 30; i++) {
            canvas.scale(0.9f, 0.9f);
            canvas.drawRect(rectF, mPaint);
        }


        canvas.restore();

    }
}

运行结果如下:
关于canvas画布的操作,看这一篇就足够了!


哈哈  炫不酷炫酷   想不想学