篇首语:本文由小编为大家整理,主要介绍了实战演练!二阶贝塞尔仿微信扔炸弹动画相关的知识,希望对你有一定的参考价值。
前言
新出来的微信炸屎动画很多人都玩过了,所以先仿照一个微信扔炸弹的动画,在后续有时间会做一个完整的,效果如下:
具体实现
其中最麻烦的就是绘制抛物线了,爆炸的效果只是播放了一个动画,另外微信貌似都是通过代码绘制的,可能不是动画,奈何没有人家那技术,只能找一张动画来凑合。
二阶贝塞尔曲线
抛物线在这里是通过二阶贝塞尔曲线来完成,所以先来了解下什么是二阶贝塞尔曲线,从下图中可以发现,二阶贝塞尔曲线有三个关键点,我们可以称作起点坐标、终点坐标,还有控制点。
起点和终点坐标好理解,控制点可以理解成开始下降的转折点,而古老的数学大神早就提供好了公式,我们只需要向这个公式提供这几个参数即可得到x、y,当然还有个参数是时间,有了时间控制,我们可以在指定秒内把他平滑的绘制完成。
公式如下:
x = (1 - t)^2 * 0 + 2 t (1 - t) * 1 + t^2 * 1 = 2 t (1 - t) + t^2y= (1 - t)^2 * 1 + 2 t (1 - t) * 1 + t^2 * 0 = (1 - t)^2 + 2 t (1 - t)
自定义二阶贝塞尔曲线计算器
提到动画,首先可能会想到ObjectAnimator类,没错,抛物线也是通过ObjectAnimator来完成的,只不过我们需要自定义一个TypeEvaluator,用来提供二阶贝塞尔曲线的x和y。
TypeEvaluator只有一个方法,定义如下:
public abstract T evaluate (float fraction, T startValue, T endValue)复制代码
fraction表示开始值和结束值之间的比例,startValue、endValue分别是开始值和结束值,这个比例也可以当作是时间,可能官方一点叫比例,他会自动计算,值的范围是0-1,比如取值0.5的时候就是动画完成了一半,1的时候动画完成。
所以套入二阶贝塞尔曲线公式得到如下代码:
class PointFTypeEvaluator(var control: PointF) : TypeEvaluator override fun evaluate(fraction: Float, startValue: PointF, endValue: PointF): PointF return getPointF(startValue, endValue, control, fraction) private fun getPointF(start: PointF, end: PointF, control: PointF, t: Float): PointF val pointF = PointF() pointF.x = (1 - t) * (1 - t) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x pointF.y = (1 - t) * (1 - t) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y return pointF 复制代码
播放动画
然后使用ObjectAnimator进行播放。
val animator = ObjectAnimator.ofObject(activityMainBinding.boom, "mPointF", PointFTypeEvaluator(controlP), startP, endP)复制代码
注意的是这个View需要有point方法,参数是PointF,方法内主要完成x和y的设置。
public void setPoint(PointF pointF) setX(pointF.x); setY(pointF.y); 复制代码
当然微信炸弹落地的位置是随机的,我们也加个随机。
class MainActivity : AppCompatActivity() lateinit var binding: ActivityMainBinding; private fun getRandom(max: Int, min: Int): Int val random = java.util.Random() return random.nextInt(max - min + 1) + min private fun getRandomPointF():PointF val outMetrics = DisplayMetrics() val offset = 100 windowManager.defaultDisplay.getMetrics(outMetrics) val width = outMetrics.widthPixels val height = outMetrics.heightPixels return PointF(getRandom(width / 2 + offset, width / 2 - offset).toFloat(), getRandom(height / 2 + offset, height / 2 - offset).toFloat()) override fun onCreate(savedInstanceState: Bundle?) super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.button.setOnClickListener binding!!.boom.visibility = View.VISIBLE val startP = PointF() val endP = PointF() val controlP = PointF() val randomPointF = getRandomPointF() startP.x = 916f startP.y = 1353f endP.x = randomPointF.x endP.y = randomPointF.y controlP.x = randomPointF.x + getRandom(200, 50) controlP.y = randomPointF.y - getRandom(200, 50) val animator = ObjectAnimator.ofObject(binding.boom, "point", PointFTypeEvaluator(controlP), startP, endP) animator.start() 复制代码
android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> 复制代码
效果如下:
爆炸效果
爆炸效果是使用的动画,用的lottie框架,这里提供爆炸文件的下载地址。
https://lottiefiles.com/download/public/9990-explosion复制代码
有了结束的坐标点,只需要吧LottieAnimationView移动到对应位置进行播放即可,播放后隐藏,完整代码如下:
package com.example.kotlindemoimport android.animation.Animatorimport android.animation.ObjectAnimatorimport android.content.Contextimport android.content.Intentimport android.graphics.BitmapFactoryimport android.graphics.PointFimport android.media.projection.MediaProjectionManagerimport android.os.Buildimport android.os.Bundleimport android.util.DisplayMetricsimport android.view.Menuimport android.view.MenuItemimport android.view.Viewimport android.widget.Toastimport androidx.appcompat.app.AppCompatActivityimport androidx.databinding.DataBindingUtilimport com.example.kotlindemo.databinding.ActivityMainBindingimport com.example.kotlindemo.widget.PointFTypeEvaluatorimport meow.bottomnavigation.MeowBottomNavigationimport kotlin.random.Randomclass MainActivity : AppCompatActivity() lateinit var binding: ActivityMainBinding; private fun getRandom(max: Int, min: Int): Int val random = java.util.Random() return random.nextInt(max - min + 1) + min private fun getRandomPointF():PointF val outMetrics = DisplayMetrics() val offset = 100 windowManager.defaultDisplay.getMetrics(outMetrics) val width = outMetrics.widthPixels val height = outMetrics.heightPixels return PointF(getRandom(width / 2 + offset, width / 2 - offset).toFloat(), getRandom(height / 2 + offset, height / 2 - offset).toFloat()) override fun onCreate(savedInstanceState: Bundle?) super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding!!.button.setOnClickListener binding!!.boom.visibility = View.VISIBLE val startP = PointF() val endP = PointF() val controlP = PointF() val randomPointF = getRandomPointF() startP.x = 916f startP.y = 1353f endP.x = randomPointF.x endP.y = randomPointF.y controlP.x = randomPointF.x + getRandom(200, 50) controlP.y = randomPointF.y - getRandom(200, 50) val animator = ObjectAnimator.ofObject(binding.boom, "point", PointFTypeEvaluator(controlP), startP, endP) animator.duration = 600 animator.addListener(object : Animator.AnimatorListener override fun onAnimationStart(animation: Animator) override fun onAnimationEnd(animation: Animator) val measuredHeight = binding.lottie.measuredHeight val measuredWidth = binding.lottie.measuredWidth binding.lottie.x = randomPointF.x - measuredWidth / 2 binding.lottie.y = randomPointF.y - measuredHeight / 2 binding.lottie.visibility = View.VISIBLE binding.boom.visibility = View.GONE binding.lottie.playAnimation() binding.lottie.addAnimatorListener(object : Animator.AnimatorListener override fun onAnimationStart(animation: Animator) override fun onAnimationEnd(animation: Animator) binding.lottie.visibility = View.GONE override fun onAnimationCancel(animation: Animator) override fun onAnimationRepeat(animation: Animator) ) override fun onAnimationCancel(animation: Animator) override fun onAnimationRepeat(animation: Animator) ) animator.start() 复制代码
本文在开源项目:https://github.com/Android-Alvin/Android-LearningNotes 中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
以上是关于实战演练!二阶贝塞尔仿微信扔炸弹动画的主要内容,如果未能解决你的问题,请参考以下文章