Android - Animation 贝塞尔曲线之美
2015-08-20 14:54
459 查看
概述
贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau演算法开发,以稳定数值的方法求出贝兹曲线。在计算机图形学中贝赛尔曲线的运用也很广泛,Photoshop中的钢笔效果,Flash5的贝塞尔曲线工具,在软件GUI开发中一般也会提供对应的方法来实现贝赛尔曲线。
线性公式
给定点P0、P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出:B(t) = P0 + (P1 - P0) * t = (1 - t) * P0 + t * P1, t ∈ [0, 1]
且其等同于线性插值。
二次方公式
二次方贝兹曲线的路径由给定点P0、P1、P2的函数B(t)追踪:B(t) = (1 - t)^2 * P0 + 2t * (1 - t) * P1 + t^2 * P2, t ∈ [0,1]
TrueType字型就运用了以贝兹样条组成的二次贝兹曲线。
百度百科 详细资料
Android上实现贝赛尔曲线
在Android实现贝赛尔曲线,要借助android.graphics.Path,其中绘制贝赛尔曲线的方法在Api v1就已经提供了,下面来认识一下吧。初识Path类
1 2 3 4 5 | Path.moveTo(float x, float y) // Path的初始点 Path.lineTo(float x, float y) // 线性公式的贝赛尔曲线, 其实就是直线 Path.quadTo(float x1, float y1, float x2, float y2) // 二次方公式的贝赛尔曲线 Path.cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) // 三次方公式的贝赛尔曲线 ... |
绘制贝赛尔曲线
![](http://gavinliu.cn/images/2015.03.30%20-%20Android-Animation-%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF%E4%B9%8B%E7%BE%8E1.png)
BezierView
1 2 3 4 56 | @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPath.moveTo(100, 100); mPath.cubicTo(800, 100, 100, 800, 800, 800); // 一共四个点,(100, 100)和(800, 800)分别为起点和终点,(800, 100)和(100, 800)为操作点 canvas.drawPath(mPath, mPaint); } |
实现一个BezierEvaluator
![](http://gavinliu.cn/images/2015.03.30%20-%20Android-Animation-%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF%E4%B9%8B%E7%BE%8E2.gif)
BezierEvaluator
实现一个三次方贝赛尔曲线Evaluator,已知公式为:
B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3代码如下:
BezierEvaluator.java
1 2 3 4 56 | public class BezierEvaluator implements TypeEvaluator<PointF> { private PointF points[]; public BezierEvaluator(PointF... points) { if (points.length != 4) { throw new IllegalArgumentException("只演示三次方贝赛尔曲线"); } this.points = points; } @Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) { // B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3 float t = fraction; float one_t = 1.0f - t; PointF P0 = points[0]; PointF P1 = points[1]; PointF P2 = points[2]; PointF P3 = points[3]; float x = (float) (P0.x * Math.pow(one_t, 3) + 3 * P1.x * t * Math.pow(one_t, 2) + 3 * P2.x * Math.pow(t, 2) * one_t + P3.x * Math.pow(t, 3)); float y = (float) (P0.y * Math.pow(one_t, 3) + 3 * P1.y * t * Math.pow(one_t, 2) + 3 * P2.y * Math.pow(t, 2) * one_t + P3.y * Math.pow(t, 3)); PointF pointF = new PointF(x, y); return pointF; } } |
一种ViewPager指示器的实现
Morning Routine 中有个ViewPager的指示器效果,非常炫酷,类似于下图,是怎么实现的呢?其实也用到了贝塞尔曲线。![](http://gavinliu.cn/images/2015.03.30%20-%20Android-Animation-%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF%E4%B9%8B%E7%BE%8E5.gif)
DropPagerIndicator
先绘制两个圆
1 2 | canvas.drawCircle(leftCircleX, mHeight / 2, leftCircleRadius, mPaint); canvas.drawCircle(rightCircleX, mHeight / 2, rightCircleRadius, mPaint); |
1 2 3 4 56 | private void drawModeBend(Canvas canvas) { float middleOffset = (leftCircleX - rightCircleX) / (mPoints.get(1).x - mPoints.get(0).x) * (mHeight / 10); mPath.reset(); mPath.moveTo(rightCircleX, mHeight / 2); mPath.lineTo(rightCircleX, mHeight / 2 - rightCircleRadius); mPath.cubicTo(rightCircleX, mHeight / 2 - rightCircleRadius, rightCircleX + (leftCircleX - rightCircleX) / 2.0F, mHeight / 2 + middleOffset, leftCircleX, mHeight / 2 - leftCircleRadius); mPath.lineTo(leftCircleX, mHeight / 2 + leftCircleRadius); mPath.cubicTo(leftCircleX, mHeight / 2 + leftCircleRadius, rightCircleX + (leftCircleX - rightCircleX) / 2.0F, mHeight / 2 - middleOffset, rightCircleX, mHeight / 2 + rightCircleRadius); mPath.close(); canvas.drawPath(mPath, mPaint); } |
![](http://gavinliu.cn/images/2015.03.30%20-%20Android-Animation-%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF%E4%B9%8B%E7%BE%8E3.jpg)
圆和中间颜色不同用来看看
![](http://gavinliu.cn/images/2015.03.30%20-%20Android-Animation-%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF%E4%B9%8B%E7%BE%8E4.jpg)
换成一样的,看起来还不错
然后加上Property Animation即可,了解 Property Animation
博客Demo代码:https://github.com/gavinliu/BeautifulOfBezier
结语
贝赛尔曲线能非常方便的绘制光滑的曲线,加以运用可以实现很多复杂的效果,实现的时候多和设计师沟通,设计师使用的PS中的钢笔其实也就是贝赛尔曲线,了解下设计师是如何绘制的,自己用代码来实现思路就很明了。相关文章推荐
- Rxjava和RxAndroid系列(一)
- Android view更改背景资源,padding消失的问题
- Android-开机自动启动程序并禁用返回键(BroadcastReceiver)
- Android学习—selector
- 关于Android PopupWindow 使用要注意的一些地方
- android的Intent用法实例
- Android 快速开发框架:推荐10个框架:afinal、ThinkAndroid ...
- android studio开发(一) 安卓的历史
- Vitamio中文API文档(3)—— MediaController
- android studio集成极光推送
- Android service
- Android自定义View
- android OSChina 客户端源代码剖析
- Android应用程序组件(一)
- 如何解决Android 5.0中出现的警告:Service Intent must be explict
- Android 自定义滑动开关ToggleButton
- Android Studio Jar、so、library项目依赖
- Android过度绘制优化心得
- android studio添加三方jar包
- Android性能优化(三),数据库优化