关闭

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

标签: canvas平移旋转缩放
398人阅读 评论(1) 收藏 举报
分类:

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.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);

运行效果如下:



可以看到蓝色的矩形就是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);

运行效果如下:


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

旋转

 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π那个角度,
还有就是正方向是顺时针,填负数就是逆时针旋转。

运行效果如下:


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

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

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();

    }
}

运行结果如下:



哈哈  炫不酷炫酷   想不想学  







2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10637次
    • 积分:427
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:13条
    最新评论