一、原理

转自:http://www.2cto.com/kf/201401/275838.html

Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation

Property Animation中最重要,最基础的一个类就是ValueAnimator了。Property Animation利用ValueAnimator来跟踪记录对象属性已经变化了多长时间及当前这个时间点的值。

而在ValueAnimator中,又封装了两个类:

1)TimeInterpolator,也称插值器,是来计算当前动画运动的一个跟时间有关系的比例因子。

2)TypeEvaluator,这个就是利用TimeInterpolator计算出来的因子来算出当前动画运行到的位置。

这样讲太抽象了,我们还是先用自然语言来描述一下整个动画的过程吧。

动画的原理,其实就是一帧帧的画面顺着时间顺序,在我们眼中形成视觉残留的效果。所以在动画中,时间的概念是很重要的,只有时间的变化,才能形成动画效果。

0)动画准备开始,我们在这里设置了一个动画的时长(duration),如果不设置的话,动画的时长就是300毫秒,每个画面显示的时间是10ms。同时也设置了某个属性值在这个时间段中变化的起始值start和结束值end,意思就是说,在duration时间中,属性值要从start 变化到 end。

1)动画开始了,过了 t 时间,ValueAnimator会根据 t / duration 算出一个时间消逝的比例因子(elapsed fraction),意思就是说,现在时间到 t了,我们假设总的时间的duration就是3t吧,那就是现在已经过了1/3时间了,那这个属性值也应该要变化到1/3了。

2)动画继续,现在到了2t了,那么现在动画时间已经过了2/3了,那么这个属性值是不是已经变化到2/3了呢。

3)现在到了3t了,动画结束了,属性值就已经从start变成end值了。

那么现在问题来了,如果都是这样算的话,那动画不就一直是很匀速的了吗?是的,如果用的是LinearInterpolator的话。

TimeInterpolator

TimeInterpolator就是用来改变我们这个动画速度的这样一个类了。为什么叫插值器呢?我理解就是,本来动画踩着时间点,一步一步走的挺好的,它硬生生在中间的插了些值进去,或者抽了一些值出去,让整条路变得不好走了,前面变然变上坡了,走起来就慢了,本来过去 t 时间之后,动画的画面也应该在1/3的位置了,但是路不好走,它就走不到1/3,而可能只走了1/4了,而后面是下坡,一激动,步伐就快了许多,又赶上去了,但是不管中间的路怎么变化,时间点一到,一定是刚刚好落在最终的位置上的。 Android中提供的Interpolator主要有九个: 1)AccelerateDecelerateInterpolator:先加速再减速。

2)AccelerateInterpolator:一直加速。

3)AnticipateInterpolator:先往后一下,再嗖的一声一往无前。

4)AnticipateOvershootInterpolator:先往后一下,再一直往前超过终点,再往回收一下。

5)BounceInterpolator:最后像个小球弹几下。

6)CycleInterpolator:重复几次,感觉就是环形进度条那种,具体我还没试过。

7)DecelerateInterpolator:一直减速。

8)LinearInterpolator:线性,这个就是我们上面讲到的很均匀的了。

9)OvershootInterpolator:到了终点之后,超过一点,再往回走。有个参数可以定义,超过的力度。

这些Interpolator都是实现了TimeInterpolator接口的类,它们只需要实现一个方法:getInterpolation (float input),将这个input根据自己的需求重新计算这个比例

第一步:当到了某时间t之后,ValueAnimator会算出某个比例 fraction = t / duration,而Interpolator会接收这个比例fraction,再调用其getInterpolation方法将这个比例因子重新计算一下,返回一个新的比例因子,比如LinearInterpolator实现的方法就是什么都不变,如下:

而 AccelerateDecelerateInterpolator 则会利用余弦函数的对称性变化计算这个比例因子,如下:

如上所述,通过第一步 Interpolator 的插值,我们会得到一个比例因子,接下来就是要用到我们的TypeEvaluator了。

TypeEvaluator

第二步:TypeEvaluator会接受第一步中算出来的比例因子,然后算出当前的属性的值,将其返回给ValuaAnimator,由ValueAnimator去设置对应属性的值。 比如,我自己写了一个BezierTypeEvaluator,根据时间的变化来让一个按钮沿着贝塞尔曲线移动,如下:

自定义TypeEvaluator,我们必须实现其evaluate方法,目的就是计算出目前的对象对应属性的值,而它会接收三个参数,一个是上文中通过interpolator算出的比例,还有我们在创建动画时设置的起始值和结束值。

ValueAnimator.AnimatorUpdateListener

