自定义Bezier动画和抖动动画的实现

xiaoxiao2021-02-28  98

别的先不说了,先上效果:

之前看到很多贝塞尔的动画效果,都很漂亮,之前有需要用到类似的效果,就先写了下来。

在百度搜索了下, 公式是这样子的:

二次方公式

二次方贝兹曲线的路径由给定点P0、P1、P2的函数B(t)追踪: 我也就照着公式 ,来一个简单的代码:

package com.mj.animapp.anim; import android.annotation.SuppressLint; import android.graphics.PointF; import com.nineoldandroids.animation.TypeEvaluator; @SuppressLint("NewApi") public class BezierEvaluatorBear implements TypeEvaluator<PointF> { /** * 二次方贝塞尔曲线 B(t)=(1-t)^2*P0+2*t*(1-t)*P1+t^2*P2,t∈[0,1] P0,是我们的起点, P2是终点, * P1是途径的点 而t则是我们的一个因子,取值范围是0-1 */ private PointF pointF1;// 中间的点 public BezierEvaluatorBear(PointF pointF1) { this.pointF1 = pointF1; } /** * 开始和结束的点,这个公式是固定 */ @Override public PointF evaluate(float fraction, PointF pointF0, PointF pointF2) { PointF pointF = new PointF(); pointF.x = (float) ((pointF0.x * (Math.pow((1 - fraction), 2))) + 2 * pointF1.x * fraction * (1 - fraction) + pointF2.x * Math.pow(fraction, 2)); pointF.y = (float) ((pointF0.y * (Math.pow((1 - fraction), 2))) + 2 * pointF1.y * fraction * (1 - fraction) + pointF2.y * Math.pow(fraction, 2)); return pointF; } }

公式是实现了 , 但是怎么实现整个动画的过程呢? 

也是同样的先上代码:

@OnClick(R.id.llLeftRate) public void llLeftRateOnlick(View view) { int[] starRect = new int[2]; ivBean.getLocationOnScreen(starRect); int[] endRect = new int[2]; rlZhangBean.getLocationOnScreen(endRect); int starx = starRect[0]; int stary = starRect[1] - statusBarHeight; int endx = 0; int endy = 0; for (int i = 0; i < ANMIBEANCOUNT; i++) { endx = endRect[0] + (int) (Math.random() * (rlZhangBean.getWidth() + 1)); endy = (endRect[1] - statusBarHeight) + (int) (Math.random() * (rlZhangBean.getHeight() + 1)); mAnmiView.addBezierView(new PointF(starx, stary), new PointF(endx - 50, endy + 100), new PointF(endx, endy)); } ObjectAnimator objAnim = rotationAnim(llLeftRate, 1f); objAnim.setStartDelay(1000); objAnim.start(); }

在这个点击事件中我们可以看出,要执行整个动画我们需要   开始的位置 p0, 中间幅度的位置 p1, 结束的位置p2。  怎么生成很多个小豆子呢, 就是使用自定义Layout , addview后,执行自定义的动画。看一下源码大家就会明白很多了。 public void addBezierView(PointF pointStart, PointF pointMid, PointF pointEnd) { this.pointStart = pointStart; this.pointMid = pointMid; this.pointEnd = pointEnd; this.pointMid.set(pointMid.x + mWidth / 2, pointMid.y - mHeight); this.pointEnd.set(pointEnd.x - mWidth / 2, pointEnd.y - mHeight); ImageView view = new ImageView(getContext()); int nextInt = mRandom.nextInt(loves.length - 1); view.setImageDrawable(loves[nextInt]); view.setLayoutParams(mParams); addView(view); ViewCompat.setX(view, pointStart.x); ViewCompat.setY(view, pointStart.y); AnimatorSet matorSet = getAnimatorSet(view); // 设置插补器. matorSet.setInterpolator(new AccelerateDecelerateInterpolator()); matorSet.start(); }  顺便说下,怎么实现不同的位置显示不同的效果呢?  // 给动画添加一个动画的进度监听;在动画执行的过程中动态的改变view的位置; valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { PointF pointF = (PointF) animation.getAnimatedValue(); ViewCompat.setX(view, pointF.x); ViewCompat.setY(view, pointF.y); if (animation.getAnimatedFraction() <= 0.6f) { ViewCompat.setScaleX(view, 0.6f + animation.getAnimatedFraction()); ViewCompat.setScaleY(view, 0.6f + animation.getAnimatedFraction()); } else { ViewCompat.setScaleX(view, 1.2f - (animation.getAnimatedFraction() - 0.6f)); ViewCompat.setScaleY(view, 1.2f - (animation.getAnimatedFraction() - 0.6f)); } // 设置view的透明度,达到动画执行过程view逐渐透明效果; } }); 这个地方使用了放大缩小,来尝试实现有点3d效果的抛物线。 最后说明下,最后面的抖动效果我使用了nineoldandroid 来实现抖动的效果 public ObjectAnimator rotationAnim(View view, float shakeFactor) { PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofKeyframe( "scaleX", Keyframe.ofFloat(0f, 1f), Keyframe.ofFloat(.1f, .9f), Keyframe.ofFloat(.2f, .9f), Keyframe.ofFloat(.3f, 1.0f),// 1.1f Keyframe.ofFloat(.4f, 1.0f), Keyframe.ofFloat(.5f, 1.0f), Keyframe.ofFloat(.6f, 1.0f), Keyframe.ofFloat(.7f, 1.0f), Keyframe.ofFloat(.8f, 1.0f), Keyframe.ofFloat(.9f, 1.0f), Keyframe.ofFloat(1f, 1f)); PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofKeyframe( "scaleY", Keyframe.ofFloat(0f, 1f), Keyframe.ofFloat(.1f, .9f), Keyframe.ofFloat(.2f, .9f), Keyframe.ofFloat(.3f, 1.0f), Keyframe.ofFloat(.4f, 1.0f), Keyframe.ofFloat(.5f, 1.0f), Keyframe.ofFloat(.6f, 1.0f), Keyframe.ofFloat(.7f, 1.0f), Keyframe.ofFloat(.8f, 1.0f), Keyframe.ofFloat(.9f, 1.0f), Keyframe.ofFloat(1f, 1f)); PropertyValuesHolder pvhRotate = PropertyValuesHolder.ofKeyframe( "rotation", Keyframe.ofFloat(0f, 0f), Keyframe.ofFloat(.1f, -3f * shakeFactor), Keyframe.ofFloat(.2f, -3f * shakeFactor), Keyframe.ofFloat(.3f, 3f * shakeFactor), Keyframe.ofFloat(.4f, -3f * shakeFactor), Keyframe.ofFloat(.5f, 3f * shakeFactor), Keyframe.ofFloat(.6f, -3f * shakeFactor), Keyframe.ofFloat(.7f, 3f * shakeFactor), Keyframe.ofFloat(.8f, -3f * shakeFactor), Keyframe.ofFloat(.9f, 3f * shakeFactor), Keyframe.ofFloat(1f, 0)); return ObjectAnimator.ofPropertyValuesHolder(view, pvhScaleX, pvhScaleY, pvhRotate).setDuration(1000); } 这个项目目前已经我已经放在github 上 ,欢迎大家star 点击打开链接https://github.com/zasdsd/BezierAmin

转载请注明原文地址: https://www.6miu.com/read-31394.html

最新回复(0)