关于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.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();
}
}
运行结果如下:
哈哈 炫不酷炫酷 想不想学