源码学习—— Demo解析Canvas绘图

 原文链接:http://blog.csdn.net/qibin0506/article/details/48621855

一:复习原作者提到的基础知识:

1、Handler

子线程处理完耗时操作后,通过Message传递数据给Handler,Handler把消息放在主线程队列中,配合主线程更新UI。

Handler有两个作用:  

(1):定时执行Message和Runnalbe 对象 

(2):让一个动作,在不同的线程中执行。 

Tip:

message是放置信息,可以传递一些参数,

Handler获取这些信息并将判度如何处理,

Runnable则是直接给出处理的方法。


2、绘制扇形

在Canvas上绘制扇形的函数:

drawArc( RectF oval, float startAngle, float sweepAngle, boolean useCenter,  Paint paint)//画弧,

参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,

参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的扇形,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象

建议看这下篇 http://blog.csdn.net/rhljiayou/article/details/7212620


3、Shader类

用于渲染图像以及几何形状,包括:

BitmapShader主要用来渲染图像

LinearGradient 用来进行梯度渲染

RadialGradient 用来进行环形渲染

SweepGradient 用来进行梯度渲染

ComposeShader则是一个 混合渲染,可以和其它几个子类组合起来使用。 

使用方法:

先构建Shader对象,然后通过Paint的setShader方法设置渲染对象,然后设置渲染对象,然后再绘制时使用这个Paint对象即可。

建议:http://byandby.iteye.com/blog/831011


4、旋转Canvas类

流程:保存现场——>操作——>恢复现场

  canvas.save(); 
  旋转
 canvas.restore();


二:Canvas基础例子、

自定义一个View,在onDraw中绘制简单的形状

public class BasicUsageView extends View {
    Paint paint1 = new Paint();
    Paint paint2 = new Paint();
    Paint paint3 = new Paint();
    Paint paint4 = new Paint();
    public BasicUsageView(Context context){
        super(context);
    }
    public BasicUsageView(Context context,Attributes attributes){
        super(context,null);
    }

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

        initPaint();
        drawLine(canvas);
        drawRect(canvas);
        drawCircle(canvas);
        drawText(canvas);
        drawImg(canvas);
        drawOval(canvas);
        drawPathLine(canvas);
        drawArc(canvas);
    }

    private void drawArc(Canvas canvas){
        //350, 900  20 250
        RectF oval = new RectF(400,500,600,800);
        canvas.drawArc(oval,0,20,true,paint1);

        canvas.drawArc(oval,60,100,false,paint3);

        Shader mShader = new LinearGradient(0,0,100,100, new int[]{Color.BLUE,Color.GREEN,Color.YELLOW,Color.RED},
        null,Shader.TileMode.REPEAT);
        paint1.setShader(mShader);

        canvas.drawArc(oval,110,160,true,paint1);
    }

    private void drawPathLine(Canvas canvas){
      Path path = new Path();
        path.moveTo(30, 900);
        path.lineTo(50, 700);
        path.lineTo(80, 900);
//        path.lineTo(30,900);
        path.moveTo(30,900);
        path.lineTo(100, 900);
        path.lineTo(75, 700);
        path.lineTo(80, 900);
        path.moveTo(100, 900);
        path.lineTo(150, 400);
        path.lineTo(180, 700);
        path.lineTo(220, 370);
        path.lineTo(300, 810);
        path.lineTo(350, 900);
        path.lineTo(100,900);
        path.close();
        canvas.drawPath(path,paint4);
    }
    private void drawOval(Canvas canvas){
        RectF f = new RectF(300,300,600,500);
        canvas.drawOval(f,paint2);
    }
    private void drawImg(Canvas canvas){
        canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img),20,350,paint1);
    }
    private void drawText(Canvas canvas){
        canvas.drawText("这是字符串",10,260,paint4);
    }
    private void drawCircle(Canvas canvas){
        //150,100
        canvas.drawCircle(150,100,50,paint3);

        canvas.drawCircle(150,100,30,paint4);
    }
    private void drawRect(Canvas canvas){
        canvas.drawRect(30, 30, 290, 190, paint1);

        RectF rectF = new RectF(50,50,260,150);
        canvas.drawRoundRect(rectF,20,20,paint2);
    }
    private void drawLine(Canvas canvas){
        canvas.drawLine(10,10,310,10,paint1);
        canvas.drawLine(10,215,310,215,paint2);
        canvas.drawLine(10,10,10,215,paint3);
        canvas.drawLine(310,10,310,215,paint4);
    }

    private void initPaint(){
        paint1.setAntiAlias(true);//抗锯齿效果
        paint1.setColor(Color.parseColor("#C0FF3E"));//画笔颜色
        paint1.setAlpha(79);
        paint1.setStyle(Paint.Style.FILL);//实心的
        paint1.setStrokeWidth(12);

        paint2.setColor(Color.CYAN);
        paint2.setTextSize(50);
        paint2.setStyle(Paint.Style.STROKE);//空心的
        paint2.setStrokeWidth(5);

        paint3.setColor(Color.RED);
        paint3.setTextSize(100);
        paint3.setStyle(Paint.Style.STROKE);//空心的
        paint3.setStrokeWidth(2);
        paint3.setAntiAlias(false);

        paint4.setColor(Color.DKGRAY);
        paint4.setTextSize(40);
        paint4.setStyle(Paint.Style.STROKE);//空心的
        paint4.setStrokeWidth(3);
        paint4.setAntiAlias(true);
        paint4.setDither(true);//设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
    }
}

