如何实现炫酷的ArtLine

看见大神实现了一个自定义view
这里写图片描述
里面只有两个点,两个点在进行圆周运动,通过绘制两点之间的线,并保存下这些线,实现图片效果。
实现只有短短的几十行代码。我默默的拿来学习了下。主要有以下几点:
- 优雅的实现不断的重绘
- 决定两点的运动轨迹
- 保存绘制的线

一、实现不断的重绘界面

大神使用了ValueAnimator,
ValueAnimator本身不作用于任何对象,从名字也可以了解到,它是对值进行动画,然后通过监听其listener,在动画过程中修改对象的属性值来达到动画的目的。
在实现这个ArtLine的demo中,只是利用了LinearInterpolator(恒定变化速率的补间器)和ValueAnimator的动画监听器。就达到了不断去重绘的目的。

ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(time);
        //恒定变化速度的interpolator(补间器)
        animator.setInterpolator(new LinearInterpolator());
        //在指定的时间内,将一个数从0变到1,然后动画的每一帧会回调onAnimationUpdate方法
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
            //重绘
                invalidate();
            }
        });
        animator.setStartDelay(500);
        animator.start();

二 、决定两点的运动轨迹
上面已经分析过了,这是两个点的圆周运动,下面这4个值就是a点和B点的坐标。

aX = (float) (Math.cos(angleA) * aXR);
aY = (float) (Math.sin(angleA) * aYR);
bX = (float) (Math.cos(angleB) * bXR);
bY = (float) (Math.sin(angleB) * bYR);

Math.cos(弧度)返回余弦值,Math.sin(弧度)返回正弦值,
余弦值*R得到X轴上的坐标
正弦值*R得到Y轴上的坐标。
这里写图片描述
通过每次draw的时候增加弧度,让点做圆周运动。

//这里的speendA,speedB就是个弧度值,如speendA越大,A点移动的角度就越大,在上一个A点和这一个A点之间的距离就越大。
angleA += speedA;
angleB += speedB;

这里如果在X轴和在Y轴的半径一样,绘制出来的就是正圆,如果两个轴的半径不同,绘制出来的就是椭圆。
我很想录个屏上来啊,但是不会,只能截图了。
比如这样一个形状
这里写图片描述
它的两点运动轨迹就是这样的。
这里写图片描述

三、保存绘制的线
上面的两张图都是经过保存的,否则就只能显示一根线,或者两个点

//将两个点的坐标保存到集合中
listPos.add(aX);
listPos.add(aY);
listPos.add(bX);
listPos.add(bY);
//循环绘制到画布上
  for (int i = 0; i < listPos.size(); i++) {
            if (i % 4 == 0) {
                canvas.drawLine(listPos.get(i), listPos.get(i + 1), listPos.get(i + 2), listPos.get(i + 3), paint);
            }
        }

通过改变speedA, speedB, aXR, aYR, bXR, bYR着六个值,就可以出现多种多样的图形,代码很简单,绘制出来的图形多种多样,绘制过程也很迷人,也许这就是简单法则的魅力吧。

给双鱼的自己画个鱼

这里写图片描述

最后附上完整代码

package com.wingjay.wjmagiccurvedemo;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import java.util.ArrayList;

/**
 * Created by kang on 2016/4/25.
 */
public class KangArtLineView extends View {

    private final String TAG = this.getClass().getSimpleName();

    private Paint paint;
    private ArrayList<Float> listPos = new ArrayList<>();
    private int centerX, centerY;
    private float aX, aY, bX, bY, angleA, angleB, speedA, speedB, aXR, aYR, bXR, bYR;
    private long time;
    private String color;

    public KangArtLineView(Context context) {
        this(context, null);
    }

    public KangArtLineView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public KangArtLineView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //抗锯齿的画笔
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(1);

        speedA = 2.0f;
        speedB = 1.0f;
        aXR = 320;
        aYR = 20;
        bXR = 20;
        bYR = 320;
        time = 40 * 1000;

        startAnim(time);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        centerX = w / 2;
        centerY = h / 2;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.i(TAG, "onDraw");
        angleA += speedA;
        angleB += speedB;

        aX = (float) (Math.cos(angleA) * aXR);
        aY = (float) (Math.sin(angleA) * aYR);
        bX = (float) (Math.cos(angleB) * bXR);
        bY = (float) (Math.sin(angleB) * bYR);

        listPos.add(aX);
        listPos.add(aY);
        listPos.add(bX);
        listPos.add(bY);

        //把画布移动到view的中心
        canvas.translate(centerX, centerY);
        canvas.drawColor(Color.BLACK);
        //canvas.save()与canvas.restore()成对出现,
//        save()用来保存画布的状态
        canvas.save();
        for (int i = 0; i < listPos.size(); i++) {
            if (i % 4 == 0) {
                canvas.drawLine(listPos.get(i), listPos.get(i + 1), listPos.get(i + 2), listPos.get(i + 3), paint);
            }
        }
        //restore()用来恢复画布保存的状态
        canvas.restore();
    }

    public void startAnim(long time) {
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(time);
        //恒定变化速度的interpolator(补间器)
        animator.setInterpolator(new LinearInterpolator());
        //在指定的时间内,将一个数从0变到1,然后动画的每一帧会回调onAnimationUpdate方法
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                invalidate();
            }
        });
        animator.setStartDelay(500);
        animator.start();
    }

  public void destory() {
        listPos.clear();
        invalidate();
    }
}

附上网址

http://mp.weixin.qq.com/s?__biz=MzA4NTc5MDU5OQ==&mid=411441608&idx=1&sn=5e846a882f58a7ba1b5312bdbeaafccf&scene=23&srcid=0120GiYhMXjmNDoN9MFQj7f5#rd
GIF 动图系列 1- 简单法则的魅力

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值