Andoird自定义View贝塞尔曲线入门用法:仿天猫LOGO加载动画

一、前言

打开天猫随便搜索一下,就会出现一个天猫LOGO的加载图
这里写图片描述

模拟效果:
这里写图片描述
gif图的效果不是很好,手机上运行效果比较好。

二、实现思路

先推荐两篇文章了解一下贝塞尔曲线:
http://www.gcssloop.com/customview/Path_Bezier
http://blog.csdn.net/harvic880925/article/details/50995587

可以让美工做一个图,然后转换成SVG,使用一些svg -> path的库转换成Path,再使用动画展示出来。不过这LOGO看上去不是很复杂,就自己绘制,弧度都是使用贝塞尔曲线绘制。
1. 知道photoshop中的钢笔工具是用贝塞尔曲线实现的,那首先用PS来简单构建一个模型,确定控制点坐标。
2. 用path.lineTo、quadTo、cubicTo等方法绘制路径。
3. 用PathMeasure类来截取长度,达到闭合图形的缺口目的。
4. ValueAnimator属性动画,动起来。

三、开始绘制

1.用PS画出草图

经过调整,得到以下:
这里写图片描述

以一个栅格(cell)为基本单位,中心点表示整个图形的中央位置,大概得出整个图形:
长度:12 * cell,高度:8 * cell,为了方便计算和绘制图形,以黑色圆点为坐标原点。
红色原点:坐标点
黄色原点:贝塞尔曲线控制点
p1(cell, 0),p2(5 * cell, -2 * cell),p3(6 * cell, 0),p4(6 * cell,5 * cell),p5(5 * cell, 6 * cell)
c1(3 * cell, 0),c2(4 * cell, -2 * cell),c3(6 * cell, -2 * cell),c4(6 * cell,6 * cell)
左侧和右侧是镜像关系,所以左侧坐标只需要将右侧x坐标取反即可。

2.代码实现

private void initEarsPath() {

        p1.x = cellSize ;
        p1.y = 0;
        p2.x = 5 * cellSize ;
        p2.y = -2 * cellSize;
        p3.x = 6 * cellSize;
        p3.y = 0;
        p4.x = 6 * cellSize ;
        p4.y = 5 * cellSize ;
        p5.x = 5 * cellSize ;
        p5.y = 6 * cellSize ;
        c1.x = 3 * p1.x ;
        c1.y = 0;
        c2.x = 4 *cellSize ;
        c2.y = -2 * cellSize ;
        c3.x = 6 * cellSize;
        c3.y = -2 * cellSize ;
        c4.x = 6 * cellSize ;
        c4.y = 6 * cellSize ;
        mPath.moveTo(p1.x, p1.y);
        //三阶
        mPath.cubicTo(c1.x, c1.y, c2.x,c2.y, p2.x, p2.y);
        //二阶
        mPath.quadTo(c3.x, c3.y, p3.x, p3.y);
        //右侧直线
        mPath.lineTo(p4.x, p4.y);
        //右下角圆弧
        mPath.quadTo(c4.x, c4.y, p5.x, p5.y);

        //取反
        p1.x = -p1.x;
        p2.x = -p2.x;
        p3.x = -p3.x;
        p4.x = -p4.x;
        p5.x = -p5.x;
        c1.x = -c1.x;
        c2.x = -c2.x;
        c3.x = -c3.x;
        c4.x = -c4.x;

        mPath.lineTo(p5.x, p5.y);
        //左下角圆弧
        mPath.quadTo(c4.x, c4.y, p4.x, p4.y);
        //左侧直线
        mPath.lineTo(p3.x, p3.y);
        //二阶
        mPath.quadTo(c3.x, c3.y, p2.x, p2.y);
        //三阶
        mPath.cubicTo(c2.x, c2.y, c1.x,c1.y, p1.x, p1.y);

        mPath.close();

        mMeasure.setPath(mPath, false);
        mPathLength = mMeasure.getLength();
    }

3.缺口实现
这里写图片描述
将图形展开成一条直线好分析,开始点和终点其实是一个点,图中绿色表示缺口距离,A点加上间距等于B点,有两种情况。
1.A和B正好在线段的中间
2.B经过了终点(始点)而A还没经过终点
根据这两种情况从原path使用PathMeasure截取出红色部分的内容存放在新的path中,再将新的Path绘制出来就实现缺口。

4.动画

private void initListener() {

        mAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
        mAnimator.setDuration(2000);//一段path的时间
        mAnimator.setRepeatCount(ValueAnimator.INFINITE);//无限循环
        //加入线性插值器 计算返回的值均匀递增 如若不用 会出现不连续现象
        mAnimator.setInterpolator(new LinearInterpolator());

        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimatorValue = (float) animation.getAnimatedValue();
                invalidate();
            }
        });

        mAnimator.start();
    }

5.绘制

@Override
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(mViewWidth / 2, mViewHeight / 2 - 2 * cellSize);

        mDstPath.reset();
        //判断哪种缺口情况
        if (mPathLength * mAnimatorValue + distance <= mPathLength) {
            mMeasure.getSegment(0, mPathLength * mAnimatorValue, mDstPath, true);
            mMeasure.getSegment(mPathLength * mAnimatorValue + distance, mPathLength, mDstPath, true);
        } else {
            mMeasure.getSegment(distance - mPathLength * (1 - mAnimatorValue), mPathLength * mAnimatorValue, mDstPath, true);
        }

        canvas.drawPath(mDstPath, mPaint);
    }

三、总结

本次主要熟悉使用贝塞尔曲线来绘制路径,通过PS来辅助完成坐标点和控制点的选取,以及跟Path相关的类做出动画效果。

源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值