Android自定义View 星球运动在dribbble闲逛的时候发现的一个有意思的星球运动的动画,刚好最近时间尚可,就简单实现了一下中间运动的部分,又是因为时间的原因,开头位移的部分没有完成.

 这是在dribbble中发现的动画

 这是我自己实现的效果... 总觉得我这个星球有点胖... 因为胖所以转的慢么这是.速度等细节还有优化的余地

设计过程

老办法,先分解动画的构成.整个动画可以看做是一个自旋的星球从右上角由小变大的移动到屏幕的中央的.

星球的位移及缩放不说(其实是最近有需求,暂时没时间完善),主要完善了星球的旋转及尾部的处理.

最底层是背景的星星闪烁,每次在星球一定范围内随机出现,并缩放就好

最开始设计尾部效果的时候,是在没列中设计了两端线.再不断的运行及移动.但是实现起来很乱.最后采用了先绘制所有尾部展示的内容,然后在用和背景一样的颜色部分遮盖并移动此部分形成视觉上的效果的方法.(也可以设置PorterDuff模式来展示).设计过程中的效果如下

星球的设计,星球的本身使用简单的遮盖和贝塞尔曲线就能完成一个较为满意的星球背景.

重点是星球地表的设计以及星球自转下的地表样式的移动.解决的方法是是先绘制三个重复并连续的地表样式,通过移动整个地表样式模拟星球的转动.最后通过PorterDuff来控制展示的部分和星球的位置重合.

未开启PorterDuff模式时绘制的样式如下:

开启PorterDuff模式后再指定位置展示指定形状的图形如下:

最后再移动设置好的星球地貌就可以模拟出星球转动的效果了

代码实现

背景的星星private fun drawStarts(canvas: Canvas, perIndexInAll: Float) {

//背景的星星在星球附近的一定范围内随机出现

val maxRand = 800

canvas.translate(-maxRand / 2F , -maxRand / 2F)

val Random = Random(perIndexInAll.toInt().toLong())

//绘制背景的星星

for (index in 0..4){

drawStart(canvas ,  Random.nextFloat() * maxRand , Random.nextFloat() * maxRand , perIndex)

}

canvas.translate(maxRand / 2F , maxRand / 2F)

}

//绘制背景的星星内容

//绘制背景的星星内容

private fun drawStart(canvas: Canvas, x: Float, y: Float, per: Float) {

var per = per

//这个部分是为了让星星实现从小到大后再从大到小的变动

if (per >= 1.0F){

per -= 1F

}

if (per <= 0.5F){

per *= 2

}else{

per = (1 - per) * 2

}

canvas.save()

canvas.translate(x , y)

canvas.scale(per , per)

val paint = Paint()

paint.color = 0xff78D8DF.toInt()

val startLength = 30F

val startOffset = startLength / 3F

//通过路径描绘星星的形状

val path = Path()

path.moveTo(0F , startLength)

path.lineTo(startOffset , startOffset )

path.lineTo(startLength , 0F)

path.lineTo(startOffset  , -startOffset )

path.lineTo(0F , -startLength)

path.lineTo(-startOffset  , -startOffset )

path.lineTo(-startLength , 0F)

path.lineTo(-startOffset  , startOffset )

path.lineTo(0F , startLength)

canvas.drawPath(path , paint)

paint.color = viewBackgroundColor

//通过缩小绘制星星内部形状

canvas.scale(0.3F , 0.3F)

canvas.drawPath(path , paint)

canvas.restore()

}

星球外部private fun drawGas(canvas: Canvas, index: Float) {

canvas.save()

canvas.rotate(45F)

val gasWidth = 18F

val baseR = baseR * 0.7F

val absBaseR = baseR / 5F

val paint = Paint()

paint.strokeWidth = gasWidth

paint.style = Paint.Style.STROKE

paint.color = 0xff2F3768.toInt()

val paintArc = Paint()

paintArc.color = 0xff2F3768.toInt()

val gasLength = baseR * 2F

canvas.save()

val gsaL = gasWidth / 2F * 3

var maxGasLength = (gasLength + gsaL ) / 2

var index = index

canvas.scale(1F , -1F)

//绘制星球后面的气流情况

//舍不得那么多定义好的变量

//又不想写个参数很多的函数,就这么实现了

canvas.save()

canvas.translate(baseR , baseR * 1.2F)

canvas.translate(0F , absBaseR)

//drawLines函数一个绘制两头带半圆的线段

drawLines(0F, maxGasLength, canvas, paint)

drawWhite( maxGasLength * index, gasWidth , gsaL * 2 , canvas)

drawWhite( maxGasLength * (index - 1 ) * 1.1F, gasWidth , gsaL * 2 , canvas)

drawWhite( maxGasLength * (index + 1 ) * 1.1F, gasWidth , gsaL * 2 , canvas)

canvas.restore()

index = index + 0.3F

//.....没有写函数就不上重复的代码了

val rectf = RectF(-baseR , -baseR , baseR ,baseR)

canvas.drawArc(rectf , 0F , 180F , false , paint)

canvas.drawLine(baseR ,0F ,  baseR ,  -baseR, paint)

canvas.drawLine(-baseR ,0F ,  -baseR ,  -baseR, paint)

canvas.restore()

}

