zoukankan      html  css  js  c++  java
  • 使用Canvas和Paint自己绘制折线图

    主要用于Canvas一个特别简单的小demo。

    能够手动点击看每一个月份的数据。很easy。就是用paint在canvas上画出来的。

    主要内容就是计算左边价格的位置,以下日期的位置,三根虚线的位置,五个点四根折线加价格标签的位置。

    绿色价格标签是由一个圆角矩形一个三角形加一个text组成的。能够依据点击的位置在五个点上面显示。

    两种方式:一种加动画一种不带动画。带动画的就是先显示五个点,然后折线从左往右显示

    动画的实现是用handler不断改变须要画的折线的坐标的位置,然后一路画过去。

    代码例如以下。须要的能够去github自行下载。

    喜欢的请star

    public class ChartView extends ImageView {
    
        /**
         * 须要传入一个ChartBeanList,里面包括表格上显示的每一个点的信息。包括时间点和价格
         * 
         */
    
        public static int height = 300;
        public static double width = 600;
    
        private int heightReal;// 图表实际的高度
        private int heightText = 70;// 底部显示时间的区域
        private int heightTop = 0;// 图表上面的空白区
    
        private int multi = 1;// 用来适配各种分辨率的机器的,为倍数
        private int radi = 5 * multi;// 圆点的半径
    
        private int widthReal;// 图表实际的宽度
        private int widthText = 50 * multi;// 图表左边显示价格的区域
        private int widthHead = 50;// 价格区域右边,图表左边的空白区
        private int widthFoot = 25 * multi;
        private int miles = 5;// 增长的毫秒数
        private int px = 10;// 每毫秒添加的像素数
        private boolean hasAnim = false;
    
        private double x1 = 0;
        private double x2 = 0;
        private double x3 = 0;
        private double x4 = 0;
        private double x5 = 0;
    
        private PointF p1 = new PointF();
        private PointF p2 = new PointF();
        private PointF p3 = new PointF();
        private PointF p4 = new PointF();
        private PointF p5 = new PointF();
        private float p2x;
        private float p3x;
        private float p4x;
        private float p5x;
        private float p2y;
        private float p3y;
        private float p4y;
        private float p5y;
        boolean p2Init = true;
        boolean isFirstRun = true;
        boolean x1Complete = true;
        boolean x2Complete = false;
        boolean x3Complete = false;
        boolean x4Complete = false;
        boolean x5Complete = false;
        private double min = 0d;
        private double max = 100000d;
        private PointF pic;
        private List<ChartBean> mChartBeanList = new ArrayList<ChartBean>();
        private double price;
        private String unit = "元/斤";
        private MyHandler handler;
        private Paint p;
        private float left;
        private float top;
        private float right;
        private float bottom;
        private int textWidth;
    
        public ChartView(Context context) {
            super(context);
            init();
        }
    
        public ChartView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        public ChartView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            handler = new MyHandler();
    
        }
    
        public void setData(List<ChartBean> list, String unit, boolean hasAnim) {
            this.mChartBeanList = list;
            this.hasAnim = hasAnim;
            if ("".equals(unit)) {
                this.unit = unit;
            }
            // 4,6,2,3,5
            try {
                x1 = list.get(0).getPrice();
                x2 = list.get(1).getPrice();
                x3 = list.get(2).getPrice();
                x4 = list.get(3).getPrice();
                x5 = list.get(4).getPrice();
            } catch (Exception e) {
                e.printStackTrace();
            }
            max = list.get(0).getPrice();
            for (int i = 0; i < list.size(); i++) {
                if (max < list.get(i).getPrice()) {
                    max = list.get(i).getPrice();
                }
            }
        }
    
        public void setMaxMin(double max, double min) {
        }
    
        @SuppressLint("DrawAllocation")
        @Override
        protected void onDraw(Canvas canvas) {
    
            super.onDraw(canvas);
            p = new Paint();
            p.setAntiAlias(true);
            p.setColor(Color.GRAY);
            p.setTypeface(Typeface.DEFAULT);
            Path path = new Path();
    
            width = canvas.getWidth();
            height = canvas.getHeight();
            multi = (int) Math.ceil(width / 560);
            int width = canvas.getWidth();
            widthText = 50 * multi;// 图表左边显示价格的区域
            widthFoot = 25 * multi;
            radi = 5 * multi;
    
            heightTop = 0;
            heightReal = height - heightText - heightTop;
            heightTop = heightReal / 4;
            heightReal = height - heightText - heightTop;
            widthReal = ((int) width - widthText - widthHead - widthFoot);
    
            /** 画左边的价格文字 */
            p.setTextSize(17 * multi);
            canvas.drawText(String.format("%.2f", (min + (max - min))), widthText - 35 * multi, heightTop, p);
            canvas.drawText(String.format("%.2f", (min + (max - min) * 2 / 3)), widthText - 35 * multi, heightTop
                    + heightReal / 3, p);
            canvas.drawText(String.format("%.2f", (min + (max - min) / 3)), widthText - 35 * multi, heightTop + heightReal
                    * 2 / 3, p);
            canvas.drawText(unit, widthText - 35 * multi - 5, heightTop + heightReal + 5, p);
            /** 画底下的日期文字 */
            try {
                switch (mChartBeanList.size()) {
                case 5:
                    canvas.drawText(mChartBeanList.get(4).getDate() + "", widthText + widthReal, 50 + heightTop
                            + heightReal, p);
                case 4:
                    canvas.drawText(mChartBeanList.get(3).getDate() + "", widthText + widthReal * 3 / 4, 50 + heightTop
                            + heightReal, p);
                case 3:
                    canvas.drawText(mChartBeanList.get(2).getDate() + "", widthText + widthReal / 2, 50 + heightTop
                            + heightReal, p);
                case 2:
                    canvas.drawText(mChartBeanList.get(1).getDate() + "", widthText + widthReal / 4, 50 + heightTop
                            + heightReal, p);
                case 1:
                    canvas.drawText(mChartBeanList.get(0).getDate() + "", widthText, 50 + heightTop + heightReal, p);
                case 0:
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            p1.x = widthText + widthHead;
            p1.y = (float) (heightTop + getHeight(x1));
            p2.x = widthText + widthHead + widthReal / 4;
            p2.y = (float) (heightTop + getHeight(x2));
            p3.x = widthText + widthHead + widthReal / 2;
            p3.y = (float) (heightTop + getHeight(x3));
            p4.x = widthText + widthHead + widthReal * 3 / 4;
            p4.y = (float) (heightTop + getHeight(x4));
            p5.x = widthText + widthHead + widthReal;
            p5.y = (float) (heightTop + getHeight(x5));
            if (p2Init) {
                /** 初始化pp2 */
                p2x = p1.x;
                p2y = p1.y;
                p2Init = false;
            }
    
            /** 最底下的粗线 */
            p.setColor(Color.GRAY);
            p.setStrokeWidth(2);
            canvas.drawLine(widthText, heightTop + heightReal, (float) width, heightTop + heightReal, p);
    
            /** 画三根虚线 */
            p.setColor(Color.GRAY);
            p.setStrokeWidth(1);
            p.setStyle(Paint.Style.STROKE);
            PathEffect effects = new DashPathEffect(new float[] { 5, 5, 5, 5 }, 1);
            p.setPathEffect(effects);
            path.moveTo(widthText, heightTop + heightReal * 2 / 3);
            path.lineTo(width, heightTop + heightReal * 2 / 3);
            canvas.drawPath(path, p);
            path.moveTo(widthText, heightTop + heightReal / 3);
            path.lineTo(width, heightTop + heightReal / 3);
            canvas.drawPath(path, p);
            path.moveTo(widthText, heightTop);
            path.lineTo(width, heightTop);
            canvas.drawPath(path, p);
            p.setStyle(Paint.Style.FILL);
            p.setColor(getResources().getColor(R.color.green_chart));
            p.setStrokeWidth(3 * multi);
            /** 几个点连起来的折线 */
            try {
                switch (mChartBeanList.size()) {
                case 0:
                    break;
                case 1:
                    canvas.drawCircle(p1.x, p1.y, radi, p);
                    if (pic == null) {
                        pic = new PointF();
                        pic = p1;
                        price = x1;
                    }
                    break;
                case 2:
                    drawLine(canvas, p);
                    canvas.drawCircle(p1.x, p1.y, radi, p);
                    canvas.drawCircle(p2.x, p2.y, radi, p);
                    if (pic == null) {
                        pic = new PointF();
                        pic = p2;
                        price = x2;
                    }
                    break;
                case 3:
                    drawLine(canvas, p);
                    canvas.drawCircle(p1.x, p1.y, radi, p);
                    canvas.drawCircle(p2.x, p2.y, radi, p);
                    canvas.drawCircle(p3.x, p3.y, radi, p);
                    if (pic == null) {
                        pic = new PointF();
                        pic = p3;
                        price = x3;
                    }
                    break;
                case 4:
                    drawLine(canvas, p);
                    canvas.drawCircle(p1.x, p1.y, radi, p);
                    canvas.drawCircle(p2.x, p2.y, radi, p);
                    canvas.drawCircle(p3.x, p3.y, radi, p);
                    canvas.drawCircle(p4.x, p4.y, radi, p);
                    if (pic == null) {
                        pic = new PointF();
                        pic = p4;
                        price = x4;
                    }
                    break;
                case 5:
                    drawLine(canvas, p);
                    canvas.drawCircle(p1.x, p1.y, radi, p);
                    canvas.drawCircle(p2.x, p2.y, radi, p);
                    canvas.drawCircle(p3.x, p3.y, radi, p);
                    canvas.drawCircle(p4.x, p4.y, radi, p);
                    canvas.drawCircle(p5.x, p5.y, radi, p);
                    if (pic == null) {
                        pic = new PointF();
                        pic = p5;
                        price = x5;
                    }
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            /** 画圆角矩形 */
            if (pic != null) {
                // p = new Paint();
                p.setAntiAlias(true);// 设置画笔的锯齿效果
                p.setPathEffect(new PathEffect());
                p.setColor(getResources().getColor(R.color.green_chart_dark));
                textWidth = getTextWidth(p, String.format("%.2f", price));
                left = pic.x - textWidth / 2;
                top = pic.y - 35 * multi;
                right = pic.x + textWidth / 2 + 5;
                bottom = pic.y - 15 * multi;
                RectF oval3 = new RectF(left, top, right, bottom);// 设置个新的长方形
                canvas.drawRoundRect(oval3, 10, 10, p);// 第二个參数是x半径。第三个參数是y半径
                path.moveTo(pic.x, pic.y - 5 * multi);
                path.lineTo((left + right) / 2 - 5 * multi, bottom);
                path.lineTo((left + right) / 2 + 5 * multi, bottom);
                path.lineTo(pic.x, pic.y - 5 * multi);
                canvas.drawPath(path, p);
                p.setColor(Color.WHITE);
                p.setTextSize(14 * multi);
                canvas.drawText(String.format("%.2f", price), pic.x - textWidth / 2 + 5, pic.y - 20 * multi, p);
            }
    
            if (hasAnim) {
                handler.sendEmptyMessageDelayed(0, miles);
            }
        }
    
        public static int getTextWidth(Paint paint, String str) {
            int iRet = 0;
            if (str != null && str.length() > 0) {
                int len = str.length();
                float[] widths = new float[len];
                paint.getTextWidths(str, widths);
                for (int j = 0; j < len; j++) {
                    iRet += (int) Math.ceil(widths[j]);
                }
            }
            return iRet;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int action = event.getAction();
            switch (action) {
            case MotionEvent.ACTION_MOVE:
                reFreshPic(event);
                break;
            case MotionEvent.ACTION_DOWN:
                reFreshPic(event);
                break;
            case MotionEvent.ACTION_UP:
                reFreshPic(event);
                break;
            }
    
            return super.onTouchEvent(event);
        }
    
        private void reFreshPic(MotionEvent event) {
            float x = event.getX();
            int[] location = new int[2];
            this.getLocationOnScreen(location);
            float offsetX = x - widthText - widthHead;
            if (offsetX < widthReal / 8) {
                pic = p1;
                price = x1;
            } else if (offsetX > widthReal / 8 && offsetX < widthReal * 3 / 8) {
                pic = p2;
                price = x2;
            } else if (offsetX > widthReal * 3 / 8 && offsetX < widthReal * 5 / 8) {
                pic = p3;
                price = x3;
            } else if (offsetX > widthReal * 5 / 8 && offsetX < widthReal * 7 / 8) {
                pic = p4;
                price = x4;
            } else if (offsetX > widthReal * 7 / 8) {
                pic = p5;
                price = x5;
            }
            this.invalidate();
        }
    
        /**
         * 依据传入的价格得到须要展示在view中的Y坐标
         * 
         * max:最大值 min:最小值 height:图表的高度
         * 
         * @param x
         * @return
         */
        public double getHeight(double x) {
            if (max - min == 0) {
                return 0;
            } else {
                return (max - x) / (max - min) * heightReal;
            }
        }
    
        public void drawLine(Canvas canvas, Paint p) {
            switch (mChartBeanList.size()) {
            case 0:
                break;
            case 1:
                break;
            case 2:
                if (hasAnim) {
                    if (x1Complete) {
                        canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
                    }
                } else {
                    canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
                }
                break;
            case 3:
                if (hasAnim) {
                    if (x1Complete) {
                        canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
                    }
                    if (x2Complete) {
                        canvas.drawLine(p2x, p2y, p3x, p3y, p);
                    }
                } else {
                    canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
                    canvas.drawLine(p2.x, p2.y, p3.x, p3.y, p);
                }
                break;
            case 4:
                if (hasAnim) {
                    if (x1Complete) {
                        canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
                    }
                    if (x2Complete) {
                        canvas.drawLine(p2x, p2y, p3x, p3y, p);
                    }
                    if (x3Complete) {
                        canvas.drawLine(p3x, p3y, p4x, p4y, p);
                    }
                } else {
                    canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
                    canvas.drawLine(p2.x, p2.y, p3.x, p3.y, p);
                    canvas.drawLine(p3.x, p3.y, p4.x, p4.y, p);
                }
                break;
            case 5:
                if (hasAnim) {
                    if (x1Complete) {
                        canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
                    }
                    if (x2Complete) {
                        canvas.drawLine(p2x, p2y, p3x, p3y, p);
                    }
                    if (x3Complete) {
                        canvas.drawLine(p3x, p3y, p4x, p4y, p);
                    }
                    if (x4Complete) {
                        canvas.drawLine(p4x, p4y, p5x, p5y, p);
                    }
                } else {
                    canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
                    canvas.drawLine(p2.x, p2.y, p3.x, p3.y, p);
                    canvas.drawLine(p3.x, p3.y, p4.x, p4.y, p);
                    canvas.drawLine(p4.x, p4.y, p5.x, p5.y, p);
                }
                break;
            }
        }
    
        class MyHandler extends Handler {
            public MyHandler() {
            }
    
            public MyHandler(Looper L) {
                super(L);
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (p2x < p2.x) {
                    p2x = p2x + px;
                    p2y = p2y + (p2.y - p1.y) / (p2.x - p1.x) * px;
                    // pp2.x++;
                    // pp2.y = pp2.y + (p2.y - p1.y) / (p2.x - p1.x) * 1;
                    x1Complete = true;
                    ChartView.this.invalidate();
                    p3x = p2x;
                    System.out.println("p2y--" + p2y);
                    p3y = p2y;
                } else if (p3x < p3.x) {
                    p3x = p3x + px;
                    p3y = p3y + (p3.y - p2.y) / (p3.x - p2.x) * px;
                    System.out.println("2");
                    // pp3.x = pp3.x + 1;
                    // pp3.y = pp3.y + (p3.y - p2.y) / (p3.x - p2.x) * 1;
                    ChartView.this.invalidate();
                    x2Complete = true;
                    p4x = p3x;
                    p4y = p3y;
                } else if (p4x < p4.x) {
                    System.out.println("3");
                    p4x = p4x + px;
                    p4y = p4y + (p4.y - p3.y) / (p4.x - p3.x) * px;
                    // pp4.x = pp4.x + 1;
                    // pp4.y = pp4.y + (p4.y - p3.y) / (p4.x - p3.x) * 1;
                    ChartView.this.invalidate();
                    x3Complete = true;
                    p5x = p4x;
                    p5y = p4y;
                } else if (p5x < p5.x) {
                    p5x = p5x + px;
                    System.out.println("4");
                    p5y = p5y + (p5.y - p4.y) / (p5.x - p4.x) * px;
                    // pp5.x = pp5.x + 1;
                    // pp5.y = pp5.y + (p5.y - p4.y) / (p5.x - p4.x) * 1;
                    ChartView.this.invalidate();
                    x4Complete = true;
                } else {
                    System.out.println("return");
                    return;
                }
            }
        }
    }


    https://github.com/yocn/chartView​

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    node-log4js3.0.6配置
    MySQL命令学习
    64位 windows10,MYSQL8.0.13重置密码(忘记密码或者无法登录)
    64位 windows10,安装配置MYSQL8.0.13
    vscode切换界面布局
    一个网站同时监听两个端口
    javascript +new Date()
    es6 解构
    react列表数据显示
    访问禁止,检测到可疑访问,事件编号
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4656237.html
Copyright © 2011-2022 走看看