canvas教程

Android自定义控件水波加速球(2)

字号+ 作者:H5之家 来源:H5之家 2017-04-26 17:00 我要评论( )

构造方法中实例化出了一个画笔对象,颜色为绿色,抗锯齿。在onDraw()方法中添加了两个画直线的方法,我们要对每个点都要绘制所以使用了循环。 哎呀,这不是咱们想看到的效果呀,这是因为坐标的原点依旧在View的左上

构造方法中实例化出了一个画笔对象,颜色为绿色,抗锯齿。在onDraw()方法中添加了两个画直线的方法,我们要对每个点都要绘制所以使用了循环。

itdadao


哎呀,这不是咱们想看到的效果呀,这是因为坐标的原点依旧在View的左上角,振幅小,都往下方画直线就覆盖了整个View,接下来我们把坐标系往下放移动len/2的距离,再去绘制:

@Override protected void onDraw(Canvas canvas) { // y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相; // 将周期定为view总宽度 float mCycleFactorW = (float) (2 * Math.PI / len); // 得到第一条波的y值 for (int i = 0; i < len; i++) { firstWaterLine[i] = (float) (10 * Math .sin(mCycleFactorW * i)); } // 得到第二条波的y值 for (int i = 0; i < len; i++) { secondWaterLine[i] = (float) (15 * Math.sin(mCycleFactorW * i + 10)); } //保存原来的内容 canvas.save(); canvas.translate(0,len/2); //第一条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, firstWaterLine[i], i, len, waterPaint); } //第二条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, secondWaterLine[i], i, len, waterPaint); } //恢复到原来的状态(会自动结合绘制的内容) canvas.restore();; }

我们需要先保存画布的状态,再去移动坐标系,之后在恢复合并。

itdadao


现在是我们想看到的样子了,但是还有一点,我们希望他是一个圆形的,这时候就需要另外一个功能,cavans的剪切功能

@Override protected void onDraw(Canvas canvas) { // y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相; // 将周期定为view总宽度 float mCycleFactorW = (float) (2 * Math.PI / len); // 得到第一条波的y值 for (int i = 0; i < len; i++) { firstWaterLine[i] = (float) (10 * Math .sin(mCycleFactorW * i)); } // 得到第二条波的y值 for (int i = 0; i < len; i++) { secondWaterLine[i] = (float) (15 * Math.sin(mCycleFactorW * i + 10)); } // 裁剪成圆形区域 Path path = new Path(); path.reset(); float clipRadius=len/2; //添加圆形路径 //Path.Direction.CCW逆时针 //Path.Direction.CW顺时针 path.addCircle(len / 2, len / 2, clipRadius, Path.Direction.CCW); // (剪裁路径)裁剪成圆形区域 //(REPLACE用当前要剪切的区域代替画布中的内容的区域) canvas.clipPath(path, android.graphics.Region.Op.REPLACE); canvas.save(); canvas.translate(0,len/2); //第一条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, firstWaterLine[i], i, len, waterPaint); } //第二条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, secondWaterLine[i], i, len, waterPaint); } canvas.restore();; }

在我们要移动画布之前,将View剪切成了圆形
点击了解
Region.Op

itdadao


在布局中我去除了,控件的背景,效果如图所示,接下来就是去控制让他动起来了,水平方向移动也就是每次初相都不相同,开启时间任务,让它的初相值不断变化(从右往左移动就加上一个数)

@Override protected void onDraw(Canvas canvas) { // y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相; // 将周期定为view总宽度 float mCycleFactorW = (float) (2 * Math.PI / len); // 得到第一条波的y值 for (int i = 0; i < len; i++) { //添加一个可变的初相值 firstWaterLine[i] = (float) (10 * Math .sin(mCycleFactorW * i+move)); } // 得到第二条波的y值 for (int i = 0; i < len; i++) { //添加一个可变的初相值 secondWaterLine[i] = (float) (15 * Math.sin(mCycleFactorW * i + move+10)); } // 裁剪成圆形区域 Path path = new Path(); path.reset(); float clipRadius=len/2; //添加圆形路径 //Path.Direction.CCW逆时针 //Path.Direction.CW顺时针 path.addCircle(len / 2, len / 2, clipRadius, Path.Direction.CCW); // (剪裁路径)裁剪成圆形区域 //(REPLACE用当前要剪切的区域代替画布中的内容的区域) canvas.clipPath(path, android.graphics.Region.Op.REPLACE); canvas.save(); canvas.translate(0,len/2); //第一条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, firstWaterLine[i], i, len, waterPaint); } //第二条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, secondWaterLine[i], i, len, waterPaint); } canvas.restore();; }

在onDraw()的方法中,获取坐标Y值的时候,添加一条可变的全局变量,动态改变初相值。开启时间任务:

public void moveWaterLine() { final Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { //不断改变初相 move += 1; //重新绘制(子线程中调用) postInvalidate(); } }, 500, 200); }

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • android自定义组件(手机加速球+水面波动效果)

    android自定义组件(手机加速球+水面波动效果)

    2017-04-26 12:03

  • Android多屏幕适配

    Android多屏幕适配

    2017-04-25 11:02

  • Android图形图像之自定义控件属性(demo:刮刮乐与打

    Android图形图像之自定义控件属性(demo:刮刮乐与打

    2017-04-24 13:01

  • Class:android总类/android覆盖物类

    Class:android总类/android覆盖物类

    2017-04-20 08:00

网友点评
.