//绘制尾部空白部分

private fun drawWhite(offset: Float, gasWidth: Float, gsaL : Float , canvas: Canvas) {

val r = gasWidth / 2F

canvas.save()

canvas.translate( 0F , offset - 2 * gsaL )

val pointPaint = Paint()

pointPaint.strokeWidth = 20F

pointPaint.color = Color.RED

//通过贝塞尔曲线绘制半圆效果

val path = Path()

path.moveTo(-r , gsaL)

path.cubicTo(

- r * C ,  gsaL - r,

r * C ,  gsaL - r,

r , gsaL

)

path.lineTo(r , - gsaL)

path.cubicTo(

r * C ,  - gsaL + r,

-r * C ,  - gsaL + r,

-r , - gsaL

)

path.lineTo(-r , gsaL * 1.5F)

val paint = Paint()

paint.color = viewBackgroundColor

canvas.drawPath(path , paint)

canvas.restore()

}

星球private fun drawPlanet(canvas: Canvas , index : Float) {

//设置原图层

val srcB = makeSrc(index)

//设置遮罩层

//遮罩层只有一和星球大小一样的圆

val dstB = makeDst(index)

val paint = Paint()

canvas.saveLayer(-baseR, -baseR, baseR , baseR, null, Canvas.ALL_SAVE_FLAG)

//绘制遮罩层

canvas.drawBitmap(dstB,  -baseR / 2F, -baseR / 2F , paint)

//设置遮罩模式为SRC_IN显示原图层中原图层与遮罩层相交部分

paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)

canvas.drawBitmap(srcB, width / -2F, height / -2F , paint)

paint.xfermode = null

}

//设置源图层

fun makeSrc(index :Float): Bitmap {

val bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)

val canvas = Canvas(bm)

canvas.translate(width.toFloat() / 2F , height.toFloat() / 2F)

val paint = Paint()

paint.color = 0xff57BEC6.toInt()

paint.style = Paint.Style.FILL

val rectf = RectF(-baseR / 2F, -baseR / 2F, baseR / 2F, baseR / 2F)

canvas.drawArc(rectf , 0F , 360F , true , paint)

canvas.save()

//绘制星球背景

paint.color = 0xff78D7DE.toInt()

var baseR = baseR * 0.9.toFloat()

val rectf2 = RectF(-baseR / 2F, -baseR / 2F, baseR / 2F, baseR / 2F)

canvas.translate(baseR / 6F , baseR / 6F)

canvas.drawArc(rectf2 , 0F , 360F , true , paint)

canvas.restore()

canvas.rotate(-45F)

canvas.save()

val bottomBaseR = baseR / 0.9F / 2

val path = Path()

path.moveTo(-bottomBaseR , 0F)

path.cubicTo(-bottomBaseR , bottomBaseR * 2, bottomBaseR  , bottomBaseR * 2, bottomBaseR , 0F)

path.cubicTo(

bottomBaseR * C,bottomBaseR ,

-bottomBaseR * C,bottomBaseR ,

-bottomBaseR , 0F

)

//绘制星球背景的阴影效果

paint.color = 0xffAAEEF2.toInt()

paint.style = Paint.Style.FILL

canvas.drawPath(path , paint)

//绘制星球的地貌

drawPoints(index , canvas)

canvas.restore()

paint.strokeWidth = 30F

paint.color = 0xff2F3768.toInt()

paint.style = Paint.Style.STROKE

canvas.drawArc(rectf , 0F , 360F , true , paint)

return bm

}

private fun drawPoints(index: Float, canvas: Canvas) {

val paintB = Paint()

val paintS = Paint()

paintS.style = Paint.Style.FILL

paintS.color = 0xffE7F2FB.toInt()

paintB.style = Paint.Style.FILL

paintB.color = 0xff2F3768.toInt()

val baseRB = baseR / 2F / 3

val baseRS = baseR / 2F / 3 / 3

val rectfB = RectF(-baseRB, -baseRB, baseRB, baseRB)

val rectfS = RectF(-baseRS, -baseRS, baseRS, baseRS)

val pointPaint = Paint()

pointPaint.color = Color.BLACK

pointPaint.strokeWidth = 50F

val coverWidth = baseR

//通过移动坐标原点模拟星球的自转效果

canvas.translate(-coverWidth / 2F , coverWidth * 1.5F)

val index = index

canvas.translate(0F , coverWidth * index )

//重复绘制三次星球的地貌使得星球的自转无缝连接

for (i in 0..2){

canvas.save()

canvas.translate(coverWidth / 3F / 2  , -coverWidth / 3F * 2)

canvas.drawArc(rectfB , 0F , 360F , true , paintB)

canvas.drawArc(rectfS , 0F , 360F , true , paintS)

canvas.restore()

canvas.save()

canvas.translate(coverWidth / 3F *2 , -coverWidth / 3F)

canvas.drawArc(rectfB , 0F , 360F , true , paintB)

canvas.drawArc(rectfS , 0F , 360F , true , paintS)

canvas.restore()

canvas.save()

canvas.translate(coverWidth / 3F *2 , -coverWidth / 8F * 7 + -coverWidth / 10F )

canvas.drawArc(rectfS , 0F , 360F , true , paintB)

canvas.restore()

canvas.save()

canvas.translate(coverWidth / 3F *2 , -coverWidth / 8F * 7  - -coverWidth / 10F )

canvas.drawArc(rectfS , 0F , 360F , true , paintB)

canvas.restore()

canvas.translate(0F , -coverWidth)

}

}

