Android 学习之自定义动画运用贝赛尔曲线

**

1:贝赛尔曲线简介

**
贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线 。 贝塞尔曲线的有趣之处更在于它的“皮筋效应”,也就是说,随着点有规律地移动,曲线将产生皮筋伸引一样的变换,带来视觉上的冲击。
曲线定义: 定义好起始点、终止点(也称锚点)、控制点,控制点可以有多个,每个节点均可编辑。通过调整控制点,贝塞尔曲线的形状会发生变化。
参考博客
以下公式中:B(t)为t时间下 点的坐标;
P0为起点,Pn为终点,Pi为控制点,i为1-n
一阶贝塞尔曲线(线段):
在这里插入图片描述在这里插入图片描述

意义:由 P0 至 P1 的连续点, 描述的一条线段

二阶贝塞尔曲线(抛物线):
在这里插入图片描述在这里插入图片描述

原理:
由 P0 至 P1 的连续点 Q0,描述一条线段。
由 P1 至 P2 的连续点 Q1,描述一条线段。
由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

经验:P1-P0为曲线在P0处的切线。

三阶贝塞尔曲线:
在这里插入图片描述
在这里插入图片描述

通用公式:
在这里插入图片描述

高阶贝塞尔曲线:
4阶曲线:

在这里插入图片描述

5阶曲线:
在这里插入图片描述

二:利用二阶贝塞尔曲线实现放大缩小的回弹效果

1:计算设计
可以设计如下方式
t为动画时间,start为缩放初始值,end为缩放最终值,control为中间的控制点,最终返回结果是某个时间点对于的需要缩放的值
public float calculateScaleByQuadraticBezier(float t, float start, float control, float end) {
float temp = 1 - t;
return temp * temp * start + 2 * t * temp * control + t * t * end;
}
2:上代码

package com.demo;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {
    private ValueAnimator mCurrentAnimator;
    private View mView;
    private Button mButton;
    private boolean mIsAnimating = false;
    private float mFinalScale = 1.3f;//想要放大的值
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mView = findViewById(R.id.test_view);
        mButton = findViewById(R.id.test);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mIsAnimating) {
                    return;
                }
                if (mView.getScaleX() > 1) {
                    scaleToNormal(mView);
                    mButton.setText("放大");
                } else {
                    scaleToBig(mView);
                    mButton.setText("还原");
                }

            }
        });
    }

    private void scaleToBig(final View view) {
        mCurrentAnimator = ValueAnimator.ofFloat(0, 1);
        mCurrentAnimator.setDuration(800);//设置的动画时长
        final float start = 1;
        final float end = mFinalScale;
        final float control = mFinalScale + mFinalScale * 0.3f;//这里的大于end的,最终效果会有一个放大回弹的效果
        mCurrentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                float scale = calculateScaleByQuadraticBezier(value,start,
                        control,end);
                view.setScaleX(scale);
                view.setScaleY(scale);
            }
        });
        mCurrentAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mIsAnimating = false;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                mIsAnimating = false;
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mIsAnimating = true;
        mCurrentAnimator.start();
    }

    //回到初始状态
    private void scaleToNormal(final View view) {
        mCurrentAnimator = ValueAnimator.ofFloat(0, 1);
        mCurrentAnimator.setDuration(800);
        final float start = mFinalScale;
        final float end = 1;
        final float control = mFinalScale + mFinalScale * 0.3f;
        mCurrentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                float scale = calculateScaleByQuadraticBezier(value,start,
                        control,end);
                view.setScaleX(scale);
                view.setScaleY(scale);
            }
        });
        mCurrentAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mIsAnimating = false;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                mIsAnimating = false;
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mIsAnimating = true;
        mCurrentAnimator.start();
    }

    public float calculateScaleByQuadraticBezier(float t, float start, float control, float end) {
        float temp = 1 - t;
        return temp * temp * start + 2 * t * temp * control + t * t * end;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaowen2008821

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值