您的位置:首页 > 其它

如何实现炫酷的ArtLine

2016-04-25 17:56 323 查看
看见大神实现了一个自定义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- 简单法则的魅力
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: