Imitation wechat chat fried "shit" effect!! Ah, just play!

Long Long Ago, wechat 8.0 has updated a new function of "frying shit", which is quite new.

Chatting with friends these two days triggered this function. At that time, I thought, ah! Isn't this article material coming?! Take advantage of the weekend to realize it.

Let's take a look at the overall implementation effect:

This article has no technical content and is purely entertainment

thinking

After continuous experiments, I checked the wechat bombing again and again 💩 Basically, it can be disassembled into several small parts.

  • Select the bomb expression. After sending, the bomb will be sent to the other party in the form of parabola, and 💣 Will flip;
  • stay 💣 meet 💩 When the expression, the explosion animation appears;
  • While the animation explodes, there are about 7 💩 The expression, facing randomly, makes the amplification effect, and finally moves down and disappears gradually.

The effect has been disassembled, and the specific technical realization ideas are as follows:

  • The IM chat interface is mainly divided into sender and receiver type s by Recyclerview;
  • The effect of bomb parabola is realized by Bessel curve. Here, the second-order Bessel curve can be used;
  • Use animation to rotate while the bomb is thrown;
  • Lottie achieves explosion effect;
  • Zoom, pan and gradient animation 💩 The explosion effect.

Concrete implementation

IM chat interface

Im chat interface is very simple. A Recyclerview is divided into left and right types. According to the type value, load the layout on the left and right respectively.

class ImAdapter  : BaseDelegateMultiAdapter<ImMsg?, BaseViewHolder>(){
    companion object {
        private const val TAG = "ImMsgAdapter"
        private const val TYPE_LEFT = 0
        private const val TYPE_RIGHT = 1
    }

    init {
        setMultiTypeDelegate(object : BaseMultiTypeDelegate<ImMsg?>() {
            override fun getItemType(data: List<ImMsg?>, position: Int): Int {

                if (data[position]?.type == 0) {
                    return TYPE_LEFT
                }
                return TYPE_RIGHT
            }
        })
        Objects.requireNonNull(getMultiTypeDelegate())!!
            .addItemType(TYPE_LEFT, R.layout.item_im_left)
            .addItemType(TYPE_RIGHT, R.layout.item_im_right)
    }

    override fun convert(holder: BaseViewHolder, item: ImMsg?) {

        if (holder.itemViewType == TYPE_LEFT) {
            holder.setText(R.id.tv_chat_left_msg,item?.msg)
        } else {
            holder.setText(R.id.tv_chat_right_msg,item?.msg)
        }

    }
}

Here, an entity class ImMsg is created to simulate chat data.

data class ImMsg(val type:Int,val msg:String)


//Initialize chat information and simulate data
val msgList = mutableListOf<ImMsg>()
msgList.add(ImMsg(0, "Hello!"))
msgList.add(ImMsg(0, "Let's test it"))
msgList.add(ImMsg(0, "Wechat explosion effect"))
msgList.add(ImMsg(1, "Oh!"))
msgList.add(ImMsg(0, "\uD83D\uDE14"))
msgList.add(ImMsg(0, "\uD83D\uDCA9"))
msgList.add(ImMsg(0, "\uD83D\uDCA9"))
msgList.add(ImMsg(0, "\uD83D\uDCA9"))

val adapter = ImAdapter()
imRv.adapter = adapter
adapter.addData(msgList)

Of course, the chat interface also needs to add an input box and an expression bar, which will not be displayed one by one here.

Send bomb 💣

After the chat interface is set up, we start to get to the point, starting with throwing bombs.

As has been analyzed above, the process of dropping a bomb is actually a parabolic process, starting from the chat on the right to the left 💩 end.

Seeing the process of dropping a bomb, the first reaction is to use Bessel curve to solve the problem of bomb route. The route of the bomb is relatively simple, which can be realized here by using second-order Bessel curve.

As we all know, to realize the second-order Bezier curve, we must know the data of at least two points, one is the control point and the other is the coordinates of the end point.

From the above figure, we can basically know that the control point is located above the middle of the start point and the end point. Here, the control point is simulated based on the screen width and height.

val resources: Resources = this.resources
val dm: DisplayMetrics = resources.displayMetrics
val scWidth = dm.widthPixels
val scHeight = dm.heightPixels
val controlX : Int = scWidth/2 - 400//Control point x
val controlY : Int = scHeight/2 - 400//Control point y

In the same way as the end point, take the starting point as the reference value to calculate the coordinates

val lastX = ivBomb.x-200
val lastY = ivBomb.y-800

If you have the coordinates of the control point and the end point, you can start drawing the second-order Bezier curve to realize the Bezier curve. There is already a ready-made API in Android. There is a quadTo method in Path. As long as you pass in the coordinates of the control point and the end point, you can generate the Bezier curve Path.

path.quadTo(
    -controlX,
    -controlY,
    -lastX,
    -lastY
)

With path, the next step is to move the bomb according to Bessel curve. Here, attribute animation and PathMeasure are needed to make the bomb move 💣 Follow the path.

