A, inspiration

The inspiration for this particle animation library came from the animation when MIUI uninstalled the application:

The exploding particle effect looks cool, and the particle color is taken from icon.

I started with a simple, exploding effect, but then I thought I could extend it and write a general purpose particle animation library.

Second, the use of

Project address: github.com/ultimateHan…

Particle is a library of Particle animations written in Kotlin. You can easily animate a Particle in just a few lines of code. It also supports highly customized particle animation tracks, which can create a very cool custom animation. This project has released version 0.1 on the JitPack and is introduced as follows:

Add (note not buildScript) to allProjects in build.gradle in the root directory:

allprojects {
	repositories {
		...
		maven { url 'https://jitpack.io'}}}Copy the code

Then introduce dependencies into your project.

Implementation 'com. Making. UltimateHandsomeBoy666: Particle: 0.1'Copy the code

With Particle introduced, the above Particle explosion effect can be achieved with a few simple lines of code:

Particles.with(context, container) // Container is the host parent ViewGroup of the particle animation
		.colorFromView(button)// Sample color from button
		.particleNum(200)// A total of 200 particles
		.anchor(button)// Use button as the anchor point for the animation
		.shape(Shape.CIRCLE)// The particle shape is round
		.radius(2.6)// Particle random radius 2~6
		.anim(ParticleAnimation.EXPLOSION)// Use the explosion animation
		.start()
Copy the code

Three, particle shape

Particle shape support circle, triangle, rectangle, five-pointed star and vector graphics and bitmaps, and support a variety of graphics particle mix.

Detailed below.

Shape.CIRCLEShape.HOLLOWCIRCLE

  • Circular and hollow circles

  • Use RADIUS to define the size of the circle. A hollow circle uses strokeWidth to define its thickness.

Shape.TRIANGLEShape.HOLLOWTRIANGLE

  • Solid triangle and hollow triangle

  • Use width and height to define the size of the triangle. Hollow triangles use strokeWidth to define thickness.

Shape.RECTANGLEShape.HOLLOWRECTANGLE

  • Solid rectangle and hollow rectangle.

  • Define the size of the rectangle using width and height. Hollow rectangles use strokeWidth to define their thickness.

Shape.PENTACLEShape.HOLLOWPENTACLE

  • Solid pentacle and hollow pentacle

  • Use RADIUS to define the size of the pentagram circle. A hollow pentacle uses strokeWidth to define the thickness.

Shape.BITMAP

  • Support for bitmaps.

  • To support vector graph, just pass in the resource ID of vector graph XML.

  • Image particles are not affected by the color setting.

In addition to the above single graph, it also supports mixed particles of a variety of graphs, as follows:

4. Particle animation

The animation control

Particle animation is controlled using ValueAnimator. We can define animator to control animation behavior, including animation length, Interpolater, repetition, start and end listener, etc.

Particle effects

Currently only the rotation of particles in motion is supported, as shown below. More will be added later

Particle trajectories

Particle trajectory control is done using a derived class of the IPathGenerator interface. There are four trajectory animations in the library, which are:

  • ParticleAnimation.EXPLOSIONExplosion 💥 effect
  • ParticleAnimation.RISEParticle rise
  • ParticleAnimation.FALLParticles falling
  • ParticleAnimation.FIREWORKFireworks 🎇 effect

If you want to customize the particle trajectory, you can inherit the IPathGenerator interface and copy the method of generating particle coordinates:

private fun createPathGenerator(a): IPathGenerator {
  // The LinearPathGenerator is built-in in the library
        return object : LinearPathGenerator() {
            val cos = Random.nextDouble(-1.0.1.0)
            val sin = Random.nextDouble(-1.0.1.0)

            override fun getCurrentCoord(progress: Float, duration: Long): Pair<Int.Int> {
              // Write the desired particle trajectory here
                val originalX = distance * progress
                val originalY = 100 * sin(originalX / 50)
                val x = originalX * cos - originalY * sin
                val y = originalX * sin + originalY * cos
                return Pair((0.01 * x * originalY).toInt(), (0.008 * y * originalX).toInt())
            }
        }
    }
Copy the code

Then pass the method that returns IPathGenerator in the form of a higher-order function:

particleManager!! .colorFromView(button) .particleNum(300)
                .anchor(it)
                .shape(Shape.CIRCLE, Shape.BITMAP)
                .radius(8.12)
                .strokeWidth(10f)
                .size(20.20)
                .rotation(Rotation(600))
                .bitmap(R.drawable.ic_thumbs_up)
                .anim(ParticleAnimation.with({
                  // The animator that controls the animation
                    createAnimator()
                }, {
                  // The trajectory of the particle
                    createPathGenerator()
                })).start()
Copy the code

The ParticleAnimation.with method in the above code accepts two higher-order functions to generate the animation control and particle trajectory, respectively.

fun with(animator: () -> ValueAnimator = DEFAULT_ANIMATOR_LAMBDA,
        generator: () -> IPathGenerator): ParticleAnimation {
    return ParticleAnimation(generator, animator)
}
Copy the code

Finally, after the above, you can get the following cool motion pictures:

Of course, you can construct as many particle animation tracks as you want, but this may require a little math at 🐶.

In github.com/ultimateHan… There’s a cool collection of trajectory formulas I’ve experimented with in the directory for your reference.

5. Matters needing attention

  • Particle animations are memory and CPU intensive, so if you have too many particles, say more than 1000, you may get stuck.
  • By default, particles do not disappear when the animation is over. If you want the particle to disappear at the end of the animation, you can customize itValueAnimatorListen for the end of the animation and call at the endParticleManager.hide()Method to hide the particles.
  • If you need to trigger a particle animation repeatedly, such as by pressing a button once, you can use a globalparticleManagerVariables to start and unanimate particles to avoid memory consumption and memory jitter. Such as:
particleManager = Particles.with(this, container) button.setOnClickListener { particleManager!! .colorFromView(button) .particleNum(300)
                      .anchor(it)
                      .shape(Shape.CIRCLE, Shape.BITMAP)
                      .radius(8.12)
                      .rotation(Rotation(600)) .anim(ParticleAnimation.EXPLOSION) particleManager!! .start() }Copy the code

Six, the last

Except for the first version, this project is also my first open source release project, and I will spend some time and energy to maintain it.

  • More particle effects will be added, such as changes in size, transparency, and color as the particles move
  • A version of compose, 🐶, may follow

Finally, github.com/ultimateHan… The project address is here, welcome fork, PR, issues, star, please point a little star ✨❤️, thank you!