Android 风向玫瑰图绘制

来源:互联网 发布:颜值评分软件 编辑:程序博客网 时间:2024/04/29 15:21
/**风向玫瑰图绘制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>

0 0