既然我们已经算出了在 t 时刻,对象的某个属性的值,那么我们要把这个值重新设置到对象中,才能够起作用啊。所以ValueAnimator也提供了一个内部的Listener接口,其只有一个方法,就是获取TypeEvaluator计算出来的值,并设置给对应的属性,比如我们Demo中的代码:

我们在这里改变Button的X坐标和Y坐标,从而改变其具体的位置。至于validate,然后引起重新绘制的过程,对于这些基本的属性,ValueAnimator已经帮我们实现了。 下面,我们看看效果图,然后再总结一下ValueAnimator的实现机制。

下载

嗯,这一篇文章大概就是这样了,大家如果有兴趣了解Property Animation的应用的话,可以看一下Android动画学习Demo(2) 关于Property Animation的用法及总结

最后还是要提醒一下,Property Animation是3.0以后才支持的,如果大家想在3.0之前去应用这些属性的话,可以去下载jake wharton的nineoldandroids包,基本上都可以直接将方法套上,不过据我实验,还是有某些方法,比如 PropertyValuesHolder就会有些bug出现的。我把这个包也放在这里吧,

点击NineoldAndroids下载

二、自定义贝塞尔曲线View

转自:http://www.2cto.com/kf/201604/497130.html

Android 自定义View高级特效,神奇的贝塞尔曲线

效果图

效果图中我们实现了一个简单的随手指滑动的二阶贝塞尔曲线,还有一个复杂点的,穿越所有已知点的贝塞尔曲线。学会使用贝塞尔曲线后可以实现例如QQ红点滑动删除啦,360动态球啦,bulabulabula~

什么是贝塞尔曲线?

贝赛尔曲线(Bézier曲线)是电脑图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝塞尔曲面,其中贝塞尔三角是一种特殊的实例。贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau算法开发,以稳定数值的方法求出贝塞尔曲线。

读完上述贝塞尔曲线简介我还是一头雾水,来个示例呗。

示例

线性贝塞尔曲线

给定点P0、P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:

二次方贝塞尔曲线

二次方贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)追踪:

三次方贝塞尔曲线

P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;公式如下:

N次方贝塞尔曲线

身为三维生物超出三维我很方,这里只给示例图。想具体了解的同学请左转度娘。

就当没看过上面

Android在API=1的时候就提供了贝塞尔曲线的画法,只是隐藏在Path#quadTo()和Path#cubicTo()方法中,一个是二阶贝塞尔曲线,一个是三阶贝塞尔曲线。当然,如果你想自己写个方法,依照上面贝塞尔的表达式也是可以的。不过一般没有必要,因为Android已经在native层为我们封装好了二阶和三阶的函数。

从一个二阶贝塞尔开始

自定义一个BezierView

初始化各个参数,花3s扫一下即可。

在onDraw中画二阶贝塞尔

上面注释很清晰就不赘述了。示例中贝塞尔是可以跟着手指的滑动而变化,我一拍榴莲,肯定是复写了onTouchEvent()!

最后将我们自定义的BezierView添加到布局文件中。至此一个简单的二阶贝塞尔曲线就完成了。假设一下,在向下拉动的过程中,在曲线上增加一个“小超人”,360动态清理是不是就出来了呢?有兴趣的可以自己拓展下。

以一个三阶贝塞尔结束

天气预报曲线图示例

(图一)

(图二)

概述

要想得到上图的效果,需要二阶贝塞尔和三阶贝塞尔配合。具体表现为,第一段和最后一段曲线为二阶贝塞尔,中间N段都为三阶贝塞尔曲线。

思路

先根据相邻点(P1,P2, P3)计算出相邻点的中点(P4, P5),然后再计算相邻中点的中点(P6)。然后将(P4,P6, P5)组成的线段平移到经过P2的直线(P8,P2,P7)上。接着根据(P4,P6,P5,P2)的坐标计算出(P7,P8)的坐标。最后根据P7,P8等控制点画出三阶贝塞尔曲线。

点和线的解释

黑色点:要经过的点,例如温度 蓝色点:两个黑色点构成线段的中点 黄色点:两个蓝色点构成线段的中点 灰色点:贝塞尔曲线的控制点 红色线:黑色点的折线图 黑色线:黑色点的贝塞尔曲线,也是我们最终想要的效果

声明

为了方便讲解以及读者的理解。本篇以图一效果为例进行讲解。BezierView坐标都是根据屏幕动态生成的,想要图二的效果只需修改初始坐标,不用对代码做很大的修改即可实现。

那么,开始吧!

初始化参数

第一个函数获取屏幕宽高就不说了。紧接着初始化了初始点、中点、中点的中点、控制点。我们一个个的跟进。首先是初始点。

