如何实现炫酷的ArtLine
2016-04-25 17:56
323 查看
看见大神实现了一个自定义view
里面只有两个点,两个点在进行圆周运动,通过绘制两点之间的线,并保存下这些线,实现图片效果。
实现只有短短的几十行代码。我默默的拿来学习了下。主要有以下几点:
- 优雅的实现不断的重绘
- 决定两点的运动轨迹
- 保存绘制的线
ValueAnimator本身不作用于任何对象,从名字也可以了解到,它是对值进行动画,然后通过监听其listener,在动画过程中修改对象的属性值来达到动画的目的。
在实现这个ArtLine的demo中,只是利用了LinearInterpolator(恒定变化速率的补间器)和ValueAnimator的动画监听器。就达到了不断去重绘的目的。
二 、决定两点的运动轨迹
上面已经分析过了,这是两个点的圆周运动,下面这4个值就是a点和B点的坐标。
Math.cos(弧度)返回余弦值,Math.sin(弧度)返回正弦值,
余弦值*R得到X轴上的坐标
正弦值*R得到Y轴上的坐标。
通过每次draw的时候增加弧度,让点做圆周运动。
这里如果在X轴和在Y轴的半径一样,绘制出来的就是正圆,如果两个轴的半径不同,绘制出来的就是椭圆。
我很想录个屏上来啊,但是不会,只能截图了。
比如这样一个形状
它的两点运动轨迹就是这样的。
三、保存绘制的线
上面的两张图都是经过保存的,否则就只能显示一根线,或者两个点
通过改变speedA, speedB, aXR, aYR, bXR, bYR着六个值,就可以出现多种多样的图形,代码很简单,绘制出来的图形多种多样,绘制过程也很迷人,也许这就是简单法则的魅力吧。
给双鱼的自己画个鱼
最后附上完整代码
附上网址
http://mp.weixin.qq.com/s?__biz=MzA4NTc5MDU5OQ==&mid=411441608&idx=1&sn=5e846a882f58a7ba1b5312bdbeaafccf&scene=23&srcid=0120GiYhMXjmNDoN9MFQj7f5#rd
GIF 动图系列 1- 简单法则的魅力
里面只有两个点,两个点在进行圆周运动,通过绘制两点之间的线,并保存下这些线,实现图片效果。
实现只有短短的几十行代码。我默默的拿来学习了下。主要有以下几点:
- 优雅的实现不断的重绘
- 决定两点的运动轨迹
- 保存绘制的线
一、实现不断的重绘界面
大神使用了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- 简单法则的魅力
相关文章推荐
- 欢迎使用CSDN-markdown编辑器
- 获取button所在tableView cell下标
- Android中文API- <merge/> 标签
- JS倒计时,距离某一日期还有多少时间
- android进程间通信:AIDL
- JAVA多线程与并发学习总结
- 用Pyton玩转数据练习题---第二周
- 单例模式中用volatile和synchronized来满足双重检查锁机制
- Android MVP&依赖注入&单元测试
- Android百度地图,定位图标随着方向的改变而改变
- 一小时了解数据挖掘⑥数据挖掘的评估和结果可视化展示
- 一小时了解数据挖掘⑤数据挖掘步骤&常用的聚类、决策树和CRISP-DM概念
- Spark 架构
- MySQL 插入(insert)性能测试
- 设计模式之---责任链模式(Chain of Responsibility)
- salesforce 零基础学习(十九)Permission sets 讲解及设置
- MAC抓包工具charles(青花瓷)
- Meta标签用法大全
- String中“”和“0”转换为Integer过程中出现的问题
- 探索内存大小段存储