Android 风向玫瑰图绘制


/**风向玫瑰图绘制Demo,默认使用16个风向
 * Created by yang_lei 2017/3/9.
 */
public class RoseChart extends View {
    //图标尺寸
    private int chart_size;

    private static Context context;

    //传入参数(各个风向百分比)
    private List<Float> percentageList;

    //风向标签
    private final String arrPerLabel[] = new String[]{"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};

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

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

    /**(默认顺时针方向 N-->NNE-->NE-->ENE-->E.....     * @param context
     * @param attrs
     * @param defStyle
     * @param percentageList 风向百分比(默认顺时针方向从正北开始 N-->NNE-->NE-->ENE-->E.....两个方向之间数据不可缺省,数据末尾可以缺省)
     */
    public RoseChart(Context context, AttributeSet attrs, int defStyle, List<Float> percentageList) {
        super(context, attrs, defStyle);

        //初始化 风向百分比 集合
        this.percentageList = percentageList;

        this.context = context;

        /**
         * 获得我们所定义的自定义样式属性
         */
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoseChart, defStyle, 0);
        chart_size = a.getDimensionPixelSize(R.styleable.RoseChart_chart_size, 0);
        a.recycle();

    }

    @Override
    public void onDraw(Canvas canvas) {

        //画布背景
        canvas.drawColor(getResources().getColor(R.color.blue1));

        float cirX = getWidth() / 2;
        float cirY = getHeight() / 2;
        //计算绘制区域半径
        float radius = (float) (getHeight() * 0.42);//150;

        float arcLeft = cirX - radius;
        float arcTop = cirY - radius;
        float arcRight = cirX + radius;
        float arcBottom = cirY + radius;
        RectF arcRF0 = new RectF(arcLeft, arcTop, arcRight, arcBottom);

        //画笔初始化
        Paint PaintArc = new Paint();
        Paint PaintLabel = new Paint();//汉字标识
        PaintLabel.setColor(Color.WHITE);

        PaintLabel.setAntiAlias(true);
        PaintArc.setAntiAlias(true);
        //位置计算类
        XChartCalc xcalc = new XChartCalc();

        float Percentage = 0.0f;
        float CurrPer = 0.0f;//绘制 扇形区域 当前起始角度
        float CurrPerLabel = 0.0f;//绘制 风向标识 当前起始角度
        float NewRaidus = 0.0f;

        //计算每个扇区的圆心角度数
//        Percentage = 360 / arrPerLabel.length;
//        Percentage = (float) (Math.round(Percentage * 100)) / 100;
        Percentage = (float) round(360.00 / arrPerLabel.length, 2);

        //计算起始扇形区域角度(默认顺时针方向 N-->NNE-->NE-->ENE-->E.....填充扇区)
        CurrPer -= (float) round((Percentage - 4) / 2,2);
        CurrPerLabel -= (float) round((Percentage - 4) / 2,2);

        //绘制三个不同百分比同心圆
        PaintLabel.setStyle(Paint.Style.STROKE);
        PaintLabel.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawCircle(cirX, cirY, radius, PaintLabel);
        canvas.drawCircle(cirX, cirY, (float) (radius * 0.75), PaintLabel);
        canvas.drawCircle(cirX, cirY, (float) (radius * 0.5), PaintLabel);
        canvas.drawCircle(cirX, cirY, (float) (radius * 0.25), PaintLabel);

        //绘制三个不同百分比标识
        //1,取出最大百分比
        Float max = Collections.max(percentageList);

        //绘制 风向 扇区
        for (int i = 0; i < percentageList.size(); i++) {
            //将百分比转换为新扇区的半径
            if (percentageList.get(i) == max) {
                NewRaidus = radius;
            } else {
                NewRaidus = radius * (percentageList.get(i) / max);
                NewRaidus = (float) (Math.round(NewRaidus * 100)) / 100;
            }

            float NewarcLeft = cirX - NewRaidus;
            float NewarcTop = cirY - NewRaidus;
            float NewarcRight = cirX + NewRaidus;
            float NewarcBottom = cirY + NewRaidus;
            RectF NewarcRF = new RectF(NewarcLeft, NewarcTop, NewarcRight, NewarcBottom);

            //分配颜色
//            PaintArc.setARGB(255, arrColorRgb[i][0], arrColorRgb[i][1], arrColorRgb[i][2]);
            PaintArc.setColor(getResources().getColor(R.color.yellow1));
            PaintArc.setAlpha(200);
            //在饼图中显示所占比例
            canvas.drawArc(NewarcRF, CurrPer - 90, Percentage - 4, true, PaintArc);

            //下次的起始角度
            CurrPer += Percentage;
        }

        //2,计算每个同心圆半径所占百分比
        float ThreePercentage = max / 4;
        ThreePercentage = (float) (Math.round(ThreePercentage * 100)) / 100;
        //3,绘制百分比标识
        PaintLabel.setColor(getResources().getColor(R.color.red1));
        PaintLabel.setTextSize(getResources().getDimension(R.dimen.RoseChart_persent));
        PaintLabel.setFakeBoldText(true);
        canvas.drawText(ThreePercentage + "%", cirX + (float) (radius * 0.18), cirY-18, PaintLabel);
        canvas.drawText(ThreePercentage * 2 + "%", cirX + (float) (radius * 0.43), cirY-18, PaintLabel);
        canvas.drawText(ThreePercentage * 3 + "%", cirX + (float) (radius * 0.68), cirY-18, PaintLabel);
        canvas.drawText(ThreePercentage * 4 + "%", cirX + (float) (radius * 0.93), cirY-18, PaintLabel);

        //绘制16个外圈风向标识
        for (int j = 0; j < arrPerLabel.length; j++) {
            //计算百分比标签
            xcalc.CalcArcEndPointXY(cirX, cirY, radius, (float) (CurrPerLabel + (Percentage - 4) * 0.5));
            //标识
            PaintLabel.setColor(Color.WHITE);
            PaintLabel.setTextSize(getResources().getDimension(R.dimen.RoseChart_direction));
            PaintLabel.setStrokeWidth((float) 0.8);
            canvas.drawText(arrPerLabel[j], xcalc.getPosX(), xcalc.getPosY(), PaintLabel);
            //下次的起始角度
            CurrPerLabel += Percentage;
        }

        PaintLabel.setColor(Color.BLACK);
        canvas.drawText("author:Yang_lei", cirX - radius, cirY + radius+context.getResources().getDimension(R.dimen.RoseChart_distance4), PaintLabel);

    }