这里循环创建了一高一低五个点,并添加到List mPoints中。上文说道图一到图二只需修改这里的初始点即可。

这里算出中点集合以及中点的中点集合,小学数学题没什么好说的。唯一需要注意的是他们数量的差别。

大家需要注意下这个方法的计算过程。以图一(P2,P4, P6,P8)为例。现在P2、P4、P6的坐标是已知的。根据由于(P8, P2)线段由(P4, P6)线段平移而来,所以可得如下结论:P2 - P6 = P8 - P4 。即P8 = P2 - P6 + P4。其余同理。

画辅助点以及对比折线图

可以看到,在画贝塞尔曲线之前我们画了一系列的辅助点,还有和贝塞尔曲线作对比的折线图。效果如图一。辅助点的坐标全都得到了,基本的画画就比较简单了。有能力的可跳过下面这段,直接进入drawBezier(canvas)方法。基本的画画这里只贴代码,如有疑问可评论或者私信。

画贝塞尔曲线

注释太详细,都没什么好写的了。不过这里需要注意判断里面的条件,对起点和终点的判断一定要理解。要不然很可能会送你一个ArrayIndexOutOfBoundsException。

结束

贝塞尔曲线可以实现很多绚丽的效果,难的不是贝塞尔,而是good idea。

三、使用

转自:

研究一下贝塞尔曲线.

/**

* 三阶贝塞尔方程

*/

private class BeizerEvaluator implements TypeEvaluator{

private PointF point1;

private PointF point2;

private PointF pointF;

public BeizerEvaluator(PointF point1, PointF point2) {

this.point1 = point1;

this.point2 = point2;

}

@Override

public PointF evaluate(float time, PointF start, PointF end) {

float timeLeft = 1.0f - time;

pointF = new PointF();//结果

PointF point0 = start;//起点

PointF point3 = end;//终点

pointF.x = timeLeft * timeLeft * timeLeft * (point0.x)

+ 3 * timeLeft * timeLeft * time * (point1.x)

+ 3 * timeLeft * time * time * (point2.x)

+ time * time * time * (point3.x);

pointF.y = timeLeft * timeLeft * timeLeft * (point0.y)

+ 3 * timeLeft * timeLeft * time * (point1.y)

+ 3 * timeLeft * time * time * (point2.y)

+ time * time * time * (point3.y);

return pointF;

}

}

//初始化一个BezierEvaluator

BeizerEvaluator evaluator = new BeizerEvaluator(getPointF(1), getPointF(2));

ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF(rand.nextInt(getWidth()), 0), new PointF(rand.nextInt(getWidth()), mHeight - dHeight));//随机

animator.addUpdateListener(new BezierListenr(tag));

animator.setInterpolator(interpolators[rand.nextInt(3)]);

animator.setTarget(tag);

animator.setDuration(3000);

然后在需要更新的时候去Update设置imageVIew的路径:

private class BezierListenr implements ValueAnimator.AnimatorUpdateListener {

private View target;

public BezierListenr(View target) {

this.target = target;

}

@Override

public void onAnimationUpdate(ValueAnimator animation) {

PointF pointF = (PointF) animation.getAnimatedValue();

ViewHelper.setX(target, pointF.x);

ViewHelper.setY(target, pointF.y);

ViewHelper.setAlpha(target, 1 - animation.getAnimatedFraction());

}

}

GitHub:https://github.com/q422013/BezierFlower

