美文网首页
Android实现抖音心形函数

Android实现抖音心形函数

作者: JimmieYang | 来源:发表于2019-02-02 15:50 被阅读91次

    刷抖音的时候,无意间刷到 心形函数的动画,觉得很有意思, 就简单的用Android的方式实现了一下.

    心形函数公式

    公式 :

    心形公式

    X的取值范围:[-1.81,1.81],该取值范围是保证正弦函数有效取值范围。

    我们可以通过参数 a 的取值, 来形成不同的心形轮廓, 进而形成动画效果.

    有了以上的认识,我们就是可开始编写Android代码了.

    Android实现

    代码使用 Kotlin来编写自定义View.个人觉得 只有心还不够, 动画结束需要逐渐显示文字,来达到表白的效果.

    先看动画效果:


    heart.gif

    然后贴上代码实现:

    class HeartView(context: Context, attrs: AttributeSet) : BaseView(context, attrs),
        ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
    
        var text = "Hello Android"
    
        private val animator = ValueAnimator.ofInt(3_000)
        private val path = Path()
        private var heartDrawing = false
        private var heart = 0.1f
        private var pct = 0f
    
        init {
            paint.strokeWidth = 4 * dp
            paint.textSize = 30 * dp
            paint.textAlign = Paint.Align.CENTER
    
            animator.interpolator = LinearInterpolator()
            animator.addUpdateListener(this)
            animator.addListener(this)
        }
    
        fun startHeart() {
            heartDrawing = true
            animator.cancel()
            animator.duration = 3_000
            animator.start()
        }
    
        override fun onDraw(canvas: Canvas) {
            path.reset()
            paint.color = Color.RED
            paint.style = Paint.Style.STROKE
    
            val padding = 20
            val halfWidth = width / 2 - padding
            val halfHeight = height / 2
            // 根据X坐标,计算出Y坐标, 将其映射到屏幕坐标后,用path连接
            for (index in 0..(width - padding * 2)) {
                val x = (index - halfWidth) * 1.81 / halfWidth
                val y = -getHeartY(x, heart) * height / 6 + halfHeight
                if (index == 0) {
                    path.moveTo(index.toFloat() + padding, y.toFloat())
                } else {
                    path.lineTo(index.toFloat() + padding, y.toFloat())
                }
            }
            canvas.drawPath(path, paint)
    
            // 结束后写文字
            if (!heartDrawing) {
                val textWidth = paint.measureText(text)
                val left = width / 2f - textWidth / 2f
                val top = height * 0.4f - 0.9f * paint.textSize
    
                canvas.clipRect(left, top, left + textWidth * pct, top + 1.2f * paint.textSize)
    
                paint.color = Color.WHITE
                paint.style = Paint.Style.FILL
                canvas.drawText(text, width / 2f, height * 0.4f, paint)
            }
        }
    
        private fun getHeartY(x: Double, a: Float): Double {
            return Math.pow(x * x, 1.0 / 3) + 0.9 * Math.sqrt(3.3 - x * x) * Math.sin(a * Math.PI * x)
        }
    
    
        override fun onAnimationUpdate(animation: ValueAnimator) {
            val value = animation.animatedValue as Int
            if (value == 0) return
            if (heartDrawing) heart = value * 0.01f
            else {
                pct = value / 3000f
            }
            invalidate()
        }
    
        override fun onDetachedFromWindow() {
            animator.cancel()
            animator.removeAllUpdateListeners()
            animator.removeAllListeners()
            super.onDetachedFromWindow()
        }
    
        override fun onAnimationEnd(animation: Animator?) {
            if (heartDrawing) {
                heartDrawing = false
    
                animation?.duration = 3_000
                animation?.start()
            }
        }
    
        override fun onAnimationStart(animation: Animator?) {
        }
    
        override fun onAnimationRepeat(animation: Animator?) {
        }
    
        override fun onAnimationCancel(animation: Animator?) {
        }
    }
    

    这样就实现了, 是不是觉得很简单.

    相关文章

      网友评论

          本文标题:Android实现抖音心形函数

          本文链接:https://www.haomeiwen.com/subject/efissqtx.html