效果图:




运用到的知识点有:画线、画圆、画矩形、Path路径绘制、画图、椭圆……都很简单

二:Demo的实现、

实现思路:

重写View:

在构造函数中初始化Paint画笔;

在onMeasure方法中测量屏幕宽度,设置矩形面积范围、为paint设置Shader样式;

在onDraw中绘制,原理也就是不断地改变扇形的角度,从0一直增加到360度再归零。为了显示更加逼真,就将Canvas也跟着扇形的角度旋转。在对画布进行操作时,记住要保存现场和恢复现场;

效果实现上,点击自定义View,对Handler发送一个小小,让它一直更新扇形的角度,调用直接在线程中调用postInvalidate()方法刷新View.

public class MyCanvasView extends View {
	
	private static final int MSG_RUN = 1;
	
	private Paint mCirclePaint;
	private Paint mArcPaint;
	private Paint mLinePaint;
	
	private RectF mRectF;
	
	private int mSweepAngle;
	
	public MyCanvasView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		
		mCirclePaint.setColor(Color.BLACK);
		mCirclePaint.setStyle(Style.STROKE);
		mCirclePaint.setStrokeWidth(1.f);
		
		mArcPaint.setColor(Color.GRAY);
		mArcPaint.setStyle(Style.FILL);
		
		mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mLinePaint.setColor(Color.BLACK);
		mLinePaint.setStrokeWidth(1.f);
		
		mRectF = new RectF();

		Log.i("hq"," 构造函数中 mSweepAngle:"+mSweepAngle);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
		int size = getMeasuredWidth();
		setMeasuredDimension(size, size);
		mRectF.set(0, 0, getMeasuredWidth(), getMeasuredHeight());

		mArcPaint.setShader(new SweepGradient(size/2, size/2, Color.GRAY, Color.BLACK));
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		int centerX = getMeasuredWidth() / 2;
		int centerY = getMeasuredHeight() / 2;
		
		canvas.save();
		canvas.rotate(mSweepAngle, centerX, centerY);
		canvas.drawArc(mRectF, 0, mSweepAngle, true, mArcPaint);
		canvas.restore();
		Log.i("hq", "mSweepAngle:" + mSweepAngle);

		canvas.drawLine(0, centerY, getMeasuredWidth(), centerY, mLinePaint);
		canvas.drawLine(centerX, 0, centerX, getMeasuredHeight(), mLinePaint);
		
		canvas.drawCircle(centerX, centerY, centerX / 2, mCirclePaint);
		canvas.drawCircle(centerX, centerY, centerX, mCirclePaint);
	}
	
	public void start() {
		mHandler.sendEmptyMessage(MSG_RUN);
	}
	
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			if(msg.what == MSG_RUN) {
				mSweepAngle+=2;
				if(mSweepAngle > 360) mSweepAngle = 0;
				postInvalidate();
				sendEmptyMessage(MSG_RUN);
			}
		}
	};
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Canvas是HTML5新增的一个用于绘制图形的标签,可以通过JavaScript来控制Canvas进行图形的绘制。在进行Canvas绘制时,可以通过调整画布的位置、大小和旋转角度等属性,来控制绘制出来的图形的位置和形态。 下面我们就来介绍一下Canvas画布的移动、缩放和旋转: 1. 画布移动 画布移动可以通过Canvas提供的translate方法来实现。translate方法接收两个参数,分别表示x轴和y轴方向上的偏移量。偏移量为正值表示向右或向下移动,为负值表示向左或向上移动。 例如,我们可以通过下面的代码将画布向右移动50个像素,向下移动100个像素: ``` context.translate(50, 100); ``` 2. 画布缩放 画布缩放可以通过Canvas提供的scale方法来实现。scale方法接收两个参数,分别表示x轴和y轴方向上的缩放比例。缩放比例为大于1的值表示放大,小于1的值表示缩小。 例如,我们可以通过下面的代码将画布在x轴和y轴方向上都放大2倍: ``` context.scale(2, 2); ``` 3. 画布旋转 画布旋转可以通过Canvas提供的rotate方法来实现。rotate方法接收一个参数,表示旋转的角度,单位为弧度。 例如,我们可以通过下面的代码将画布旋转45度: ``` context.rotate(Math.PI / 4); ``` 需要注意的是,Canvas绘图的坐标系原点默认在画布的左上角,而移动、缩放和旋转操作都是相对于原点进行的。因此,在进行这些操作时,需要先将画布的原点移动到需要的位置,再进行操作。例如,如果需要将画布向右移动50个像素,需要先将原点移动到(50,0)的位置,再进行移动操作: ``` context.translate(50, 0); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值