蛛网雷达图
知识点:
1 数学:角度和弧度的关系。
角度和弧度的区别:
角度:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆周长的360分之一时,两条射线的夹角的大小为1度。
弧度:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧度。
由定义可知:圆所对应的弧长是半径的几倍,那么角的大小就是几弧度。
周角(360度)= 2π弧度
平角(180度)= π弧度
在Java中Math类的三角函数接收的参数是弧度,不是角度。
所以2 * Math.PI即表示360°
2 正弦、余弦定理
x = cos(∠AOB) * OA
y = sin(∠AOB) * OA
3 Path的基本用法
moveTo(x,y):移动到坐标点
lineTo(x,y):目前坐标与坐标连线,绘制出一条直线
实现步骤如下:
1 绘制单个多边形
使用canvas.drawPath()绘制多边形
2 绘制多个多边形
3 连线中心到末端
4 绘制分值区域
色值加透明度
1 绘制单个多边形
2 绘制多个多边形
3 连线中心到末端
4 绘制分值区域
整理代码如下:
public class SpiderWebView extends View {
//多边形变数
private int BORDER_COUNT = 8;
//角度:在java中Math类的三角函数接收的参数并不角度,而是弧度,所以需要用2 * Math.PI表示360°
private float mAngel = (float) (2 * Math.PI / BORDER_COUNT);
private int width, height;
//三种Paint:多边形Paint、直线Paint、分值区Paint
private Paint mPaintShape, mPaintLine, mPaintRegion;
//三种Path:图形Path、直线Path,分值区域Path
private Path pathShape, pathLine, pathRegion;
//多边形起始半径
private int radiu = 0;
//中心点坐标
private int centerX, centerY;
public SpiderWebView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SpiderWebView(Context context) {
super(context);
init(context);
}
public void init(Context context) {
//多边形绘制初始化
mPaintShape = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintShape.setColor(getResources().getColor(R.color.black));
mPaintShape.setStyle(Paint.Style.STROKE);
mPaintShape.setStrokeWidth(3);
pathShape = new Path();
//绘制直线初始化
mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintLine.setColor(getResources().getColor(R.color.red));
mPaintLine.setStyle(Paint.Style.STROKE);
mPaintLine.setStrokeWidth(3);
pathLine = new Path();
//绘制域值初始化
mPaintRegion = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintRegion.setColor(Color.parseColor("#7f33b5e5"));//透明度
mPaintRegion.setStyle(Paint.Style.FILL_AND_STROKE);
mPaintRegion.setStrokeWidth(3);
pathRegion = new Path();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.d("lincoln", "onSizeChanged");
width = w;
height = h;
centerX = width / 2;
centerY = height / 2;
radiu = Math.min(width, height) / 2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(getResources().getColor(R.color.azure));
//TODO OnDraw()被调用2次,问题待查找
drawMutilShape(canvas);
drawLine(canvas);
drawRegion(canvas);
}
//1 绘制单个多边形
private void drawSingleShape(Canvas canvas) {
pathShape.moveTo(centerX + radiu, centerX);
for (int index = 0; index < BORDER_COUNT; index++) {
float x = (float) (centerX + Math.cos(index * mAngel) * radiu);
float y = (float) (centerY + Math.sin(index * mAngel) * radiu);
Log.d("lincoln", "drawSingleShape:" + " x:" + x + " y:" + y);
pathShape.lineTo(x, y);
}
pathShape.close();
canvas.drawPath(pathShape, mPaintShape);
}
//2 绘制多个多边形
public void drawMutilShape(Canvas canvas){
//每一份的值
int each = radiu / 5;
//2 绘制多个多边形
for (int index = 0; index < 5; index++) {
Log.d("lincoln", "radiu:" + radiu + " each:" + each);
radiu = radiu - each;
drawSingleShape(canvas);
}
}
//3 多边形对角线相连
private void drawLine(Canvas canvas) {
radiu = Math.min(width, height) / 2;
int each = radiu / 5;
radiu = radiu - each;
for (int index = 0; index < BORDER_COUNT; index++) {
pathLine.moveTo(centerX, centerX);
float x = (float) (centerX + Math.cos(index * mAngel) * radiu);
float y = (float) (centerY + Math.sin(index * mAngel) * radiu);
Log.d("lincoln", "drawLine:" + " x:" + x + " y:" + y);
pathLine.lineTo(x, y);
canvas.drawPath(pathLine, mPaintLine);
}
//TODO 解决2次绘制的bug
radiu = Math.min(width, height) / 2;
}
//4 绘制分值区域
float[] percents = new float[]{
0.2F,
0.6F,
0.8F,
0.5F,
0.6F,
0.9F,
0.2F,
0.8F,
0.3F,
0.7F,
};
public void drawRegion(Canvas canvas) {
radiu = Math.min(width, height) / 2;
int each = radiu / 5;
radiu = radiu - each;
for (int index = 0; index < BORDER_COUNT; index++) {
float x = (float) ( Math.cos(index * mAngel) * radiu * percents[index]);
float y = (float) ( Math.sin(index * mAngel) * radiu * percents[index]);
Log.d("lincoln", "drawRegion:" + " x:" + x + " y:" + y);
if (index == 0) {
pathRegion.moveTo( centerX+x, centerY);
} else {
pathRegion.lineTo(centerX+x, centerY+y);
}
}
pathRegion.close();
canvas.drawPath(pathRegion, mPaintRegion);
radiu = Math.min(width, height) / 2;
}
}
Demo源码:
参考文章
简书当前Markdown语法与效果
安卓自定义View教程目录
简单造轮子系列 - 自定义支持手势旋转的Android Radar Chart(蛛网雷达图)
自定义View——画一个雷达图