java 贝塞尔曲线_贝塞尔曲线:原理、自定义贝塞尔曲线View、使用!!!相关推荐

  1. 光滑曲线_计算机图形学十:贝塞尔曲线与贝塞尔曲面

    贝塞尔曲线与贝塞尔曲面 1 贝塞尔曲线(Bézier Curves) 在进入具体原理讲解之前,首先看一下一条实际的贝塞尔曲线长什么样子 其中 为 控制点,蓝色所表示曲线正是非常著名的贝塞尔曲线了,可以 ...

  2. unity 控制点 贝塞尔曲线_在Unity中使用贝塞尔曲线(转)

    鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么MOMO迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是 ...

  3. matlibplot 一张图画多个曲线_热重法实验条件设定与曲线解析 第53部分 热重实验方案设计与曲线解析常见问题之热重仪选择中常见问题分析...

    在本系列内容第49部分至第52部分中分别介绍了在不同的应用领域中热重曲线解析的常见方法,自本部分内容开始将陆续介绍在热重实验方案设计和曲线解析中的常见问题,在本部分内容中将介绍在热重实验方案设计中选择 ...

  4. 光滑曲线_消防水泵-流量扬程性能曲线

    石峥嵘,消防资源网创始人,消防大讲堂主讲人,从业消防25年,参与近千项目设计施工,解答消防疑问数万条,极为资深的实践经验,结合深厚理论基础,汇集金典,奉献大家! 石峥嵘:消防水泵的性能应满足消防给水系 ...

  5. 平台型时间信号强度曲线_乳腺MR灌注时间-信号强度曲线表现及价值研究

    乳腺MR灌注时间-信号强度曲线表现及价值研究 目的探讨乳腺MRT2*WI首次通过灌注时间-信号强度曲线(TIC)表现及其在乳腺病变鉴别诊断中的价值.资料与方法对40例乳腺肿瘤患者行乳腺动态增强成像扫描 ...

  6. unity 控制点 贝塞尔曲线_在Unity中使用贝塞尔曲线

    前言 最近项目需要呈现各种轨道且随机性较强,在找了一天插件后打算自己实现平滑曲线,思路是策划对关卡中的轨道放置任意个节点,我通过代码将所有节点绘制成一条平滑的曲线,每两个节点之间通过三阶贝塞尔实现,最 ...

  7. 瑞雷波频散曲线_瑞雷波多模式频散曲线的能量计算研究

    许崇彩 王国富 闫伟 摘要:瑞雷波勘探技术具有快速.无损.衰减小.抗干扰能力强等优点,广泛应用于实际的工程勘探.在实际的工程勘探中提取的瑞雷波频散曲线只有一条,是正演中多个模式频散曲线的拟合,但是在正 ...

  8. python怎么画出圆润的曲线_利用python画出AUC曲线的实例

    以load_breast_cancer数据集为例,模型细节不重要,重点是画AUC的代码. 直接上代码: from sklearn.datasets import load_breast_cancer ...

  9. java链表实现_链表的原理及java实现

    一:单向链表基本介绍 链表是一种数据结构,和数组同级.比如,Java中我们使用的ArrayList,其实现原理是数组.而LinkedList的实现原理就是链表了.链表在进行循环遍历时效率不高,但是插入 ...

  10. java简单毕设_计算机毕业设计之自定义毕设课题需要如何确定工作量

    " 真正让导师满意的不是众多普通的功能,而是那一抹有创意的充满着生活气息的小功能." 自定义毕设课题,我觉得这是一种体现学生创新的一种很好的手段,但是有一些学生却因为脑海中没有积累 ...

最新文章

  1. Python 黑魔法 --- 描述器(descriptor)
  2. java中IOUtil.readLong_使用io/ioutil进行读写文件
  3. .NET Standard中使用TCPListener和TCPClient的高性能TCP客户端服务器
  4. 6000万条GitHub帖子告诉你:工作状态与表情符号强相关
  5. 获取笔记本序列号(SN码)命令
  6. 三菱伺服驱动器示例_三菱MRJB伺服放大器应用实例
  7. svn忽略指定文件或目录
  8. UAC遭禁用?UAC知识了解
  9. python发送短信接口_Python发短信接口
  10. 传统存储方式_制造核心系统传统存储升级全闪存F900或混闪V7000F实施方案在线探讨...
  11. cdr怎么抠图轮廓线条_CDR怎么抠图?CorelDRAW快速抠图方法
  12. 神经网络之父Hinton介绍及其论文介绍
  13. Xposed框架Xposed安装器|Xposed for Android 5.0/5.1/6.0|详细安装教程
  14. 枚举子集复杂度 O(n^3) 证明
  15. P4231 三步必杀
  16. 气质妈妈“特色”制胜巧心计 情系旗袍书画淘宝梦
  17. vue前端上传文件给后端的两种方式
  18. Apache文件解析漏洞
  19. 七、JVM调优实战——基本命令使用
  20. 液压水位控制阀原理液压水位控制阀厂家

热门文章

  1. Fortify漏洞之 Log Forging(日志伪造)
  2. 2014,成为更好程序员的7个方法
  3. ZJOI 2017 仙人掌
  4. Asiabrand访谈:农企怎样进行品牌价值评估?
  5. 「Serial No.」、UDID、IMEI、ICCID
  6. python认证国际标准_Python Matplotlib.colors.LogNorm用法及代码示例
  7. Ch3.3 对数几率回归
  8. 数学建模系列-评价模型(三)---聚类分析法
  9. 神雕侠侣2服务器维护,《神雕侠侣2》手游8月20日9:00-10:00停服维护公告
  10. Wincc计算机双网卡连接CPU,wincc通过两个网卡连接PLC?-工业支持中心-西门子中国...