Commit 3e1b1fe1 by wjg

v2

parent 2cf223b5
package com.ihaoin.hooloo.device.component.particlesmasher;
import android.app.Presentation;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/14
* desc : xxxx描述
* version: 1.0
* </pre>
*/
public class ParticleSmasher extends View {
private List<SmashAnimator> mAnimators = new ArrayList<>();
private Canvas mCanvas;
private Presentation mActivity;
public ParticleSmasher(Presentation activity) {
super((Context) activity.getContext());
this.mActivity = activity;
addView2Window(activity);
init();
}
/**
* 添加View到当前界面
*/
private void addView2Window(Presentation activity) {
ViewGroup rootView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
// 需要足够的空间展现动画,因此这里使用的是充满父布局
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
rootView.addView(this, layoutParams);
}
private void init() {
mCanvas = new Canvas();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (SmashAnimator animator : mAnimators) {
animator.draw(canvas);
}
}
public SmashAnimator with(View view) {
// 每次都新建一个单独的SmashAnimator对象
SmashAnimator animator = new SmashAnimator(this, view);
mAnimators.add(animator);
return animator;
}
/**
* 获取View的Rect,并去掉状态栏、toolbar高度
* @param view 来源View
* @return 获取到的Rect
*/
public Rect getViewRect(View view) {
Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
int[] location = new int[2];
getLocationOnScreen(location);
rect.offset(-location[0], -location[1]);
return rect;
}
/**
* 获取View的Bitmap
* @param view 来源View
* @return 获取到的图片
*/
public Bitmap createBitmapFromView(View view) {
view.clearFocus();
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
if (bitmap != null) {
synchronized (mCanvas) {
Canvas canvas = mCanvas;
canvas.setBitmap(bitmap);
view.draw(canvas);
canvas.setBitmap(null);
}
}
return bitmap;
}
/**
* 移除动画
* @param animator 需要移除的动画
*/
public void removeAnimator(SmashAnimator animator) {
if (mAnimators.contains(animator)) {
mAnimators.remove(animator);
}
}
/**
* 清除所有动画
*/
public void clear() {
mAnimators.clear();
invalidate();
}
/**
* 让View重新显示
* @param view 已经隐藏的View
*/
public void reShowView(View view) {
view.animate().setDuration(100).setStartDelay(0).scaleX(1).scaleY(1).translationX(0).translationY(0).alpha(1).start();
}
}
package com.ihaoin.hooloo.device.component.particlesmasher;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import com.ihaoin.hooloo.device.component.particlesmasher.particle.DropParticle;
import com.ihaoin.hooloo.device.component.particlesmasher.particle.ExplosionParticle;
import com.ihaoin.hooloo.device.component.particlesmasher.particle.FloatParticle;
import com.ihaoin.hooloo.device.component.particlesmasher.particle.Particle;
import java.util.Random;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/14
* desc : xxxx描述
* version: 1.0
* </pre>
*/
public class SmashAnimator {
public static final int STYLE_EXPLOSION = 1, // 爆炸
STYLE_DROP = 2, // 下落
STYLE_FLOAT_LEFT = 3, // 飘落——>自左往右,逐列飘落
STYLE_FLOAT_RIGHT = 4, // 飘落——>自右往左,逐列飘落
STYLE_FLOAT_TOP = 5, // 飘落——>自上往下,逐行飘落
STYLE_FLOAT_BOTTOM = 6; // 飘落——>自下往上,逐行飘落
private int mStyle = STYLE_EXPLOSION; // 动画样式
private ValueAnimator mValueAnimator;
private ParticleSmasher mContainer; // 绘制动画效果的View
private View mAnimatorView; // 要进行爆炸动画的View
private Bitmap mBitmap;
private Rect mRect; // 要进行动画的View在坐标系中的矩形
private Paint mPaint; // 绘制粒子的画笔
private Particle[][] mParticles; // 粒子数组
private float mEndValue = 1.5f;
private long mDuration = 1000L;
private long mStartDelay = 150L;
private float mHorizontalMultiple = 3; // 粒子水平变化幅度
private float mVerticalMultiple = 4; // 粒子垂直变化幅度
private int mRadius = Utils.dp2Px(2); // 粒子基础半径
// 加速度插值器
private static final Interpolator DEFAULT_INTERPOLATOR = new AccelerateInterpolator(0.6f);
private OnAnimatorListener mOnAnimatorLIstener;
public SmashAnimator(ParticleSmasher view, View animatorView) {
this.mContainer = view;
init(animatorView);
}
private void init(View animatorView) {
this.mAnimatorView = animatorView;
mBitmap = mContainer.createBitmapFromView(animatorView);
mRect = mContainer.getViewRect(animatorView);
initValueAnimator();
initPaint();
}
private void initValueAnimator() {
mValueAnimator = new ValueAnimator();
mValueAnimator.setFloatValues(0F, mEndValue);
mValueAnimator.setInterpolator(DEFAULT_INTERPOLATOR);
}
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
/**
* 爆炸动画回调事件
*/
public static abstract class OnAnimatorListener {
/**
* 动画开始时回调
*/
public void onAnimatorStart() {
}
/**
* 动画结束后回调
*/
public void onAnimatorEnd() {
}
}
/**
* 设置动画样式
*
* @param style {@link #STYLE_EXPLOSION},{@link #STYLE_DROP},{@link #STYLE_FLOAT_TOP},{@link #STYLE_FLOAT_BOTTOM},{@link #STYLE_FLOAT_LEFT},{@link #STYLE_FLOAT_RIGHT};
* @return 链式调用,因此返回本身
*/
public SmashAnimator setStyle(int style) {
this.mStyle = style;
return this;
}
/**
* 设置爆炸动画时间
*
* @param duration 时间,单位为毫秒
* @return 链式调用,因此返回本身
*/
public SmashAnimator setDuration(long duration) {
this.mDuration = duration;
return this;
}
/**
* 设置爆炸动画前延时
*
* @param startDelay 动画开始前的延时,单位为毫秒
* @return 链式调用,因此返回本身
*/
public SmashAnimator setStartDelay(long startDelay) {
mStartDelay = startDelay;
return this;
}
/**
* 设置水平变化参数
*
* @param horizontalMultiple 水平变化幅度,默认为3。为0则不产生变化。
* @return 链式调用,因此返回本身
*/
public SmashAnimator setHorizontalMultiple(float horizontalMultiple) {
this.mHorizontalMultiple = horizontalMultiple;
return this;
}
/**
* 设置垂直变化参数
*
* @param verticalMultiple 垂直变化参数,默认为4,为0则不产生变化
* @return 链式调用,因此返回本身
*/
public SmashAnimator setVerticalMultiple(float verticalMultiple) {
this.mVerticalMultiple = verticalMultiple;
return this;
}
/**
* 设置粒子基础半径
*
* @param radius 半径,单位为px
* @return 链式调用,因此返回本身
*/
public SmashAnimator setParticleRadius(int radius) {
this.mRadius = radius;
return this;
}
/**
* 添加回调
*
* @param listener 回调事件,包含开始回调、结束回调。
* @return 链式调用,因此返回本身
*/
public SmashAnimator addAnimatorListener(final OnAnimatorListener listener) {
this.mOnAnimatorLIstener = listener;
return this;
}
/**
* 开始动画
*/
public void start() {
setValueAnimator();
calculateParticles(mBitmap);
hideView(mAnimatorView, mStartDelay);
mValueAnimator.start();
mContainer.invalidate();
}
/**
* 设置动画参数
*/
private void setValueAnimator() {
mValueAnimator.setDuration(mDuration);
mValueAnimator.setStartDelay(mStartDelay);
mValueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mOnAnimatorLIstener != null) {
mOnAnimatorLIstener.onAnimatorEnd();
}
mContainer.removeAnimator(SmashAnimator.this);
}
@Override
public void onAnimationStart(Animator animation) {
if (mOnAnimatorLIstener != null) {
mOnAnimatorLIstener.onAnimatorStart();
}
}
});
}
/**
* 根据图片计算粒子
*
* @param bitmap 需要计算的图片
*/
private void calculateParticles(Bitmap bitmap) {
int col = bitmap.getWidth() / (mRadius * 2);
int row = bitmap.getHeight() / (mRadius * 2);
Random random = new Random(System.currentTimeMillis());
mParticles = new Particle[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int x = j * mRadius * 2 + mRadius;
int y = i * mRadius * 2 + mRadius;
int color = bitmap.getPixel(x, y);
Point point = new Point(mRect.left + x, mRect.top + y);
switch (mStyle) {
case STYLE_EXPLOSION:
mParticles[i][j] = new ExplosionParticle(color, mRadius, mRect, mEndValue, random, mHorizontalMultiple, mVerticalMultiple);
break;
case STYLE_DROP:
mParticles[i][j] = new DropParticle(point, color, mRadius, mRect, mEndValue, random, mHorizontalMultiple, mVerticalMultiple);
break;
case STYLE_FLOAT_LEFT:
mParticles[i][j] = new FloatParticle(FloatParticle.ORIENTATION_LEFT, point, color, mRadius, mRect, mEndValue, random, mHorizontalMultiple, mVerticalMultiple);
break;
case STYLE_FLOAT_RIGHT:
mParticles[i][j] = new FloatParticle(FloatParticle.ORIENTATION_RIGHT, point, color, mRadius, mRect, mEndValue, random, mHorizontalMultiple, mVerticalMultiple);
break;
case STYLE_FLOAT_TOP:
mParticles[i][j] = new FloatParticle(FloatParticle.ORIENTATION_TOP, point, color, mRadius, mRect, mEndValue, random, mHorizontalMultiple, mVerticalMultiple);
break;
case STYLE_FLOAT_BOTTOM:
mParticles[i][j] = new FloatParticle(FloatParticle.ORIENTATION_BOTTOM, point, color, mRadius, mRect, mEndValue, random, mHorizontalMultiple, mVerticalMultiple);
break;
}
}
}
mBitmap.recycle();
mBitmap = null;
}
/**
* View执行颤抖动画,之后再执行和透明动画,达到隐藏View的效果
*
* @param view 执行效果的View
* @param startDelay 爆炸动画的开始前延时时间
*/
public void hideView(final View view, long startDelay) {
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(startDelay + 50).setFloatValues(0f, 1f);
// 使View颤抖
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
Random random = new Random();
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
view.setTranslationX((random.nextFloat() - 0.5F) * view.getWidth() * 0.05F);
view.setTranslationY((random.nextFloat() - 0.5f) * view.getHeight() * 0.05f);
}
});
valueAnimator.start();
// 将View 缩放至0、透明至0
view.animate().setDuration(260).setStartDelay(startDelay).scaleX(0).scaleY(0).alpha(0).start();
}
/**
* 开始逐个绘制粒子
*
* @param canvas 绘制的画板
* @return 是否成功
*/
public boolean draw(Canvas canvas) {
if (!mValueAnimator.isStarted()) {
return false;
}
for (Particle[] particle : mParticles) {
for (Particle p : particle) {
// 根据动画进程,修改粒子的参数
p.advance((float) (mValueAnimator.getAnimatedValue()), mEndValue);
if (p.alpha > 0) {
mPaint.setColor(p.color);
mPaint.setAlpha((int) (Color.alpha(p.color) * p.alpha));
canvas.drawCircle(p.cx, p.cy, p.radius, mPaint);
}
}
}
mContainer.invalidate();
return true;
}
}
package com.ihaoin.hooloo.device.component.particlesmasher;
import android.content.res.Resources;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/04
* desc : xxxx描述
* version: 1.0
* </pre>
*/
public class Utils {
private static final float DENSITY = Resources.getSystem().getDisplayMetrics().density;
/**
* dp转换px
* @param dp dp值
* @return 转换后的px值
*/
public static int dp2Px(int dp) {
return Math.round(dp * DENSITY);
}
}
package com.ihaoin.hooloo.device.component.particlesmasher.particle;
import android.graphics.Point;
import android.graphics.Rect;
import java.util.Random;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/20
* desc : 下落粒子的实体类
* version: 1.0
* </pre>
*/
public class DropParticle extends Particle {
/**
* 生成粒子
* @param point 粒子在图片中原始位置
* @param color 粒子颜色
* @param radius 粒子的半径
* @param rect View区域的矩形
* @param endValue 动画的结束值
* @param random 随机数
* @param horizontalMultiple 水平变化幅度
* @param verticalMultiple 垂直变化幅度
*/
public DropParticle(Point point, int color, int radius, Rect rect, float endValue, Random random, float horizontalMultiple, float verticalMultiple){
this.color = color;
alpha = 1;
// 参与横向变化参数和竖直变化参数计算,规则:横向参数相对值越大,竖直参数越小
float nextFloat = random.nextFloat();
baseRadius = getBaseRadius(radius, random, nextFloat);
this.radius = baseRadius;
horizontalElement = getHorizontalElement(rect, random, nextFloat, horizontalMultiple);
verticalElement = getVerticalElement(rect, random, nextFloat, verticalMultiple);
baseCx = point.x;
baseCy = point.y;
cx = baseCx;
cy = baseCy;
font = endValue / 10 * random.nextFloat();
later = 0.4f * random.nextFloat();
}
private static float getBaseRadius(float radius, Random random, float nextFloat) {
// 下落和飘落的粒子,其半径很大概率大于初始设定的半径
float r = radius + radius * (random.nextFloat() - 0.5f) * 0.5f;
r = nextFloat < 0.6f ? r :
nextFloat < 0.8f ? r * 1.4f : r * 1.6f;
return r;
}
private static float getHorizontalElement(Rect rect, Random random, float nextFloat, float horizontalMultiple) {
// 第一次随机运算:h=width*±(0.01~0.49)
float horizontal = rect.width() * (random.nextFloat() - 0.5f);
// 第二次随机运行: h= 1/5概率:h;3/5概率:h*0.6; 1/5概率:h*0.3; nextFloat越大,h越小。
horizontal = nextFloat < 0.2f ? horizontal :
nextFloat < 0.8f ? horizontal * 0.6f : horizontal * 0.3f;
// 上面的计算是为了让横向变化参数有随机性,下面的计算是修改横向变化的幅度。
return horizontal * horizontalMultiple;
}
private static float getVerticalElement(Rect rect, Random random, float nextFloat, float verticalMultiple) {
// 第一次随机运算: v=height*(0.5~1)
float vertical = rect.height() * (random.nextFloat() * 0.5f + 0.5f);
// 第二次随机运行: v= 1/5概率:v;3/5概率:v*1.2; 1/5概率:v*1.4; nextFloat越大,h越大。
vertical = nextFloat < 0.2f ? vertical :
nextFloat < 0.8f ? vertical * 1.2f : vertical * 1.4f;
// 上面的计算是为了让变化参数有随机性,下面的计算是变化的幅度。
return vertical * verticalMultiple;
}
public void advance(float factor, float endValue) {
// 动画进行到了几分之几
float normalization = factor / endValue;
if (normalization < font ) {
alpha = 1;
return;
}
if ( normalization > 1f - later) {
alpha = 0;
return;
}
alpha = 1;
// 粒子可显示的状态中,动画实际进行到了几分之几
normalization = (normalization - font) / (1f - font - later);
// 动画超过7/10,则开始逐渐变透明
if (normalization >= 0.7f) {
alpha = 1f - (normalization - 0.7f) / 0.3f;
}
float realValue = normalization * endValue;
// y=j+k*x,j、k都是常数,x为 0~1.4
cx = baseCx + horizontalElement * realValue;
// 下落粒子,y轴持续增大
cy = baseCy + verticalElement * realValue;
radius = baseRadius + baseRadius / 6 * realValue;
}
}
package com.ihaoin.hooloo.device.component.particlesmasher.particle;
import android.graphics.Rect;
import java.util.Random;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/14
* desc : 爆炸粒子
* version: 1.0
* </pre>
*/
public class ExplosionParticle extends Particle{
/**
* 生成粒子
*
* @param color 粒子颜色
* @param radius 粒子的半径
* @param rect View区域的矩形
* @param endValue 动画的结束值
* @param random 随机数
* @param horizontalMultiple 水平变化幅度
* @param verticalMultiple 垂直变化幅度
*/
public ExplosionParticle( int color, int radius, Rect rect, float endValue, Random random, float horizontalMultiple, float verticalMultiple){
this.color = color;
alpha = 1;
// 参与横向变化参数和竖直变化参数计算,规则:横向参数相对值越大,竖直参数越小
float nextFloat = random.nextFloat();
baseRadius = getBaseRadius(radius, random, nextFloat);
this.radius = baseRadius;
horizontalElement = getHorizontalElement(rect, random, nextFloat, horizontalMultiple);
verticalElement = getVerticalElement(rect, random, nextFloat, verticalMultiple);
int offsetX = rect.width() / 4;
int offsetY = rect.height() / 4;
// baseCx,baseCy在中心点四周的offset/2的范围内。
baseCx = rect.centerX() + offsetX * (random.nextFloat() - 0.5f);
baseCy = rect.centerY() + offsetY * (random.nextFloat() - 0.5f);
cx = baseCx;
cy = baseCy;
font = endValue / 10 * random.nextFloat();
later = 0.4f * random.nextFloat();
}
private static float getBaseRadius(float radius, Random random, float nextFloat) {
float r = radius + radius * (random.nextFloat() - 0.5f) * 0.5f;
r = nextFloat < 0.6f ? r :
nextFloat < 0.8f ? r * 1.4f : r * 0.8f;
return r;
}
private static float getHorizontalElement(Rect rect, Random random, float nextFloat,float horizontalMultiple) {
// 第一次随机运算:h=width*±(0.01~0.49)
float horizontal = rect.width() * (random.nextFloat() - 0.5f);
// 第二次随机运行: h= 1/5概率:h;3/5概率:h*0.6; 1/5概率:h*0.3; nextFloat越大,h越小。
horizontal = nextFloat < 0.2f ? horizontal :
nextFloat < 0.8f ? horizontal * 0.6f : horizontal * 0.3f;
// 上面的计算是为了让横向变化参数有随机性,下面的计算是修改横向变化的幅度。
return horizontal * horizontalMultiple;
}
private static float getVerticalElement(Rect rect, Random random, float nextFloat,float verticalMultiple) {
// 第一次随机运算: v=height*(0.5~1)
float vertical = rect.height() * (random.nextFloat() * 0.5f + 0.5f);
// 第二次随机运行: v= 1/5概率:v;3/5概率:v*1.2; 1/5概率:v*1.4; nextFloat越大,h越大。
vertical = nextFloat < 0.2f ? vertical :
nextFloat < 0.8f ? vertical * 1.2f : vertical * 1.4f;
// 上面的计算是为了让变化参数有随机性,下面的计算是变化的幅度。
return vertical * verticalMultiple;
}
public void advance(float factor, float endValue) {
// 动画进行到了几分之几
float normalization = factor / endValue;
if (normalization < font || normalization > 1f - later) {
alpha = 0;
return;
}
alpha = 1;
// 粒子可显示的状态中,动画实际进行到了几分之几
normalization = (normalization - font) / (1f - font - later);
// 动画超过7/10,则开始逐渐变透明
if (normalization >= 0.7f) {
alpha = 1f - (normalization - 0.7f) / 0.3f;
}
float realValue = normalization * endValue;
// y=j+k*x,j、k都是常数,x为 0~1.4
cx = baseCx + horizontalElement * realValue;
// y=j+k*(x*(x-1),j、k都是常数,x为 0~1.4
cy = baseCy + verticalElement * (realValue * (realValue - 1));
radius = baseRadius + baseRadius / 4 * realValue;
}
}
package com.ihaoin.hooloo.device.component.particlesmasher.particle;
import android.graphics.Point;
import android.graphics.Rect;
import java.util.Random;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/20
* desc : 飘落粒子
* version: 1.0
* </pre>
*/
public class FloatParticle extends Particle {
private float top;
private float left;
public static final int ORIENTATION_LEFT=1,ORIENTATION_RIGHT=2,ORIENTATION_TOP=3,ORIENTATION_BOTTOM=4;
// 方向
private int orientation=ORIENTATION_TOP;
/**
* 生成粒子
* @param orientation 方向
* @param point 粒子在图片中的位置
* @param color 粒子颜色
* @param radius 粒子的半径
* @param rect View区域的矩形
* @param endValue 动画的结束值
* @param random 随机数
* @param horizontalMultiple 水平变化幅度
* @param verticalMultiple 垂直变化幅度
*/
public FloatParticle(int orientation,Point point, int color, int radius, Rect rect, float endValue, Random random, float horizontalMultiple, float verticalMultiple){
this.color = color;
alpha = 1;
// 参与横向变化参数和竖直变化参数计算,规则:横向参数相对值越大,竖直参数越小
float nextFloat = random.nextFloat();
baseRadius = getBaseRadius(radius, random, nextFloat);
this.radius = baseRadius;
horizontalElement = getHorizontalElement(rect, random, nextFloat, horizontalMultiple);
verticalElement = getVerticalElement(rect, random, nextFloat, verticalMultiple);
baseCx = point.x;
baseCy = point.y;
cx = baseCx;
cy = baseCy;
font = endValue / 10 * random.nextFloat();
later = 0.4f * random.nextFloat();
left=(baseCx-rect.left)/rect.width();
top=(baseCy-rect.top)/rect.height();
this.orientation=orientation;
}
private static float getBaseRadius(float radius, Random random, float nextFloat) {
// 下落和飘落的粒子,其半径很大概率大于初始设定的半径
float r = radius + radius * (random.nextFloat() - 0.5f) * 0.5f;
r = nextFloat < 0.6f ? r :
nextFloat < 0.8f ? r * 1.4f : r * 1.6f;
return r;
}
private static float getHorizontalElement(Rect rect, Random random, float nextFloat, float horizontalMultiple) {
// 第一次随机运算:h=width*±(0.01~0.49)
float horizontal = rect.width() * (random.nextFloat() - 0.5f);
// 第二次随机运行: h= 1/5概率:h;3/5概率:h*0.6; 1/5概率:h*0.3; nextFloat越大,h越小。
horizontal = nextFloat < 0.2f ? horizontal :
nextFloat < 0.8f ? horizontal * 0.6f : horizontal * 0.3f;
// 上面的计算是为了让横向变化参数有随机性,下面的计算是修改横向变化的幅度。
return horizontal * horizontalMultiple;
}
private static float getVerticalElement(Rect rect, Random random, float nextFloat, float verticalMultiple) {
// 第一次随机运算: v=height*(0.5~1)
float vertical = rect.height() * (random.nextFloat() * 0.5f + 0.5f);
// 第二次随机运行: v= 1/5概率:v;3/5概率:v*1.2; 1/5概率:v*1.4; nextFloat越大,h越大。
vertical = nextFloat < 0.2f ? vertical :
nextFloat < 0.8f ? vertical * 1.2f : vertical * 1.4f;
// 上面的计算是为了让变化参数有随机性,下面的计算是变化的幅度。
return vertical * verticalMultiple;
}
public void advance(float factor, float endValue) {
// 动画进行到了几分之几
float normalization = factor / endValue;
if (normalization < font ) {
alpha = 1;
return;
}
if ( normalization > 1f - later) {
alpha = 0;
return;
}
alpha = 1;
// 粒子可显示的状态中,动画实际进行到了几分之几
normalization = (normalization - font) / (1f - font - later);
// 动画超过7/10,则开始逐渐变透明
if (normalization >= 0.7f) {
alpha = 1f - (normalization - 0.7f) / 0.3f;
}
float realValue = normalization * endValue;
// 重点:这里使用了realValue(0~1),而不是normalization(0~1.4)。如果使用nor的话,在最后面开始飘落的粒子就会全透明看不到了。
switch (orientation){
case ORIENTATION_LEFT:
if(realValue>left){
cy=baseCy+verticalElement*(realValue-left);
cx = baseCx + horizontalElement * (realValue-left);
}
break;
case ORIENTATION_RIGHT:
if(realValue>(1-left)){
cy=baseCy+verticalElement*(realValue-(1-left));
cx = baseCx + horizontalElement * (realValue-(1-left));
}
break;
case ORIENTATION_TOP:
if(realValue>top){
cy=baseCy+verticalElement*(realValue-top);
cx = baseCx + horizontalElement * (realValue-top);
}
break;
case ORIENTATION_BOTTOM:
if(realValue>(1-top)){
cy=baseCy+verticalElement*(realValue-(1-top));
cx = baseCx + horizontalElement * (realValue-(1-top));
}
break;
}
radius = baseRadius + baseRadius / 6 * realValue;
}
}
package com.ihaoin.hooloo.device.component.particlesmasher.particle;
/**
* <pre>
* author : FaDai
* e-mail : i_fadai@163.com
* time : 2017/12/20
* desc : xxxx描述
* version: 1.0
* </pre>
*/
public abstract class Particle {
public int color; // 颜色
public float radius; // 半径
public float alpha; // 透明度(0~1)
public float cx; // 圆心 x
public float cy; // 圆心 y
public float horizontalElement; // 水平变化参数
public float verticalElement; // 垂直变化参数
public float baseRadius; // 初始半径,同时负责半径大小变化
public float baseCx; // 初始圆心 x
public float baseCy; // 初始圆心 y
public float font; // 决定了粒子在动画开始多久之后,开始显示
public float later; // 决定了粒子动画结束前多少时间开始隐藏
public void advance(float factor, float endValue) {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment