最近研究了一个特效动画: 一个水波纹动画的动态效果。有兴趣的童鞋们可以去了解一下。定义组件大家都非常熟悉。不可以参考如不熟悉童鞋可以去参考:http://blog.csdn.net/androidstarjack/article/details/42567301
水波纹动画展示效果:
话不多说,先看代码:
加速后和起风时的效果:
MainActivity.java代码如下:
贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等。在Flash4中还没有完整的曲线工具,而在Flash5里面已经提供出贝塞尔曲线工具。
贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau演算法开发,以稳定数值的方法求出贝兹曲线。
给定点P0、P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出:
且其等同于线性插值。
二次方贝兹曲线的路径由给定点P0、P1、P2的函数B(t)追踪:
TrueType字型就运用了以贝兹样条组成的二次贝兹曲线。
P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝兹曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;这两个点只是在那里提供方向资讯。P0和P1之间的间距,决定了曲线在转而趋进P3之前,走向P2方向的“长度有多长”。
曲线的参数形式为:
现代的成象系统,如PostScript、Asymptote和Metafont,运用了以贝兹样条组成的三次贝兹曲线,用来描绘曲线轮廓。
阶贝兹曲线可如下推断。给定点P0、P1、…、Pn,其贝兹曲线即:
如上公式可如下递归表达:
用表示由点P0、P1、…、Pn所决定的贝兹曲线。
用平常话来说,阶的贝兹曲线,即双阶贝兹曲线之间的插值。
贝塞尔曲线跟PS里的钢笔的意思大概差不多,不过贝塞尔曲线没有选取的功能。在这里,要切记,不要和轮廓工具弄混,前者是通过调节点调节形状,后者是调节形状轮廓的粗细以及样式。
补充几点:
Region,中文意思即区域的意思,它表示的是canvas图层上的某一块封闭的区域。
/**构造方法*/
public Region() //创建一个空的区域
public Region(Region region) //拷贝一个region的范围
public Region(Rect r) //创建一个矩形的区域
public Region(int left, int top, int right, int bottom) //创建一个矩形的区域
/**一系列set方法,这些set方法,和上面构造方法形式差不多*/
public void setEmpty() {
public boolean set(Region region)
public boolean set(Rect r)
public boolean set(int left, int top, int right, int bottom)
/*往一个Region中添加一个Path只有这种方法,参数clip代表这个整个Region的区域,在在里面裁剪出path范围的区域*/
public boolean setPath(Path path, Region clip) //用指定的Path和裁剪范围构建一个区域
/**几个判断方法*/
public native boolean isEmpty();//判断该区域是否为空
public native boolean isRect(); //是否是一个矩阵
public native boolean isComplex();//是否是多个矩阵组合
/**一系列的getBound方法,返回一个Region的边界*/
public Rect getBounds()
public boolean getBounds(Rect r)
public Path getBoundaryPath()
public boolean getBoundaryPath(Path path)
/**一系列的判断是否包含某点 和是否相交*/
public native boolean contains(int x, int y);//是否包含某点
public boolean quickContains(Rect r) //是否包含某矩阵
public native boolean quickContains(int left, int top, int right,
int bottom) //是否没有包含某矩阵
public boolean quickReject(Rect r) //是否没和该矩阵相交
public native boolean quickReject(int left, int top, int right, int bottom); //是否没和该矩阵相交
public native boolean quickReject(Region rgn); //是否没和该矩阵相交
/**几个平移变换的方法*/
public void translate(int dx, int dy)
public native void translate(int dx, int dy, Region dst);
public void scale(float scale) //hide
public native void scale(float scale, Region dst);//hide
/**一系列组合的方法*/
public final boolean union(Rect r)
public boolean op(Rect r, Op op) {
public boolean op(int left, int top, int right, int bottom, Op op)
public boolean op(Region region, Op op)
public boolean op(Rect rect, Region region, Op op)
上面几乎是Region的所有API,很好理解,主要说明一下最后的一组关于Region组合的方式。组合即当前的Region和另外的一个Region组合,可以用不同的Op方式来进行组合。
Op是一个枚举,定义在Region类中。
```
public enum Op {
DIFFERENCE(0), //最终区域为region1 与 region2不同的区域
INTERSECT(1), // 最终区域为region1 与 region2相交的区域
UNION(2), //最终区域为region1 与 region2组合一起的区域
XOR(3), //最终区域为region1 与 region2相交之外的区域
REVERSE_DIFFERENCE(4), //最终区域为region2 与 region1不同的区域
REPLACE(5); //最终区域为为region2的区域
}
```
ApiDemo中已经提供了一个关于组合的例子,在最后面给出。
Android还提供了一个RegionIterator来对Region中的所有矩阵进行迭代,可以使用该类,获得某个Region的所有矩阵。
了解了这些,你会体验到Region的好处。
布局,xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:appWave="http://schemas.android.com/apk/res/com.example.administrator.waterwavedemo"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#7CC1E0"
tools:context="com.example.administrator.waterwavedemo.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="@dimen/dp60"
android:layout_height="@dimen/dp60"
android:background="@drawable/yang"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_gravity="right"
android:id="@+id/imageView" />
<com.example.administrator.waterwavedemo.view.MyWaterWaveView
android:layout_width="match_parent"
android:id="@+id/myWaterWaveView"
android:layout_height="500dp"
appWave:rise="false"
appWave:originY="500px"
appWave:waveLegth="500px"
appWave:waveHeight="200px"
appWave:diration="3000"
appWave:waveView_boatBitmap="@drawable/chuan"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true" />
RelativeLayout>
<LinearLayout
android:layout_height="@dimen/dp80"
android:layout_gravity="bottom"
android:gravity="center"
android:layout_width="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_increave_rice"
android:text="加速"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_del_rice"
android:text="减速"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_add_wind"
android:text="起风"/>
LinearLayout>
FrameLayout>
项目连接 地址:
https://github.com/androidstarjack/WaterWaveDemo
如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
微信公众号:终端研发部
(欢迎关注学习和交流)