zoukankan      html  css  js  c++  java
  • D11-Android自定义控件之动画篇3-插值器与估值器

    零、前言

    估值器和插值器丰富了动画更新时的效果
    为方便本案例演示使用了我的LogicCanvas绘图库--github地址,当然你也可以自己绘制
    估值器:TypeEvaluator :该以什么方式运动
    插值器:运动的变化情况


    一、估值器--TypeEvaluator:

    1.以二次曲线移动为例:
    9414344-970b6b039bda6d4f.gif
    二次曲线.gif
    绘制:动态改变p值
    mPainter = PainterEnum.INSTANCE.getInstance(canvas);
    mPainter.draw(sa.deepClone()
            .r(mCircleR).ang(360)
            .fs(mColor).p(mCircleR, -mCircleR).coo(0, 1600).p(currentPoint));
    
    估值器:
    public class PosX2Evaluator implements TypeEvaluator {
    
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            //初始点
            Pos startPos = (Pos) startValue;
            //结束点
            Pos endPos = (Pos) endValue;
            //计算每次更新时的x坐标
            float x = startPos.x + fraction * (endPos.x - startPos.x);
            //将y坐标进行联动
            float y = x * x / 800;
            //返回更新后的点
            return endPos.clone(x, y);
        }
    }
    
    更新监听
    Pos startP = currentPoint;//初始值(起点)
    Pos endP = new Pos(1000, mCircleR);//结束值(终点)
    ValueAnimator animator = ValueAnimator.ofObject(new PosX2Evaluator(), startP, endP);
    animator.setRepeatCount(-1);
    animator.setRepeatMode(ValueAnimator.REVERSE);
    animator.setDuration(5000);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            currentPoint = (Pos) animation.getAnimatedValue();
            postInvalidate();
        }
    });
    animator.start();
    
    2.log型:
    9414344-dbc06c3abe7c962f.gif
    log型.gif
    public class PosLogEvaluator implements TypeEvaluator {
    
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            //初始点
            Pos startPos = (Pos) startValue;
            //结束点
            Pos endPos = (Pos) endValue;
            //计算每次更新时的x坐标
            float x = startPos.x + fraction * (endPos.x - startPos.x);
            //将y坐标进行联动
            float y = (float) (Math.log10(x) * 200);
            //返回更新后的点
            return endPos.clone(x, y);
        }
    }
    
    3.sin型:
    9414344-5d049d187e0c5bf4.gif
    sin型.gif
    public class PosSinEvaluator implements TypeEvaluator {
    
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
    
            //初始点
            Pos startPos = (Pos) startValue;
            //结束点
            Pos endPos = (Pos) endValue;
            //计算每次更新时的x坐标
            float x = startPos.x + fraction * (endPos.x - startPos.x);
            //将y坐标进行联动
            float y =  (float) (Math.sin(x * Math.PI / 180) * 200);
            //返回更新后的点
            return endPos.clone(x, y);
        }
    }
    

    由此可以看出:不同的移动曲线只是在x坐标变化是对y坐标的不同处理。这就是估值器的作用。


    二、插值器--TimeInterpolator

    注意输出值也是要在0~1之间的变化数
    安卓内置了一下插值器,就不说了,使用自定义插值器来说明其中的原理

    1.定义sin型插值器:
    9414344-e96aa869954bb5ed.gif
    sin减速.gif
    /**
     * 作者:张风捷特烈
     * 时间:2018/7/9:10:08
     * 邮箱:1981462002@qq.com
     * 说明:sin函数实现加速插值器
     */
    public class D_Sin_Inter implements TimeInterpolator {
        @Override
        public float getInterpolation(float input) {
            //input是一个从0~1均匀变化的值
            //从0到PI/2均匀变化的值
            float rad = Logic.rad(90 * input);
            //返回这个弧度的sin值--sin曲线在0~PI/2区域是增长越来越缓慢,是的小球运动越来越缓慢
            return (float) (Math.sin(rad));
        }
    }
    

    使用:

     animator.setInterpolator(new D_Sin_Inter());
    
    2.定义Log型减速
    9414344-55ef86b36a1ad73d.gif
    log型减速.gif
    /**
     * 作者:张风捷特烈
     * 时间:2018/7/9:10:08
     * 邮箱:1981462002@qq.com
     * 说明:log函数实现加速插值器
     */
    public class D_Log_Inter implements TimeInterpolator {
        @Override
        public float getInterpolation(float input) {
            return (float) (Math.log10(1 + 10 * input));
        }
    }
    

    要加速效果将返回值改为1-XXX就行了
    插值器从表现上来看就是某个函数值域在0~1上的图象曲率变化的速率作用与View的某个属性上


    三、插播一个路径动画吧:

    使用sin型减速

    9414344-02adb64fe31a1259.gif
    path绘制.gif
    //初始画笔
    mPaint = new Paint();
    mPaint.setStrokeWidth(5);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setAntiAlias(true);
    mPaint.setColor(Color.RED);
    //实例路径
    mPath =new ShapeStar(ShapeStar.MODE_REGULAR).num(8).R(200).formPath();
    //测量路径
    pathMeasure = new PathMeasure(mPath, false);
    
    //动画设置
    ValueAnimator pathAnimator = ValueAnimator.ofFloat(1, 0);
    pathAnimator.setDuration(5000);
    pathAnimator.setInterpolator(new D_Sin_Inter());
    pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float value = (Float) animation.getAnimatedValue();
            DashPathEffect effect = new DashPathEffect(
                    new float[]{
                            pathMeasure.getLength(),
                            pathMeasure.getLength()},
                    value * pathMeasure.getLength());
            mPaint.setPathEffect(effect);
            invalidate();
        }
    });
    pathAnimator.start();
    
    //绘制路径
    canvas.drawPath(mPath, mPaint);
    

    后记、

    1.声明:

    [1]本文由张风捷特烈原创,转载请注明
    [2]欢迎广大编程爱好者共同交流
    [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    [4]你的喜欢与支持将是我最大的动力

    2.连接传送门:

    更多安卓技术欢迎访问:安卓技术栈
    我的github地址:欢迎star
    张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

    3.联系我

    QQ:1981462002
    邮箱:1981462002@qq.com
    微信:zdl1994328

    4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
    9414344-c474349cd3bd4b82.jpg
    公众号.jpg
  • 相关阅读:
    浅析C++中的this指针
    转:函数指针数组的妙用(I)
    函数指针与函数指针数组的使用方法
    指针函数与函数指针的区别
    二叉树的镜像
    树的子结构
    Irrlicht 3D Engine 笔记系列 之 教程5- User Interface
    Android获取当前连接的wifi名称
    dlopen 方式调用 Linux 的动态链接库
    Appium基于安卓的各种FindElement的控件定位方法实践和建议
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781874.html
Copyright © 2011-2022 走看看