使用surfaceview画贝塞尔曲线+旋转背景图片

来源:互联网 发布:知有儿童挑促织 编辑:程序博客网 时间:2024/06/05 15:40

        (转载请注明出处,尊重别人劳动成果,健康开源)

          最近想到画贝塞尔曲线,是因为f打算自己开发一款app,需要类似的功能,所以找demo,研究怎么实现。

        跟着我的思路往下走(f也是这样一步一步去画的)首先画出一条贝塞尔曲线,然后控制曲线旋转角度不断变化,视觉上就感觉是一个中心固定的几条贝塞尔曲线在旋转,也可以同时画出几条贝塞尔曲线,控制旋转来达到类似的效果。OK,第一步,我们需要画贝塞尔曲线。怎么画贝塞尔曲线,百度找了一些资料,大体相近,很多都是在ontouchevent里获取坐标来绘制的。简单的贝塞尔曲线绘制是用这些api 

                        mPath.moveTo(200, 200);//起点坐标
                        mPath.quadTo(150, 125, 200, 50);//控制点坐标和终点坐标
                        mCanvas.drawPath(mPath, paintQ);


        这样就能画出来一条最简单的。但是如果用view来画,指定的起点和终点距离较远时候,控制点指定的不合适,如我所给的坐

标,就会画成一个月牙,而不是一根线段,当然你可以给定合适的控制点来画成线段。但在Android中,画图时候推荐使用

surfaceview,用这个控件绘图更加高效,至于具体概念,f也没深入学习,感兴趣的同学可以自己去探索一下。大体了解就是

surfaceview相当于镂空在窗体window上的,而普通的view则覆盖在window上,平时看到的activity从底层到顶层依次为 window →

framelayout(decorview) →自己的布局 ,我就不解释了。使用sv绘图,一般需要得到sv的holder,然后给holder添加callback,在

callback的三个回调方法中绘图。(这种方法很熟悉啊,有木有?应该跟监听事件的设置时同一个道理,源码也差不多,this.callback

= callback...)而使用sv绘图,同样指定三个点 ,起点、控制点和终点,就能画出贝塞尔曲线,不用担心闭合。这样就可以用sv画一

条贝塞尔曲线了。那么问题来了,怎么样在同一个起点画四条呢?继续找demo,get,上面的代码写四遍,但是控制点和终点要设置。

然后就画出了四条。沿着前面的思路继续往下走,ok,到旋转了,与view相同,贝塞尔曲线也是被绘制在canvas上的,只不过sv的

canvas是需要用sv的holder来锁定的。我们画好贝塞尔曲线,给画布设置旋转角度,然后控制不停重画就可以实现了。


        在view中,我们可以使用invalidate()使界面重绘

        但是这个地方有个大坑,path.reset的这个api,f刚开始时候是加了这个方法的,但是后来鬼使神差地擦掉了,然后我的曲线图越转越慢,到几秒钟才转一下。。。找了半天也没找到解决方案,最后把最先的demo找到,一条一条改,竟然成了,原来是没调这个api,reset这个方法的意思就是清除path上所有的线和弧线,但对于充满的类型不起作用。

看完解释终于恍然大悟,其实f也有想到,越来越慢的原因是sv上的东西太多了,不擦掉的话,界面最终是一片白色,能显示的地儿就越来越小。使用了invalidate(),postinvalidate(),都不管用,好吧。自己挖的坑还得自己填。


写到这里,我的目标只完成了一半,看到题目的朋友肯定知道了,我们还要画一个旋转的图片,让贝塞尔曲线和图片一起旋转来达到目标。那么来看看怎么实现呢?

简单的逻辑就是把图片的中心定到贝塞尔曲线图的中心,然后设置不断旋转,不断旋转已经实现,那需要的就是把图片画到中心了!

之前陆续找的资料中也是使用canvas.drawbitmap()这个api来画图的,f试了很多个api,最终发现这个能实现要求

void android.graphics.Canvas.drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint)

bitmap 可以用bitmapfactory的四类方法生成,rectf可以指定我们图片的显示位置。rect这个属性是设置画bitmap的设置,可以为空。我的demo里,dst = new RectF(100, 100, 300, 300);正好能把图片的中心固定在(200,200)点。


运行后发现,图片和贝塞尔曲线旋转的角度一样!想了想,应该是我们给同一个canvas设置了两次matrix,后面的取代的前面的,所以没生效,最后找到canvas,save即可保存原先的matrix,他们旋转的角度就不同了。


整体代码就是这样,还需要注意在绘制以前要调用canvas.drawcolor(color.black)  才可以。基本就是这样,整体性能还可以通过脏矩形优化,具体还没研究,但是也有很多资料可以参考。

这篇就更新到这里,欢迎交流!

0 0
原创粉丝点击