呵呵将 个推Android高阶合作开发技师
序言
APP合作开发市场已经挥别“残暴繁殖”黄金时代,现代人无须满足用户于APP外型技术创新,而将注意力转为全方面的使用者新体验上。在这过程中,动效化作为移动互联网产品的新趋势,如何同时实现酷炫柔滑的动画电影效用早已成为合作开发人员们的新研究课题。同时实现方式其实很单纯。责任撰稿将为你探究方法论此基础和具体内容应用领域。看完这首诗,你的App也可以达到酷炫吊炸天的动画电影效用。
先看三个范例:
1. 智能手机 QQ 表里消息红点拖曳效用。
2. 短篇小说写作 APP 的缩放效用。
概要
在开始两栖作战之前,我们还是先了解下方法论此基础。动画电影的毁灭者枪械就是德帕伦抛物线了。它是一条扁平的抛物线,依照五个边线任一的点座标绘出而成。1962年,比利时工程师弗朗索瓦·德帕伦(Pierre Bézier)火速研究出这种向量绘出抛物线的方法并得出了详尽的计算方法,应用领域于汽车的市场主体结构设计。因此,现代人将按照此类式子绘出的抛物线重新命名为德帕伦抛物线。
中心思想
德帕伦抛物线是计算机信号处理中利用得最多的模块抛物线之一。它通过控制抛物线上的五个点(初始点、中止点和三个互相分立的尾端点)来缔造、撰稿绘图。其中起重要作用的是位于抛物线中央的边界线。这条线是交互式的,尾端与德帕伦抛物线交叠,两端是控制端点。移动两端的端点时德帕伦抛物线可以改变抛物线的曲率(弯曲的程度);移动尾端点(也就是移动交互式的边界线)时,德帕伦抛物线在初始点和中止点锁定的情况下做均匀移动。注意:德帕伦抛物线上的所有控制点、节点均可撰稿。
基本原理
这里面有个通用式子,这个式子已经有前辈帮我们总结好了。
其中 P0 为起点,Pn 为中点,Pi 为控制点。
一阶德帕伦抛物线
一阶这个比较单纯,因为没有在网上找到可以直接输入数学式子的工具,就手工推导了下。
最后的式子为 B(t)=(1-t)Po+tP1,t->[0,1]
二阶德帕伦抛物线
先看动画电影效用。
着 t 的不断变化,红线的转换过程非常的顺滑。
最后得到的式子如下:
德帕伦抛物线的绘出,无论多少阶(一阶除外),均需要逐级降阶,最终降至一阶。在 “二阶德帕伦抛物线解析” 这段文字中,从 第一步 到 第二步 的过程就是在降阶。德帕伦抛物线最终的路径是由 一阶基线 上游走的红色小点形成的。
三阶德帕伦抛物线
有了二阶的推导过程,三阶的推导就容易多啦。由于篇幅限制,推导过程这里无须展开,大家有兴趣的话可以自行推导下。
最后的红色抛物线是由蓝色一阶抛物线获得的,而蓝色一阶抛物线又是由绿色一阶抛物线获得,最后的绿色一阶抛物线则是最外的 P0,P1,P2,P3构成的。动画电影效用为:
四阶德帕伦抛物线
五阶德帕伦抛物线
结论 我们发现原来德帕伦抛物线上的点与高数中二项式展开一样,对于每个线段上的点经过控制点进行切面操作,而连续的两点之间是无限接近的,所以在绘出的过程中会出现非常柔滑地过度。
德帕伦抛物线在 Android 上的使用
在Android 中使用德帕伦抛物线比较单纯,Android 已经内置了德帕伦抛物线的 API,合作开发人员可以直接予以调用。主要有三个 API 。
quadTo
Path path = new Path();path.moveTo(startX, startY); path.quadTo(eventX, eventY, endX, endY); canvas.drawPath(path, paint);其中 (startX,startY) 为起点,(endX,endY)为终点,而 (eventX,eventY)即为控制点了。
cubicTo
Path path = new Path();path.moveTo(startX, startY);path.cubicTo(leftX, leftY, rightX, rightY, endX, endY);canvas.drawPath(path, paint);调用此方法即可画出一条三阶德帕伦抛物线。(startX,startY)为起点,(endX,endY)为终点,而(leftX,leftY)与(rightX,rightY) 为三个控制点了。
多阶德帕伦抛物线:Android 系统最高只能画出三阶的德帕伦抛物线,那么想画出更高阶的怎么办呢?其实也很单纯。如果真的需要使用高阶的抛物线,可以进行人工降阶,降阶到 3 级即可。
两栖作战
终于到两栖作战环节了,该环节共有三个demo。一个是德帕伦抛物线拟圆效果,另一个是仿网易云音乐里面的鲸云效用。
效用同时实现1:以德帕伦抛物线画圆为例
前文总结了德帕伦抛物线的通用式子。在网上浏览资料的过程中我们发现有这么一个式子:(4/3)tan(π/(2n)),其意义是由n段三阶德帕伦抛物线拟合圆形时,抛物线端点到该端点最近的控制点的最佳距离是(4/3)tan(π/(2n))。大家感兴趣的话可以自行推导。推导过程并不复杂,因为德帕伦抛物线有个重要的性质,即抛物线方程中t=0.5时的点一定落在圆弧上。只需要把座标系带入到三阶方程式即可。
最后得知当 t=0.5,根据圆形方程式 X^2+Y^2=R^2 ,得到h=(4/3)(sqrt(2)-1) ≈ 0.552284749831 。有了上述的方法论此基础,再去画圆就非常的轻松,我们先在草稿纸中得到这么一个模型。
根据上图,这个圆是由 4 段三阶德帕伦抛物线构成的,分别是 P0->P3,P3->P6,P6->P9,P9->P11。三阶德帕伦抛物线的构图是 Android 内置的,我们直接调用API 即可,核心代码如下:
public HeartView(Context context, @Nullable AttributeSet attrs,int defStyleAttr) { super(context, attrs, defStyleAttr); init(context) } @Override protected void init(Context context) { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(Color.RED);mPaint.setStyle(Paint.Style.FILL); mPath = new Path(); //绘出 12 个点。 mCurPointList = new ArrayList<>(); mCurPointList.add(newPointF(0, dpToPx(-89))); mCurPointList.add(new PointF(dpToPx(50), dpToPx(-89))); mCurPointList.add(newPointF(dpToPx(90), dpToPx(-49))); mCurPointList.add(new PointF(dpToPx(90), 0)); mCurPointList.add(newPointF(dpToPx(90), dpToPx(50))); mCurPointList.add(new PointF(dpToPx(50), dpToPx(90))); mCurPointList.add(new PointF(0, dpToPx(90))); mCurPointList.add(new PointF(dpToPx(-49), dpToPx(90))); mCurPointList.add(newPointF(dpToPx(-89), dpToPx(50))); mCurPointList.add(new PointF(dpToPx(-89), 0)); mCurPointList.add(newPointF(dpToPx(-89), dpToPx(-49))); mCurPointList.add(new PointF(dpToPx(-49), dpToPx(-89))); } @Override protected void onDraw(Canvas canvas) { drawCoordinate(canvas); canvas.translate(mWidth / 2, mHeight / 2);mPath.reset(); for (int i = 0; i < 4; i++) { if (i == 0) { mPath.moveTo(mCurPointList.get(i * 3).x, mCurPointList.get(i * 3).y); } else { mPath.lineTo(mCurPointList.get(i * 3).x, mCurPointList.get(i * 3).y); } intendPointIndex; if (i == 3) { endPointIndex = 0; } else { endPointIndex = i * 3 + 3; } mPath.cubicTo(mCurPointList.get(i * 3 + 1).x, mCurPointList.get(i * 3 + 1).y, mCurPointList.get(i * 3 + 2).x, mCurPointList.get(i * 3 + 2).y,mCurPointList.get(endPointIndex).x, mCurPointList.get(endPointIndex).y); } canvas.drawPath(mPath, mPaint); }}成果展示
效用同时实现2:以网易云音乐鲸云效用为例
转换成 GIF,图片可能会有点失真,但并不妨碍具体内容同时实现思路。根据这个 GIF,我们发现有三点功能需要去完成:
1.背景色与歌曲图片相搭配,随图片的变化而变化;
2.歌曲尾端图片是一张圆形图片并且可以自动旋转;
3.绘图外圈有动感 3D环绕效用。
第一点同时实现比较单纯。
第二点也不难。我们可以把一张图片裁剪成圆形,也可以使用 GitHub 上现有的开源库,再加上一个属性动画电影代码。
public void handleRotate(){ ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivShowPic, “rotation”, 0f, 360f); objectAnimator.setDuration(20 * 1000); objectAnimator.setRepeatMode(ValueAnimator.RESTART);objectAnimator.setInterpolator(new LinearInterpolator()); objectAnimator.setRepeatCount(-1);objectAnimator.start(); }看下动感3D环绕效用即转圈圈。
第三点 如何做跳动旋律特技?!!先不考虑前面两点需求,我们逐步分析下跳动旋律特技。动态图在文章开始部分已经看到了,我们建议先从静态图着手。
我们猜测可能的同时实现思路(不代表官方同时实现思路):该动效外层一圈有 4 条线段在不规则地跳动,每条线的背后是一个圆,每个圆由 4 条德帕伦抛物线组成。
第一步先画个圆。我们只需要把画笔的属性设置成如下属性,即可画出一个空心圆。
mPaint.setStyle(Paint.Style.STROKE);为达到更顺滑的环绕效用,我们需要不断调试各条德帕伦抛物线的对应的三个控制点。具体内容模块可根据业务场景来定。文中demo仅作参考。
第二步上文我们分析过这个圆其实是由德帕伦抛物线组成的拟圆。在Android系统中是以每秒60帧为满帧的,那么只要将1秒÷60帧,就能得出16毫秒(ms)/帧是满帧的界限,即每帧快于16ms则为流畅。所以我们这边的刷新频率设定为每 80 毫秒刷新一次:
public void onPlay(View view){scheduledExecutorService = Executors.newScheduledThreadPool(1); scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { diyBezierView.post(new Runnable() { @Override public void run() { diyBezierView.play(); } }); } },0,80, TimeUnit.MILLISECONDS);得到的效用如下:
第三步 雏形已经完成,后续我们的做法是再往上添加 2 个圆,看下 3 个圆是怎么样的效用。
第四步最后一步当然是把前面两点合在一起啦,合一起后就可以看下最终效用了:
实际效用与预期效用会存在一定的差异,主要原因在于函数座标和画笔的一些属性问题。以上就是具体内容的同时实现思路,供大家参考。
总结
酷炫动画电影的同时实现过程并没有我们想象的那么复杂。其实,很多复杂特技都是由不同的动画电影组合而成的,而柔滑般的动态效用则离不开德帕伦抛物线的应用领域。希望这首诗可以帮助到想要做出酷炫柔滑的动态效用的你。
h)
抛物线”