PathMeasure打造万能路径动效
转载自:http://blog.csdn.net/tianjian4592/article/details/47067161
前面两篇文章主要讲解了 Path 的概念和基本使用,今天我们一起利用 Path 做个比较实用的小例子;
上一篇我们使用 Path 绘制了一个小桃心,我们这一篇继续围绕着这个小桃心进行展开:
如果对这个桃心绘制有问题或有兴趣的同学,可以链接到 Path相关方法讲解(二),此时我们的需求是这样的:
假定我们现在是一个婚恋产品,有一个“心动”的功能,用户点击“心动”按钮的时候,有一个光点快速的沿着桃心转一圈,然后整个桃心泛起光晕!
针对这个需求,很多人可能会想到以下方案:
不就一个光点沿着桃心跑一圈么,既然桃心是使用贝塞尔曲线画出来的,那么我们就可以用对应的函数模拟出这条曲线,然后算出对应位置上的点,不断将光点绘制到对应的位置上!
这个思路当然没有问题,但我们还有相对简单的方式,那就是使用 PathMeasure:
我们主要使用它两个方法:
1.getLength() - 获取路径的长度
2.getPosTan(float distance, float pos[],float tan[]) - path 为 null ,返回 false
distance 为一个 0 - getLength() 之间的值,根据这个值 PathMeasure 会计算出当前点的坐标封装到 pos 中;
上面这句话我们可以这么来理解,不管实际 Path 多么的复杂,PathMeasure 都相当于做了一个事情,就是把 Path “拉直”,然后给了我们一个接口(getLength)告诉我们path的总长度,然后我们想要知道具体某一点的坐标,只需要用相对的distance去取即可,这样就省去了自己用函数模拟path,然后计算获取点坐标的过程;
接下来,我们用代码实现这一效果:
我们先创建一个 PathMeasure ,并将创建好的 path 作为参数传入
mPath = new Path(); mPath.moveTo(START_POINT[0], START_POINT[1]); mPath.quadTo(RIGHT_CONTROL_POINT[0], RIGHT_CONTROL_POINT[1], BOTTOM_POINT[0], BOTTOM_POINT[1]); mPath.quadTo(LEFT_CONTROL_POINT[0], LEFT_CONTROL_POINT[1], START_POINT[0], START_POINT[1]); mPathMeasure = new PathMeasure(mPath, true);
然后用一个数组纪录点的坐标:
private float[] mCurrentPosition = new float[2];
向外暴露一个开启动效的接口:
// 开启路径动画 public void startPathAnim(long duration) {// 0 - getLength() ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength()); Log.i(TAG, "measure length = " + mPathMeasure.getLength()); valueAnimator.setDuration(duration); // 减速插值器 valueAnimator.setInterpolator(new DecelerateInterpolator()); valueAnimator.addUpdateListener(new AnimatorUpdateListener() {@Override public void onAnimationUpdate(ValueAnimator animation) {float value = (Float) animation.getAnimatedValue(); // 获取当前点坐标封装到mCurrentPosition mPathMeasure.getPosTan(value, mCurrentPosition, null); postInvalidate(); }}); valueAnimator.start(); }
实时获取到当前点之后,将目标绘制到对应位置:
protected void onDraw(Canvas canvas) {super.onDraw(canvas); canvas.drawColor(Color.WHITE); canvas.drawPath(mPath, mPaint); canvas.drawCircle(RIGHT_CONTROL_POINT[0], RIGHT_CONTROL_POINT[1], 5, mPaint); canvas.drawCircle(LEFT_CONTROL_POINT[0], LEFT_CONTROL_POINT[1], 5, mPaint); // 绘制对应目标 canvas.drawCircle(mCurrentPosition[0], mCurrentPosition[1], 10, mPaint); }
到这里目标环绕 path 的效果就ok了,不管这条路径简单也好,复杂也罢,我们都可以如此简单的完成对应的效果,而不需要自己用简单或复杂函数模拟求解了;
完成了一步,自己提的需求还有一点就是光晕的问题,这个东西如何是好呢?切图?! 不需要,Android 已经给我们提供了一个好用的东西 MaskFilter ,后面我就不做了,大家有兴趣自己做的玩玩,只需要注意一点,MaskFilter 不支持硬件加速,记得关掉!
好了,PathMeasure 看似很简单,但着实很有用,有了它,再结合上 Path 、Shader、ColorMatrix 等利器,我们已经可以做出很多酷炫的效果了!
最后,完整的代码献上,请笑纳:
public class DynamicHeartView extends View {private static final String TAG = "DynamicHeartView"; private static final int PATH_WIDTH = 2; // 起始点 private static final int[] START_POINT = new int[] {300, 270 }; // 爱心下端点 private static final int[] BOTTOM_POINT = new int[] {300, 400 }; // 左侧控制点 private static final int[] LEFT_CONTROL_POINT = new int[] {450, 200 }; // 右侧控制点 private static final int[] RIGHT_CONTROL_POINT = new int[] {150, 200 }; private PathMeasure mPathMeasure; private Paint mPaint; private Path mPath; private float[] mCurrentPosition = new float[2]; public DynamicHeartView(Context context) {super(context); init(); }private void init() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Style.STROKE); mPaint.setStrokeWidth(PATH_WIDTH); mPaint.setColor(Color.RED); mPath = new Path(); mPath.moveTo(START_POINT[0], START_POINT[1]); mPath.quadTo(RIGHT_CONTROL_POINT[0], RIGHT_CONTROL_POINT[1], BOTTOM_POINT[0], BOTTOM_POINT[1]); mPath.quadTo(LEFT_CONTROL_POINT[0], LEFT_CONTROL_POINT[1], START_POINT[0], START_POINT[1]); mPathMeasure = new PathMeasure(mPath, true); mCurrentPosition = new float[2]; }@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas); canvas.drawColor(Color.WHITE); canvas.drawPath(mPath, mPaint); canvas.drawCircle(RIGHT_CONTROL_POINT[0], RIGHT_CONTROL_POINT[1], 5, mPaint); canvas.drawCircle(LEFT_CONTROL_POINT[0], LEFT_CONTROL_POINT[1], 5, mPaint); // 绘制对应目标 canvas.drawCircle(mCurrentPosition[0], mCurrentPosition[1], 10, mPaint); }// 开启路径动画 public void startPathAnim(long duration) {// 0 - getLength() ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength()); Log.i(TAG, "measure length = " + mPathMeasure.getLength()); valueAnimator.setDuration(duration); // 减速插值器 valueAnimator.setInterpolator(new DecelerateInterpolator()); valueAnimator.addUpdateListener(new AnimatorUpdateListener() {@Override public void onAnimationUpdate(ValueAnimator animation) {float value = (Float) animation.getAnimatedValue(); // 获取当前点坐标封装到mCurrentPosition mPathMeasure.getPosTan(value, mCurrentPosition, null); postInvalidate(); }}); valueAnimator.start(); } }
以上代码的效果如下,其余效果大家自行补充:
PathMeasure打造万能路径特效 - 源码下载
PathMeasure打造万能路径动效相关推荐
- Path特效之PathMeasure打造万能路径动效
转自:http://blog.csdn.net/u013831257/article/details/51565591 Path之玩出花样 作者微博: @GcsSloop [本系列相关文章] 可以看到 ...
- Android使用SVG矢量图打造酷炫动效!
一个真正酷炫的动效往往让人虎躯一震,话不多说,咱们先瞅瞅效果: 如果你想看 GAStudio Github主页,请戳这里: 如果你想看 GAStudio更多技术文章,请戳这里: QQ技术交流群:277 ...
- 动效引擎_要做动效?这75款动效工具让你无所不能(上)
原标题:要做动效?这75款动效工具让你无所不能(上) 动效这两年崛起非常之迅猛,几乎是网页设计领域最强大的设计趋势之一.无论是在设计师群体还是在用户当中,它的受欢迎程度都非常之高,大家都对它津津乐道. ...
- 动效素材极速交付: 腾讯PAG动效组件技术揭秘
编者按:音视频产品中的动效素材需求是源源不断的,例如贴纸花字,转场特效,照片和视频模板等,并且对它们的产量,上线速度,以及视觉效果都有比较高的要求.但在传统工作流中的交付成本却非常高,需要通过代码来手 ...
- 动效设计原理:从卡通动画到UI动效
UI是基于静态页面来设计的,页面之间通过跳转切换.在设计过程中,设计师很重视单页的视觉效果,却经常忽略了对界面跳转的处理.这些未经处理的跳 转由于没有提供足够的预期,所以用户在使用时经常会觉得困惑.与 ...
- 三看 SVG Web 动效
CSS3 动效玩腻了吗?没关系的,我们还有 SVG. Welikesmall 是一个互联网品牌宣传代理,这是我见过的最喜欢使用 SVG 做动效的网页设计团队.事实上,越来越多的网页动效达人选择在 SV ...
- H5动效的常见制作手法 - 腾讯ISUX
众所周知,一个元素,动往往比静更吸引眼球: 一套操作界面,合适的动态交互反馈能给用户带来更好的操作体验: 一个H5运营宣传页,炫酷的动画特效定能助力传播和品牌打造. 近两年,小到loading动画,表 ...
- lottie 导出html,Lottie Web动效基本原理
前段时间在<Lottie Web动效在React中的构建>一文中和大家聊了如何通过lottie-web将AE导出来的JSON文件自动生成动效.在该文中,聊的主要是设计软件Figma.Ske ...
- 行业思考 | 酷炫动效是否利于你的产品设计?
本文为PMCAFF专栏作者南可出品 前言 写这篇文章的起因是前段时间在Meidum上读到的一篇驳斥dribbble发展现状的文章.文章发表在16年,其中提到:"我不认为dribbble解决了 ...
- HTML5培训教程学习之动效制作
近年来,HTML5应用愈发广泛,并有取代Flash的趋势.很多人知道利用HTML5可以做出好的动作效果,但你知道它是怎么做出来的吗?今天小千就来给大家分享一下HTML5培训教程中动效制作的几种方法. ...
最新文章
- 并行机调度问题matlab,顺序依赖并行机调度问题介绍
- ArcServer for Java 讲座
- jdk javac运行不了_Intellij IDEA搭建jdk源码阅读环境
- U盘为什么还有剩余空间,但却提示说空间不够
- PyQt5 技术篇-QWidget、Dialog设置界面固定大小、不可拉伸方法实例演示
- 大规模微服务利器:eBPF + Kubernetes
- Spring系列(二):Bean注解用法介绍
- SQL- AND OR Order by INSERT INTO
- Java 设计模式之Mediator调节者模式
- “System.AccessViolationException”类型的未经处理的异常在 System.Data.dll 中发生
- PHP表单常用正则表达式(URL、HTTP、手机、邮箱等)
- DataScience:风控场景之金融评分卡模型构建—将逻辑回归LoR模型结果转为评分卡之详细攻略
- python与开源gis空间分析_Python 与开源GIS:数据处理、空间分析与地图制图
- h5制作导出html,H5制作工具Hype的导出功能详解
- 企业服务器系统怎么做,如何搭建一个小型企业服务器机房?6个步骤学起来!...
- JavaScript 教程「2」:注释、输入输出、变量
- 驱动精灵 v9.61 去广告最终版绿色清爽单文件
- 扫地机器人哪个牌子好?合格的扫地机器人推荐
- 记录【1】Vue遇到的bug , 点击按钮出现Cannot read property 'toString' of undefined的解决方法
- sql server2008处理笛卡儿积的逻辑——记一次解决疑惑