    public static class XChartCalc {
        private static float x;
        private static float y;
        private static float r;

        public static void CalcArcEndPointXY(float cirX, float cirY, float radius, float Percentage) {
            double a = 2 * Math.PI * (Percentage / 360);
            if (Percentage >= 0 && Percentage < 130) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance1);
            } else if (Percentage >= 130 && Percentage < 180) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance2);
            } else if (Percentage == 180) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance3);
            }  else if (Percentage > 180 && Percentage < 240) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance4);
            } else if (Percentage > 240 && Percentage < 270) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance5);
            } else if (Percentage == 270) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance6);
            } else if (Percentage > 270 && Percentage < 300) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance5);
            } else if (Percentage >= 300 && Percentage < 330) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance6);
            } else if (Percentage >=  330 && Percentage < 350){
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance3);
            }
            y = cirY - (float) (r * (Math.cos(a)));
            x = cirX + (float) (r * (Math.sin(a)));
        }

        public static float getPosX() {
            return x;
        }

        public static float getPosY() {
            return y;
        }
    }

    /**返回指定小数位数
     * @param v
     * @param scale
     * @return
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The   scale   must   be   a   positive   integer   or   zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}

<resources>
    <dimen name="RoseChart_persent">10sp</dimen>
    <dimen name="RoseChart_direction">8sp</dimen>

    <dimen name="RoseChart_distance1">4dp</dimen>
    <dimen name="RoseChart_distance2">8dp</dimen>
    <dimen name="RoseChart_distance3">10dp</dimen>
    <dimen name="RoseChart_distance4">16dp</dimen>
    <dimen name="RoseChart_distance5">22dp</dimen>
    <dimen name="RoseChart_distance6">12dp</dimen>
</resources>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值