一个绚丽的Downloading动效分析与实现.doc_第1页
一个绚丽的Downloading动效分析与实现.doc_第2页
一个绚丽的Downloading动效分析与实现.doc_第3页
一个绚丽的Downloading动效分析与实现.doc_第4页
一个绚丽的Downloading动效分析与实现.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一个绚丽的Downloading动效分析与实现这个动效用CJJ的话说难度还好,但本人觉得还比较灵动、带感、俏皮、有新意,好了话不多说,咱们先来撸一张高清无码gif图: 咱可以将整个动效简单划分为以下流程:1. BeforeProgress(显示进度前);2. InProgress(显示进度中);3.Failed(失败动画);4.Done(完成动画);下面咱们一起对以上流程进行分析与实现;1. BeforeProgress(显示进度前):同样,咱们一起撸一下第一部分高清无码gif图:通过观察,我们可以将以上动画分割为以下几个内容:1.圆形背景和下载剪头整体缩放;2.圆形背景逐步镂空(缩放到一定阶段,内部镂空圆不断扩大);3.圆形背景变为一条直线,并伴随箭头些许上移;4.直线上下震荡及下载箭头(Arrow)变承载进度文字的线框形态;1.1. 圆形背景和下载剪头整体缩放:这里面,圆形背景和整体的缩放好说,稍显麻烦的是下载箭头,由于后面箭头还需要形变为承载进度文字的线框,所以丢掉你使用图片的小想法,咱们一起用path勾一个活泼的小箭头:/ move to bottom centermArrowPath.moveTo(halfArrowWidth, 0);/ rect bottom left edgemArrowPath.lineTo(rectPaddingLeft, 0);/ rect left edgemArrowPath.lineTo(rectPaddingLeft, rectHeight);/ tri bottom left edgemArrowPath.lineTo(triPaddingLeft, rectHeight);/ tri left edgemArrowPath.lineTo(halfArrowWidth, arrowHeight);/ tri right edgemArrowPath.lineTo(arrowWidth - triPaddingLeft, rectHeight);/ tri bottom right edgemArrowPath.lineTo(arrowWidth - rectPaddingLeft, rectHeight);/ rect right edgemArrowPath.lineTo(arrowWidth - rectPaddingLeft, 0);/ rect right bottom edgemArrowPath.lineTo(halfArrowWidth, 0);箭头OK了,圆形背景和整体的缩放就不再细说,只需要canvas.drawCircle()和使用ValueAnimator动态改变canvas缩放比例即可,so easy!后面箭头需要形变为承载进度文字的线框,通过观察,可以看到线框的4个角是圆角。由于使用path勾勒,实现圆角线框大致有以下几种方案:1.使用path的quadTo()以二次贝塞尔曲线连接;2.使用path的arcTo()以圆弧形式连接;3.使用path中addArc()添加一段圆;4.使用paint的setPathEffect设置PathEffect为ConnerPathEffect;本人最终采用第四种方式进行实现;上图,我们可看到,圆形背景由实心圆变换至一个圆环,最终消失,此处我们可以想到如下方案:1. 直接采用背景的颜色,在里面画实心圆(需要提前知道背景颜色并且背景只能为纯色); 2. 外面深色的圆直接是圆环,然后通过调整圆的半径及paint的strokeWidth实现;3.直接采用混合模式(Xfermode),圆形背景中混合掉内圆部分;第一种方案太挫,帅气逼人的GAStudio哥肯定不会考虑,本文采用混合模式方案,关键代码如下:int layoutCont = canvas.saveLayer(mCircleRectF, mDefaultPaint, Canvas.ALL_SAVE_FLAG);mDefaultPaint.setColor(mLoadingCircleBackColor);canvas.drawCircle(mCircleRectF.centerX(), mCircleRectF.centerY(), mCircleRadius, mDefaultPaint);mDefaultPaint.setXfermode(mXfermode);/ draw bg circle 2int innerCircleRadius = (int) (mCircleRadius * innerCircleScalingFactor);canvas.drawCircle(mCircleRectF.centerX(), mCircleRectF.centerY(), innerCircleRadius, mDefaultPaint);mDefaultPaint.setXfermode(null);canvas.restoreToCount(layoutCont);1.3.圆形背景变为一条直线,并伴随箭头些许上移:这个部分相比前面两步稍显复杂,需要将圆环如丝般顺滑的变换成直线,并随之上线震荡,该过程拆解图如下:对于这个过程,GAStudio哥采用两条三阶贝塞尔曲线对初期的圆环、中间部分的曲线、最终的直线进行模拟;为了便于理解,抽象出四个核心状态,过程图解如下:1. 完整圆形状态:2.3.4. 更新path核心逻辑如下:5. vate void updateCircleToLinePath(Path linePath, int circleDiameter, float normalizedTime) 6. if (linePath = null) 7. return;8. 9. int index = 0;10. float adjustNormalizedTime = 0;11. if (normalizedTime = CIRCLE_TO_LINE_SEASONS1) 12. adjustNormalizedTime = normalizedTime / CIRCLE_TO_LINE_SEASONS1;13. else if (normalizedTime CIRCLE_TO_LINE_SEASONS2) 14. index = 1;15. adjustNormalizedTime = (normalizedTime - CIRCLE_TO_LINE_SEASONS1)16. / (CIRCLE_TO_LINE_SEASONS2 - CIRCLE_TO_LINE_SEASONS1);17. else 18. index = 2;19. adjustNormalizedTime = (normalizedTime - CIRCLE_TO_LINE_SEASONS2)20. / (CIRCLE_TO_LINE_SEASONS3 - CIRCLE_TO_LINE_SEASONS2);21. 22.23. / the path bounds width24. int boundWidth = (int) (CIRCLE_TO_LINE_WIDTH_FACTORindex + 125. - CIRCLE_TO_LINE_WIDTH_FACTORindex)26. * adjustNormalizedTime + CIRCLE_TO_LINE_WIDTH_FACTORindex) * circleDiameter);27.28. / the distance of cubic line1 x1 to cubic line2s x229. int adjustBoundWidth = boundWidth;30. if (normalizedTime -30 - 20 - -10 - 0度;OK,到这里,第一部分就可以告一段落,咱们继续看后面的部分;2. InProgress(显示进度中) :GAStudio哥本次在实现过程中,没有实现在移动的过程中的线框的摇摆,有兴趣的同学可以自己修改实现,剩余部分主要讲下拉绳的变动:2.1. 拉绳的变动:观察上图,可以将拉绳下拉的顶点移动的轨迹近似看成一条折线, 先计算出顶点的位置,再分别绘制左、右两边的直线,关键代码如下:private void drawProgressRopePath( Canvas canvas, float normalizeProgress, int baselineLen, int baseLineX, int baseLineY, int highestPointHeight, int leftLineColor) int halfLen = baselineLen / 2; int middlePointX = (int) (baseLineX + baselineLen * normalizeProgress); int middlePointY; float k = (float) highestPointHeight / halfLen; if (normalizeProgress HALF_NORMALIZED_PROGRESS) middlePointY = (int) (halfLen * k * normalizeProgress / HALF_NORMALIZED_PROGRESS) + baseLineY; else middlePointY = (int) (halfLen * k * (1 - normalizeProgress) / HALF_NORMALIZED_PROGRESS) + baseLineY; / draw right part first mBaseLinePaint.setColor(DEFAULT_LOADING_LINE_COLOR); canvas.drawLine(middlePointX, middlePointY, baseLineX + baselineLen, baseLineY, mBaseLinePaint); / draw left part mBaseLinePaint.setColor(leftLineColor); canvas.drawLine(baseLineX, baseLineY, middlePointX, middlePointY, mBaseLinePaint); if (mProgressRopePathRectF = null) mProgressRopePathRectF = new RectF(); mProgressRopePathRectF.set(baseLineX, baseLineY, baseLineX + baselineLen, middlePointY);3. Failed(失败动画):撸完以上gif,我们可以把这部分效果分为如下几点:1.线框内的文字变为Failed并且晃动;2.绳子上下抖动;3.绳子左侧的白色部分爆炸消失;4.线框回到最初位置,变且变为下载箭头;5.圆形背景逐渐放大出现;6.圆形背景和下载箭头整体缩放;在这里,我们一起看下爆炸效果的实现,其他部分相对简单,不再赘述;关于爆炸效果,我们可以很逼真的模拟,绘制出各式各样的圆点来模拟,但是由于点的个数多,大小不一,采用该方式费事费力,并且由于效果速度快,转瞬即逝,我们可以采用一种简单而效果看起来差不多的方式,就是只画几个形状,然后平铺到整个绳子;该处主要使用paint的setPathEffect方法将PathEffect设置为PathDashPathEffect,关键代码如下:Path cycle = new Path();/ generate bomb point shapecycle.addCircle(0, 0, mBaseLineStrokeWidth / 2, Path.Direction.CCW);cycle.addCircle(mBaseLineStrokeWidth, 0, mBaseLineStrokeWidth / 3, Path.Direction.CCW);cycle.addCircle(mBaseLineStrokeWidth * 2, 0, mBaseLineStrokeWidth / 4, Path.Direction.CCW);cycle.addCircle(mBaseLineStrokeWidth * 3, 0, mBaseLineStrokeWidth / 5, Path.Direction.CCW);mFailedBombPaint = ew Paint();mFailedBombPaint.setStrokeWidth(mBaseLineStrokeWidth);mFailedBombPaint.setAntiAlias(true);mFailedBombPaint.setColor(DEFAULT_PROGRESS_LINE_LEFT_COLOR);mFailedBombPaint.setStyle(Paint.Style.STROKE);mFailedBombPaint.setPathEffect(new PathDashPathEffect(cycle, mBaseLineStrokeWidth * 3, 0, PathDashPathEffect.Style.TRANSLATE);mFailedBombBellowPaint = new Paint(mFailedBombPaint);mFailedBombBellowPaint.setPathEffect(new PathDashPathEffect(cycle, mBaseLineStrokeWidth * 3, HALF_FULL_ANGLE, PathDashPathEffect.Style.TRANSLATE);4.Done(完成动画):撸完以上gif, 我们可以将该部分概括为以下部分:1. 线框绕Y轴旋转,并由100%变换为done;2.线框随进度条收缩到最中心;3.线框在中心点晃动;4.线框变换为下载箭头,圆形背景复出;5.圆形背景和下载箭头整体缩放,伴随下载箭头上下晃动;该部分咱们一起看下第一条的实现,即Canvas里如何实现伪三维变换;Canvas中只有rotate函数,也就是在二维平面内进行旋转,不能实现如上的绕Y轴旋转,类似效果需要借助Camera来实现,关键代码如下:float angle;String str;if (normalizedTime = HALF_NORMALIZED_PROGRESS) str = FULL_PROGRESS_STR; angle = HALF_FULL_ANGLE * normalizedTime; mProgressTextPaint.setColor(DEFAULT_PROGRESS_TEXT_COLOR); else str = FULL_PROGRESS_DONE_STR; angle = HALF_FULL_ANGLE * normalizedTime + HALF_FULL_ANGLE; mProgressTextPaint.setColor(DEFAULT_DONE_PROGRESS_TEXT_COLOR);if (mCamera = null) mCamera = new Camera();mCamera.save();mCamera.rotateY(angle);mCamera.getMatrix(mArrowRotateMatrix);mCamera.restore();/ 保证绕Arrow的中心进行旋转mArrowRotateMatrix.preTranslate(-mArrowRectF.centerX(), -mArrowRectF.centerY();mArrowRotateMatrix.postTranslate(mArr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论