canvas教程

模仿QQ运动item的界面(4)

字号+ 作者:H5之家 来源:H5之家 2016-09-29 17:03 我要评论( )

img4.PNG 接下来画柱状图,首先int lineWidth=(widthView-marginLineChart*2)/8;计算出每个点之间的间隔 img5.PNG if(mListStep.size()0){ for(int i=mListStep.size();i=1;i--){if(mListStep.get(i-1)!=0){//计算


img4.PNG


接下来画柱状图,首先int lineWidth=(widthView-marginLineChart*2)/8;计算出每个点之间的间隔


img5.PNG

if(mListStep.size()>0){ for(int i=mListStep.size();i>=1;i--){ if(mListStep.get(i-1)!=0){ //计算出起始点X和终点X的值 int startX=marginLineChart+lineWidth*i-radius/23; int endX=marginLineChart+lineWidth*i+radius/23; if(mListStep.get(i-1)>mStandardStop){ //达标 mTextPaint.setColor(mBesselCurveColor); //超出的部分 int exceed=mListStep.get(i-1)-mStandardStop; //算出柱体大小 float standard=(float) (mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop))); mRecf=new RectF(startX,marginBottomText-(standard>mCircleRectHeight?mCircleRectHeight:standard) ,endX,marginBottomText+mCircleRectHeight); canvas.drawRoundRect(mRecf,50,50,mTextPaint); }else{ //不达标 mTextPaint.setColor(besselColorText); //算出不达标柱体的大小 float noStandard=(float)(mCircleRectHeight*Double.valueOf(mListStep.get(i-1)/Double.valueOf(mStandardStop))); mRecf=new RectF(startX,marginBottomText,endX,marginBottomText+( noStandard>mCircleRectHeight?mCircleRectHeight:noStandard)); canvas.drawRoundRect(mRecf,50,50,mTextPaint); } } //画底下的日期 mTextPaint.setColor(besselColorText); mCalendar.set(Calendar.DAY_OF_MONTH,mCalendar.get(Calendar.DAY_OF_MONTH)-1); Rect rect =new Rect(); String number=stringTemplate(R.string.day,mCalendar.get(Calendar.DAY_OF_MONTH)+""); mTextPaint.getTextBounds(number,0,number.length(),rect); canvas.drawText(number,(marginLineChart+lineWidth*i)-(rect.right-rect.left)/2,marginBottomText+70,mTextPaint); } }

mStandardStop是达标的数据,当数据小于mStandardStop就是不达标,所以柱状图就要画在虚线的下面,mCircleRectHeight是柱状图一半的高
float standard=(float)(mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop)));这句代码是计算出下面圆柱体的具体大小,noStandard>mCircleRectHeight?mCircleRectHeight:noStandard当,但柱状图大于mCircleRectHeight时就用mCircleRectHeight不然就根据计算的数值来。当数据大于mStandardStop时,
int exceed=mListStep.get(i-1)-mStandardStop;float standard=(float)(mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop)));exceed是计算出超出的部分,再拿超出的部分算出具体的大小,剩下的和小于的一样,当standard大于最大的mCircleRectHeight是就用mCircleRectHeight否则就用standard。底下日期是用Calendar得到前7天的日期再循环的画上去,思路和上面一样不再赘述。此时效果如下:


img6.PNG

接下来是画波浪,画波浪是用了贝塞尔曲线的方法画的,如果不懂贝塞尔曲线请参考这里写链接内容,这也是我学贝塞尔曲线参考的内容。首先我们又把canvas恢复到原点canvas.restore();再用float mWavyHeight=heightView*((float)4/5)+50; canvas.translate(0,mWavyHeight);移动这个位置,是为了适配。

WavyLinePath.reset(); WavyLinePath.moveTo(-mWaveLength+ mOffset,0); int wHeight=radius/5; for(int i=0;i<mWaveCount;i++){ WavyLinePath.quadTo((-mWaveLength*3/4)+(i*mWaveLength)+mOffset,wHeight,(-mWaveLength/2)+(i*mWaveLength)+mOffset,0); WavyLinePath.quadTo((-mWaveLength/4)+(i * mWaveLength)+mOffset,-wHeight,i*mWaveLength+mOffset,0); } WavyLinePath.lineTo(widthView,heightView-mWavyHeight); WavyLinePath.lineTo(0,heightView-mWavyHeight); WavyLinePath.close(); canvas.drawPath(WavyLinePath,WavylinesPaint);

WavyLinePath.quadTo就是贝塞尔曲线调的方法,for循环几次使之形成波浪图形,记得一样要WavyLinePath.lineTo().不让会出现底下有些地方会画不到。原理是向上定一个控制点有向下定一个控制点使之形成一个sin函数图形。具体请学贝塞尔曲线。此时效果图:


img7.PNG

最后就是画底下的矩形和头像和文字了。最值得讲的是头像我一开始的设想的传Url的,不过这样子又要做网络方面的代码工作,这样子会破怀类的功能单一性原则,所以最后我实在外部传一个位图,在位图进行处理使其圆角。剩下的只是画文字而已,上面已经讲够多了,就不在讲了。
对了,最后还有一个刚开始的动画效果。

public void startAnimator(){ ValueAnimator mCircleAminator=ValueAnimator.ofFloat(0f,300f); mCircleAminator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCircleNum=(float)animation.getAnimatedValue(); postInvalidate(); } }); ValueAnimator mCenterText=ValueAnimator.ofInt(0,allStop); mCenterText.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCenterNum=(int)animation.getAnimatedValue(); postInvalidate(); } }); ValueAnimator mWavyAnimator = ValueAnimator.ofInt(0, mWaveLength); mWavyAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mOffset = (int) animation.getAnimatedValue(); postInvalidate(); } }); animSet.setDuration(2000); animSet.playTogether(mCircleAminator,mCenterText,mWavyAnimator); animSet.start(); } //字符串拼接 public String stringTemplate(int template,String content){ return String.format(getContext().getResources().getString(template),content); }

其实也简单通过设置ValueAnimator让它在规定的时间内产生数值的变化,再调用postInvalidate().对View的界面进行刷新即可实现动画效果。

最后给源码好好研究吧源码只有好好看源码才能学到更多东西。

假如我的文章对你有帮助请点个喜欢吧。

 

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

相关文章
  • canvas中的三角运动(2):旋转动画

    canvas中的三角运动(2):旋转动画

    2016-08-21 18:01

  • html5 canvas炫彩运动小球动画特效

    html5 canvas炫彩运动小球动画特效

    2016-06-20 17:00

  • canvas学习之圆周运动,canvas学习圆周

    canvas学习之圆周运动,canvas学习圆周

    2016-06-11 18:00

  • python开发之thread实现布朗运动的方法

    python开发之thread实现布朗运动的方法

    2015-11-13 16:56

网友点评