自定义日出日落曲线动画

背景

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

分析

我们先对这个动画元素进行分析:
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();

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

曲线效果图

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值