android自定义view-雷达图(蜘蛛网图)

前一段因项目需求,需要使用雷达图来表示一些数据信息,需要展示的效果如下图:
android自定义view-雷达图(蜘蛛网图)_第1张图片
如下是绘制雷达图的思路以及代码:
1.计算出雷达网络的每个点的坐标。
2.连接每个点,绘制出雷达网络
3.绘制圆心点到各个顶点的轴线。
4.绘制各个顶点的标签文字。
5.绘制阴影区域。

第一步 计算出雷达网络的每个点的坐标
雷达图的每个点的坐标,我们首先可以获取雷达区域中心点的x,y坐标,就是整个view的宽度/2和高度/2。
得到中心点的坐标后,然后我们开始计算各个点的坐标,首先计算一条半径上每个刻度点的坐标,例如A点B点的x坐标为centerX+cos(夹角角度)×斜边半径,y坐标为centerY+sin(夹角角度)×斜边半径。C点的 x坐标为centerX-cos(夹角角度)×斜边半径,y坐标为centerY-sin(夹角角度)×斜边半径。
依据不同的斜边长度即依次类推我们可以得到各个点的坐标。
android自定义view-雷达图(蜘蛛网图)_第2张图片

//依圆心坐标,半径,角度,计算出各个xy坐标
public PointF calcArcEndPointXY(float cirX,float cirY, float radius,float cirAngle)
{
   PointF mPointF=new PointF();
   if( Float.compare(cirAngle, 0.0f) == 0 ||Float.compare(radius, 0.0f) == 0   )
   {
       return mPointF;
   }
   float arcAngle = (float) (Math.PI *  div(cirAngle , 180.0f));
   if( Float.compare(arcAngle,0.0f) == -1)
       mPointF.x = mPointF.y = 0.0f;
   if (Float.compare(cirAngle , 90.0f) == -1)
   {
       mPointF.x = add(cirX , (float)Math.cos(arcAngle) * radius);
       mPointF.y = add(cirY , (float)Math.sin(arcAngle) * radius) ;
   }else if (Float.compare(cirAngle,90.0f) == 0){
       mPointF.x = cirX;
       mPointF.y = add(cirY , radius);
   } else if (Float.compare(cirAngle,90.0f) == 1 && Float.compare(cirAngle,180.0f) == -1){
       arcAngle = (float) (Math.PI * (sub(180f , cirAngle)) / 180.0f);
       mPointF.x = sub(cirX , (float) (Math.cos(arcAngle) * radius));
       mPointF.y = add(cirY , (float) (Math.sin(arcAngle) * radius));
   }else if (Float.compare(cirAngle,180.0f) == 0){
       mPointF.x = cirX - radius;
       mPointF.y = cirY;
   }else if (Float.compare(cirAngle,180.0f) == 1 &&Float.compare(cirAngle,270.0f) == -1){
       arcAngle = (float) (Math.PI * ( sub(cirAngle , 180.0f)) / 180.0f);
       mPointF.x = sub(cirX , (float) (Math.cos(arcAngle) * radius));
       mPointF.y = sub(cirY , (float) (Math.sin(arcAngle) * radius));
   }  else if (Float.compare(cirAngle,270.0f) == 0)  {
       mPointF.x = cirX;
       mPointF.y = sub (cirY , radius);
   } else{
       arcAngle = (float) (Math.PI * ( sub(360.0f , cirAngle )) / 180.0f);
       mPointF.x = add(cirX , (float) (Math.cos(arcAngle) * radius)) ;
       mPointF.y = sub(cirY , (float) (Math.sin(arcAngle) * radius));
   }
   return mPointF;
}

第二步 .连接每个点,绘制出雷达网络*
由于我们已经知道各个点的坐标,我们首先把每个圆环里面的各个顶点的坐标来绘制一层,在绘制不同的圆环。我们通过Path类的moveTo和lineTo方法即绘制出如下的效果:

 for(int i=0; i <  mRingCount+1;i++)
        {
            for(int j=0;j < mCornerCount;j++)
            {
                if(j==0)
                {
                    //移动下一次操作的起点位置
                    mRdPath.moveTo( mArrayDotX[i][j], mArrayDotY[i][j]);
                }else{
                    //添加上一个点到当前点之间的直线到Path
                    mRdPath.lineTo( mArrayDotX[i][j], mArrayDotY[i][j]);
                }
            }
            mRdPath.close();
            canvas.drawPath(mRdPath, mPaintLine);
            mRdPath.reset();
        }


android自定义view-雷达图(蜘蛛网图)_第3张图片 **第三步 绘制圆心到各个顶点的轴线** 绘制完雷达图后再继续绘制圆心到各个顶点的轴线。只需要通过drawLine方法传入圆心和顶点的横纵坐标即绘制出各个轴线。 ``` for(int j=0;j < mCornerCount ;j++) { canvas.drawLine(mCenterX,mCenterY, mArrayDotX[mRingCount][j],mArrayDotY[mRingCount][j], mPaintLine); } ```

第四步,绘制各个顶点的标签文字
第一步我们已经得到了最外层圆环各个顶点的坐标。根据标签文字所在的不同象限,这里根据最外层顶点与x,y坐标的比较来确定标签文字的象限。之后对标签文字对应的顶点的横纵坐标加上一定的偏移值来获取各个标签文字的横纵坐标。`

 if(mArrayDotX[mRingCount][j]>mCenterX&&mArrayDotY[mRingCount][j]mCenterX&&mArrayDotY[mRingCount][j]>mCenterY){
     mArrayLabelX[mRingCount][j]=mArrayDotX[mRingCount][j]+30f;
     mArrayLabelY[mRingCount][j]=mArrayDotY[mRingCount][j]+30f;
}else if(mArrayDotX[mRingCount][j]<=mCenterX&&mArrayDotY[mRingCount][j]>mCenterY){
     mArrayLabelX[mRingCount][j]=mArrayDotX[mRingCount][j]-30f;
     mArrayLabelY[mRingCount][j]=mArrayDotY[mRingCount][j]+30f;
}else if(mArrayDotX[mRingCount][j]

第四步,绘制阴影区域,
绘制阴影区域我们根据每个标签点的百分比得到对应的半径长度,之后我们知道角度和圆心坐标和半径长度,同第一步一样我们可以算出对应的五个点左边,然后我们连接各个点的坐标绘制出对应的区域即可。最终的效果就是最开始的图。

github地址:https://github.com/huangruiLearn/CustomView/blob/master/app/src/main/java/com/huel/learn/MyRadarChart.java

你可能感兴趣的:(android自定义view-雷达图(蜘蛛网图))