pathMeasure = PathMeasure(path, false)
valueAnimator = ValueAnimator.ofFloat(0f, pathMeasure.length)
valueAnimator.duration = MILLS + 100
valueAnimator.interpolator = LinearInterpolator()
valueAnimator.addUpdateListener { animation ->
    val animatedValue = animation.animatedValue as Float
    pathMeasure.getPosTan(animatedValue, mCurrentPosition, null)
    ivBomb.translationX = mCurrentPosition[0]
    ivBomb.translationY = mCurrentPosition[1]
    ivBomb.rotation = animatedValue
}

The bomb of wechat has a continuous overturning effect while parabola.

Then we only need to monitor the update listener of the attribute animation. In the process of monitoring the movement, set the rotation to make the bomb flip continuously.

Let's look at the effect:

Explosion effect

The next step is the explosion effect of the bomb. The scheme given here is to use the Lottie library to load. The explosion effect of wechat is still very realistic. I haven't found the corresponding material for a long time. It's true and can't be simulated here.

So from https://lottiefiles.com/ A json file similar to the explosion effect is found in the resource library, and the explosion effect is realized in combination with Lottie.

Lottie is also easy to use, adding dependencies

implementation 'com.airbnb.android:lottie:3.4.0'

Add lottieanimation view in layout

<com.airbnb.lottie.LottieAnimationView
    android:id="@+id/lottie_layer_view"
    android:layout_width="200dp"
    android:layout_height="200dp"
    app:layout_constraintBottom_toTopOf="@id/cl_ed_send"
    android:layout_marginBottom="140dp"/>

At the end of the bomb execution parabola, play begins

mLottieAnimation?.playAnimation()

Let's see the overall effect of bomb combined with explosion

💩 Explosion effect

When the bomb exploded, there was a 💩 The effect of being blown open is shown below.

From the perspective of wechat effect, there are 7 💩 And each expression tilts at a random angle, starting from the explosion animation, pops up from small to large, forming a far and near effect.

The implementation scheme is to draw 7 identical expression maps from the user-defined View, rotate the angle randomly by Math.random, and place the 7 expressions randomly within the controllable range.

//At the beginning of the explosion, there are 7 pictures randomly, and the rotation angle is random
for (i in 0..6) {
    dst?.let {
        it.left = i * 50 + 150
        it.top = mHeight + (Math.random() * 400).toInt() - mHeight / 4
        it.right = it.left + 100
        it.bottom = it.top + 100
    }
    
    val matrix = Matrix()
    matrix.postScale(i.toFloat() + 4, i.toFloat() + 4)
    matrix.postTranslate((-bitmap.width / 2).toFloat(), (-bitmap.height / 2).toFloat())
    matrix.postRotate((Math.random() * 70).toFloat())
    matrix.postTranslate(dst!!.top.toFloat(), dst!!.left.toFloat())
    val bitmap1 =
        Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    canvas.drawBitmap(bitmap1, null, dst!!, paint)
    matrix.reset()
}

As for the effect from far to near, you need to zoom and animate the custom Baba View.

val scaleXAni = ObjectAnimator.ofFloat(baView, "scaleX", 0f, 1.8f)
val scaleYAni = ObjectAnimator.ofFloat(baView, "scaleY", 0f, 1.5f)

In addition, in 💩 At the end of the explosion, 💩 It moves down and the gradient is transparent at the same time, so start panning the animation after zooming the animation
translation and gradient animation alpha.

val tranY1Ani = ObjectAnimator.ofFloat(baView, "translationY", 0f, -300f)
val tranYAni = ObjectAnimator.ofFloat(baView, "translationY", -300f, 300f)
val alphaAni = ObjectAnimator.ofFloat(baView, "alpha", 1f, 0f)

Finally, use AnimatorSet to set the animation and start playing.

val animatorSet = AnimatorSet()
animatorSet.play(scaleXAni).with(scaleYAni).with(tranY1Ani).before(tranYAni)
    .before(alphaAni)

Look at the effect.

Basically, each disassembled part has been realized. Now start to combine the IM interface, bomb parabola, explosion effect and final explosion effect.

Finally, the effects are as follows:

At the moment of the bomb explosion, the user's Avatar and expression will shake. It's not realized here. Interested partners can try it.

Well, that's all for this article. I think it's OK. I can give you three companies!

Recommended reading:

Play Compose, the original God theme list
Here comes the Compose version! Imitation free naked eye 3D effect

Easter egg

A few days ago, I successfully applied to the periphery of the Nuggets. Let's open a lucky draw under this article. Thank the nuggets for their official support.

Lottery method:

As of September 10, if more than 10 people interact in the comment area (excluding myself), the top two lucky viewers will be selected from the popular comment area and sent out a "Nuggets badge" respectively. (Note: those who brush their own comments are not included)

Lottery time: 12:00 noon on September 11

Tags: Android kotlin wechat

Posted on Sun, 12 Sep 2021 15:07:52 -0400 by omniuni