Android贝塞尔曲线应用-跳动的水滴

jumpWater

主要通过6个控制点实现。

val startPoint = PointF()
val endPoint = PointF()
val control1 = PointF()
val control2 = PointF()
val control3 = PointF()
val control4 = PointF()

control point

绘制过程:

private fun drawWater(canvas: Canvas) {
    waterPath.apply {
        reset()
        moveTo(startPoint)
        cubicTo(control1, control3, endPoint)
        cubicTo(control4, control2, startPoint)
    }
    canvas.save()
    // clipOut 出中间的圆
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        canvas.clipOutPath(Path().apply { addCircle(circleX, circleY, circleR, Path.Direction.CW) })
    } else {
        canvas.clipPath(Path().apply {
            addCircle(circleX, circleY, circleR, Path.Direction.CW)
        }, Region.Op.DIFFERENCE)
    }
    canvas.drawPath(waterPath, waterPaint)
    canvas.drawCircle(circleX, circleY, circleR, waterPaint)
    canvas.restore()
}

一些扩展函数,方便直接使用 PointF。

private fun Path.moveTo(p: PointF) {
    moveTo(p.x, p.y)
}
private fun Path.lineTo(p: PointF) {
    lineTo(p.x, p.y)
}
private fun Path.cubicTo(control1: PointF, control2: PointF, end: PointF) {
    cubicTo(control1.x, control1.y, control2.x, control2.y, end.x, end.y)
}
private fun Path.quadTo(control: PointF, end: PointF) {
    quadTo(control.x, control.y, end.x, end.y)
}
private fun Canvas.drawPoint(p: PointF, paint: Paint) {
    drawPoint(p.x, p.y, paint)
}

动画

分为 6 个阶段完成

class AnimatorHelper(val target: JumpWater) {

    private var animDuration = 300L
    private var animStartDown: ValueAnimator? = null
    private var animStartJump: ValueAnimator? = null
    private var animJump: ValueAnimator? = null
    private var animDown: ValueAnimator? = null
    private var animTail: ValueAnimator? = null
    private var animTailReconver: ValueAnimator? = null
    private var animSet: AnimatorSet? = null

    internal fun startJump(tailMove: Float, jumpH: Float) {
        endJump()
        animStartDown = ValueAnimator.ofFloat(0f, jumpH).apply {
            addUpdateListener {
                target.updateStartDown(it.animatedValue as Float)
            }
        }
        animStartJump = ValueAnimator.ofFloat(jumpH, 0f).apply {
            addUpdateListener {
                target.updateStartDown(it.animatedValue as Float)
            }
        }
        animJump = ValueAnimator.ofFloat(0f, jumpH).apply {
            addUpdateListener {
                target.updateJump(it.animatedValue as Float)
            }
        }
        animDown = ValueAnimator.ofFloat(jumpH, 0f).apply {
            addUpdateListener {
                target.updateJump(it.animatedValue as Float)
            }
        }
        animTail = ValueAnimator.ofFloat(0f, tailMove).apply {
            addUpdateListener {
                target.updateTail(it.animatedValue as Float)
            }
        }
        animTailReconver = ValueAnimator.ofFloat(tailMove, 0f).apply {
            addUpdateListener {
                target.updateTail(it.animatedValue as Float)
            }
        }

        val tailSet = AnimatorSet().apply {
            playTogether(animJump, animTail)
        }

        val tailSetReconver = AnimatorSet().apply {
            playTogether(animDown, animTailReconver)
        }

        animSet = AnimatorSet().apply {
            playSequentially(animStartDown, animStartJump, tailSet, tailSetReconver)
            addListener(object : Animator.AnimatorListener {
                override fun onAnimationRepeat(animation: Animator?) {

                }

                override fun onAnimationEnd(animation: Animator?) {
                    mOnAnimEndListener?.onAnimEnd()
                }

                override fun onAnimationCancel(animation: Animator?) {
                }

                override fun onAnimationStart(animation: Animator?) {
                }
            })
            start()
        }
    }
}

具体请看:https://github.com/stefanJi/AndroidView/tree/master/jumpwater

posted @ 2018-10-05 20:07  just_yang  阅读(1862)  评论(0编辑  收藏  举报