新年了,项目中要作个动画,整体要求实现彩带乱飞,烟花冲天而起,烟花缩放,小鸡换图,小鸡飘移,横幅裁剪、展开等动画效果,全局大量使用了属性动画来实现。
如下效果图:
我在实现过程中,横幅的裁剪计算,捣腾了比较久的时间,初版采用属性动画计算float的一个比率值,来配合每一帧的裁剪绘制,如下代码:
private static class RollView extends View { private Bitmap mBitmap; private Rect mSrc; private Rect mDst; private int mRollWidth = 60; private float mRate; private boolean mIsStopAnim; public RollView(Context context) { super(context); mSrc = new Rect(); mDst = new Rect(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { if (mBitmap == null) return; drawFromMiddleByFloatCompute(canvas); } private void drawFromMiddleByFloatCompute(Canvas canvas) { /* 以下src 都需要加上mBitmap. 的前缀,, 因从drawable拿到的是原始图片宽高 而适配时,可能view的宽高比 drawable的宽高还小或大 */ final float rate = mRate; mSrc.left = 0; mSrc.top = 0; mSrc.right = mRollWidth; mSrc.bottom = mBitmap.getHeight(); mDst.left = (int) ((getWidth() / 2 - mRollWidth) - (getWidth() / 2 - mRollWidth) * rate); mDst.top = 0; mDst.right = mDst.left + mRollWidth + 1;//因精度问题,这里强制+1 mDst.bottom = getHeight(); canvas.drawBitmap(mBitmap, mSrc, mDst, null); //中间 int sw = (int) ((mBitmap.getWidth() - mRollWidth * 2) * rate); mSrc.left = mBitmap.getWidth() / 2 - sw / 2; mSrc.top = 0; mSrc.right = mSrc.left + sw; mSrc.bottom = mBitmap.getHeight(); int dw = (int) ((getWidth() - mRollWidth * 2) * rate); mDst.left = getWidth() / 2 - dw / 2; mDst.top = 0; mDst.right = mDst.left + dw; mDst.bottom = getHeight(); canvas.drawBitmap(mBitmap, mSrc, mDst, null); //右边 mSrc.left = mBitmap.getWidth() - mRollWidth; mSrc.top = 0; mSrc.right = mBitmap.getWidth(); mSrc.bottom = mBitmap.getHeight(); mDst.left = (int) (getWidth() / 2 + (getWidth() / 2 - mRollWidth) * rate); mDst.top = 0; mDst.right = mDst.left + mRollWidth; mDst.bottom = getHeight(); canvas.drawBitmap(mBitmap, mSrc, mDst, null); } public void setRes(int resId) { mBitmap = getBitmapFromLocal(resId); } @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void startFloatComputeAnim() { /* 如果有float获取比率值,从而计算出相应的坐标值,那么可能由于最终在转成Rect的坐标时, float to int ,有精度的损失:1个px 而引起效果的不理想 */ ValueAnimator animator = ValueAnimator.ofFloat(0, 1); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (mIsStopAnim) { animation.cancel(); return; } mRate = (float) animation.getAnimatedValue(); invalidate(); } }); animator.setDuration(2000); animator.start(); } public void stopAnim() { mIsStopAnim = true; } }
> 因float转int有一个精度损失的问题,所以在计算中强制加上了1px(代码中有);
这样虽然解决了有1px没有绘制的问题,但是会发生绘制时不够平滑,而出现抖动的情形(在某些devices上)
所以最好还是不要使用float来计算
> 后来,同事猜想使用一个固定int值 来参与计算,可能可以解决上述问题:
比如每秒30帧,这里动画时长2秒,即共30*2=60帧;
图片宽度、左画轴、右画轴 对 60帧数 做相应的除法及其他计算,可得出一个单帧中 它们应该运动的x距离
> 之后,我又想了一种,使用一个属性动画,来计算出从0到getWidth()之间的 动画值,
从而通过计算,使得横幅从左向右拉开, 如下:
代码就不整体开源了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍非常漂亮的新年祝福!C语言实现漂亮的烟花效果,包括了非常漂亮的新年祝福!C语言实现漂亮的烟花效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了C语言实现漂亮的烟花效果展示的具体代码,供大家参考,具体内容如下 程序名称:祝福烟花,祝福朋友 编译环境:VC++6.0 && easyx(立冬版) 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程
365个日夜, 每一条推送饱含真心, 每一次的成长都有你们的陪伴。 此刻无论你身在银装素裹的北国, 亦或是阳光明媚的南方。 小农愿这一年来的温暖与感动, 化作来年满满的幸运赠予你们。
本文向大家介绍程序员的新年祝福 Happy New Year,包括了程序员的新年祝福 Happy New Year的使用技巧和注意事项,需要的朋友参考一下 愿你新年快乐,许下新年的新愿望,努力实现! 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
有什么富有诗意的新年祝福代码含义
虎年怎么能少得了老虎?画只虎头虎脑的可爱老虎,点燃除夕夜。不用纸和笔,就靠Python海龟作图,小朋友赶紧代码敲起来吧!
本文向大家介绍Android自定义View实现左右滑动选择出生年份,包括了Android自定义View实现左右滑动选择出生年份的使用技巧和注意事项,需要的朋友参考一下 自定义view的第三篇,模仿的是微博运动界面的个人出生日期设置view,先看看我的效果图: 支持设置初始年份,左右滑动选择出生年份,对应的TextView的值也会改变。这个动画效果弄了好久,感觉还是比较生硬,与微博那个还是有点区别。