android动画 行星,AndroidAnimation相关推荐

  1. android动画 行星,Android自定义View之星球运动

    Android自定义View之星球运动 欢迎大家访问我的个人博客 在dribbble闲逛的时候发现的一个有意思的星球运动的动画,刚好最近时间尚可,就简单实现了一下中间运动的部分,又是因为时间的原因,开 ...

  2. Android动画-Animation原理解析

    Android动画-Animation原理解析 一.概述 在android中动画分为3类,帧动画.补间动画.属性动画 今天要说的就是"补间动画",补间动画的基类是Animation ...

  3. Android动画效果translate、scale、alpha、rotate详解

    动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面 ...

  4. android jason动画,Android 动画之Lottie动画使用

    Android 动画之Lottie动画使用 一:简介 Lottie是Airbnb开源的一套跨平台的完整解决方案,设计师只需要使用After Effects(简称AE)设计动画之后,使用Lottic提供 ...

  5. android动画的实现原理,Android动画的实现原理 .

    1.动画运行模式 独行模式 中断模式 2.Animation类 每个动画都重载了父类的applyTransformation方法这个方法的主要作用是把一些属性组装成一个Transformation类, ...

  6. Android动画曲线库AndroidEasingFunctions

    Android动画曲线库AndroidEasingFunctions AndroidEasingFunction是基于Easing Function(缓动函数)的Android动画曲线库.它提供了九大 ...

  7. android 动画引擎,一个使用openGL渲染的炫丽Android动画库

    这是一个 android 动画特效库 可以实现各种炫酷动画. github地址: ht t ps:// gith  u b.co m/g pl ib s/an dro id- ma gic-s ur ...

  8. Android 动画分析学习笔记

    一:分类: Android动画分三种:view动画(对场景中的对象不断做图像变换<平移,缩放,旋转,透明度>).帧动画(顺序播放一系列图像产生动画效果).属性动画(动态改变对象属性). 二 ...

  9. Android动画之Tween动画实战

    Android动画分为Tween动画和Frame动画,上一节通过一个实例介绍了Frame动画,本节将介绍Tween动画.Tween可以把对象进行缩小.放大.旋转和渐变等操作. Tween动画有四个主要 ...

最新文章

  1. 我觉得有不少人被Spring带着跑偏了!
  2. tensorflow随笔-tf.no_op
  3. 关于MSSQL数据存储的问题
  4. 班级日常分享:一天一瞬间!
  5. uni-app运行编译报错
  6. CentOS 7下sshd防暴力破解及fail2ban的使用方法
  7. 澳门智能公交调度系统客户端GUI设计
  8. (Python)BiliBili(手机端缓存视频转换)
  9. HDLC和PPP协议的配置
  10. Android开发丶基于高德地图实现定位、搜索定位、绘制圆圈自定义图标及改变圆圈半径等功能
  11. 几何线条科技感员工转正述职报告PPT模板-优页文档
  12. 怎样在家远程访问单位的电脑 如何利用远程桌面进行远程办公 3款软件测评
  13. c++名字空间指令与名字空间声明
  14. Navicat Premium 注 册 码
  15. Spring Boot配置定时任务
  16. 等比数列等差数列求和
  17. spark java mysql 连接数据库_Spark入门:通过JDBC连接数据库(DataFrame)
  18. 【谨慎学习】手把手教你破解网站管理后台帐号密码
  19. SEO学习心得:分享总结学习SEO的心得
  20. mybatis批量修改操作示例

热门文章

  1. android开发中中按钮 变成红边白底,PS人像换红底为白底等的处理
  2. 如何在 HTML 网站上创建其他网页
  3. android uyghur app,‎App Store 上的“Uyghur Quran And Translation”
  4. 易經大意(6) 三和 韓長庚 著
  5. Debian10.12安装oracle11g(亲测有效)
  6. 思科交换机配置:三层交换机技术
  7. 学校计算机教室 计划总结怎么写,学校信息技术教师的工作总结范文
  8. 计算机在职研究生的详细介绍
  9. 利用Web查询文件(.iqy)有效钓鱼
  10. SQL中的PROCEDURE