为什么要有画布操作?
疑问======>>>以默认的坐标系圆点为起点,画一条与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)取值范围详解:
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°即可得到想要的结果。