自定义日出日落动画

作者: Only凹凸曼 | 来源:发表于2017-05-18 12:27 被阅读271次

    背景

    最近在使用某一款天气软件的时候发现了它的一个日出日落的动画,感觉还不错,后面就自己动手撸了一个源码地址

    分析

    我们先对这个动画元素进行分析:

    1. 需要一条曲线。
    2. 需要一个沿着曲线运动的小太阳。
    3. 需要一个跟着太阳一起运动的阴影面。

    好了我们直接开始

    首先我们定义一个自定义View,然后初始化一些我们上面分析到的元素

     //曲线初始化
            mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPathPaint.setStyle(Paint.Style.STROKE);
            mPathPaint.setStrokeWidth(2);
            mPathPaint.setColor(Color.parseColor("#ffffff"));
            PathEffect effects = new DashPathEffect(new float[]{10, 10, 10, 10}, 0);
            mPathPaint.setPathEffect(effects);
    
            //日出动画阴影部分初始化
            mAnmationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mAnmationPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mAnmationPaint.setColor(Color.parseColor("#32ffffff"));
    
            //开始坐标的XY
            mStartPointX = dp2px(9);
            mStartPointY = dp2px(80);
    
            //结束坐标的XY
            mEndPointX = dp2px(139);
            mEndPointY = mStartPointY;
    
            //太阳的移动坐标的XY
            mMovePointX = mStartPointX;
            mMovePointY = mStartPointY;
    
            //圆的半径
            mRadius = dp2px(74);
    
            //圆心坐标
            mCirclePointX = dp2px(74);
            mCirclePointY = dp2px(115);
    
            //圆的初始化
            mRectF = new RectF(mCirclePointX - mRadius, mCirclePointY - mRadius, mCirclePointX + mRadius, mCirclePointY + mRadius);
    

    接下来就是我们绘制的代码

    if (isNeedSun) {
                //画曲线
                canvas.save();
                canvas.clipRect(mStartPointX, 0, mEndPointX, mStartPointY, Region.Op.INTERSECT);
                canvas.clipRect(mMovePointX - mBitmapW / 2, mMovePointY - mBitmapH / 2, mMovePointX + mBitmapW / 2, mMovePointY + mBitmapH / 2, Region.Op.DIFFERENCE);
                canvas.drawArc(mRectF, 200, 140, true, mPathPaint);
                //画透明背景用圆的角度来控制
                canvas.clipRect(mStartPointX, 0, mMovePointX, mStartPointY, Region.Op.INTERSECT);
                canvas.drawArc(mRectF, 200, 140, true, mAnmationPaint);
                canvas.restore();
    
                //画小太阳
                canvas.drawBitmap(mSunBitmap, mMovePointX - mBitmapW, mMovePointY - mBitmapH, null);
    
            } else if (mNotUp || mHasDown) {
                //画曲线
                canvas.save();
                canvas.clipRect(mMovePointX - mBitmapW / 2, mMovePointY - mBitmapH / 2, mMovePointX + mBitmapW / 2, mMovePointY + mBitmapH / 2, Region.Op.DIFFERENCE);
                canvas.clipRect(0, 0, getWidth(), mStartPointY, Region.Op.INTERSECT);
                canvas.drawCircle(mCirclePointX, mCirclePointY, mRadius, mPathPaint);
                canvas.restore();
    
                if (mNotUp) {
                    //画小太阳
                    canvas.drawBitmap(mSunBitmap, mStartPointX - mBitmapW, mStartPointY - mBitmapH, null);
                } else {
                    canvas.drawBitmap(mSunBitmap, mEndPointX - mBitmapW, mEndPointY - mBitmapH, null);
                }
            } else {
                //这里不绘制小太阳,只有曲线
                canvas.save();
                canvas.clipRect(0, 0, getWidth(), mStartPointY, Region.Op.INTERSECT);
                canvas.drawCircle(mCirclePointX, mCirclePointY, mRadius, mPathPaint);
                canvas.restore();
            }
    

    最后就是通过我们外部的控制来实现小太阳的动画

    mSunBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.daily_deatil_sun);
                mBitmapW = mSunBitmap.getWidth() / 2;
                mBitmapH = mSunBitmap.getHeight() / 2;
                mNotUp = false;
                isNeedSun = true;
                mHasDown = false;
                ValueAnimator progressAnimator = ValueAnimator.ofFloat(210, 330);
                progressAnimator.setDuration(3000);
                progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        /**每次在初始值和结束值之间产生的一个平滑过渡的值,逐步去更新进度*/
                        float x = (float) animation.getAnimatedValue();
                        if ((x - 210) <= (120 * a)) {
                            mMovePointX = mCirclePointX + (int) (mRadius * (Math.cos(x * 3.14 / 180)));
                            mMovePointY = mCirclePointY + (int) (mRadius * (Math.sin(x * 3.14 / 180)));
                            invalidate();
                        } else {
                            return;
                        }
                    }
                });
                progressAnimator.setInterpolator(new LinearInterpolator());
                progressAnimator.start();
    

    最后附上源码地址和简单看一下效果图:

    曲线效果图

    相关文章

      网友评论

        本文标题:自定义日出日落动画

        本文链接:https://www.haomeiwen.com/subject/sgxsxxtx.html