淺析簡易k線圖圖表

淺析簡易k線圖圖表

先說下實現的需求: 咱們須要一個x軸分爲12個刻度,x軸最大值爲24. y軸最大刻度值爲180,這樣的一個k線圖,如右圖所示canvas

咱們先來整理下思路:

x最大爲刻度24,y最大值爲180.那麼咱們怎麼去繪製x軸刻度呢? 仔細想一想,x軸分爲12份,最大值24.而且k線圖表的寬度是已知的,那麼咱們等比例計算: xStep(一個刻度)=已知寬度/24。 不就能夠知道一個刻度值是多少了麼?api

那咱們再來分析分析y軸的怎麼處理。數組

如今已知的數值:最大值180,圖表的高度(ps:別糾結圖表高寬怎麼來的啊~會挨板子的。控件生命週期onLayout 哪裏就能夠獲取了) 那麼 參考x軸的計算方式,同樣咱們能夠經過:yStep=已知高度/180.是否是挺簡單的啊。至於駝峯,留到文末再說。有了思路,那麼代碼實現起來就很容易了,寫這篇簡易文章的出發點是想跟你們說說本身日常的我的觀點,不要什麼場景、事物開始前都想着直接找輪子,本身嘗試實現、摸索的過程對於我的是y頗有益的。咳咳咳,很差意思。我跑題了。 回到原點,接下來開始編碼部分:bash

編寫X軸

繼承View 重寫onLayout 獲取已知高寬markdown

@Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getWidth();
        height = getHeight();
    }
複製代碼

按照上面分析的公式,繪製X軸刻度ide

xPaint = new Paint();
        xPaint.setAntiAlias(true);
        xPaint.setStrokeWidth(xlinewidth);
        xPaint.setStrokeCap(Paint.Cap.ROUND);
        xPaint.setColor(xlinecolor);
        
     @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        step = width / 24f;
        y_step = height / 180f;
        canvas.drawLine(0, height, width, height, xPaint);
        for (int i = 0; i <= 12; i++) {
            canvas.drawLine((i * 2) * step, 0, (i * 2) * step, height, xPaint);
        }

       


    }
複製代碼

知道刻度步伐,實現軸刻度是否是簡單多了。 接下來咱們繪製k線吧。 我有一個24長度的集合數據:編碼

ArrayList<Integer> data = new ArrayList<>();
        data.add(10);
        data.add(50);
        data.add(100);
        data.add(40);
        data.add(120);
        data.add(60);
        data.add(80);
        data.add(160);
        data.add(90);
        data.add(80);
        data.add(60);
        data.add(40);
        data.add(20);
        data.add(50);
        data.add(80);
        data.add(100);
        data.add(130);
        data.add(160);
        data.add(180);
        data.add(50);
        data.add(120);
        data.add(100);
        data.add(80);
        data.add(60);
        data.add(10);
複製代碼

集合的角標分別對應x軸的1-24,我想把他們體如今圖標上。那要怎麼作呢? 其實想一想,咱們已知xStep和yStep,那麼不久能夠知道每一個值在每一個刻度的x,y座標了麼? 如 data集合0角標:x座標=xStep1 y座標=yStep10(data集合0角標的值)。 繪製一個點須要x,y就足夠了。 那麼咱們的實現邏輯代碼以下:spa

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        step = width / 24f;
        y_step = height / 180f;
        canvas.drawLine(0, height, width, height, xPaint);
        for (int i = 0; i <= 12; i++) {
            canvas.drawLine((i * 2) * step, 0, (i * 2) * step, height, xPaint);
        }

        Path path = new Path();
        path.moveTo(0, height);
        for (int i = 0; i < data.size(); i++) {
            float x = (i + 1) * step;  //這是x座標
            float y = height - (data.get(i) * y_step);//這是y座標  總高度-y座標,是爲了從下往上

          path.lineTo(x, y);

        }
        canvas.drawPath(path, linePaint);
    }
複製代碼

到了這一步是否是感受特別簡單啊,那麼恭喜你,又收穫了自定義綜合使用路上的小小知識點。畢竟水滴石穿嘛。 言歸正傳,咱們還有最後一個步驟,渲染駝峯呢~~~ 這一步我就不羅嗦了,官方其實有提供api的,小火雞們日常要多查查看看文檔啊(LinearGradient)code

mPaintShader = new Paint();
 mPaintShader.setAntiAlias(true);
 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        step = width / 24f;
        y_step = height / 180f;
        canvas.drawLine(0, height, width, height, xPaint);
        for (int i = 0; i <= 12; i++) {
            canvas.drawLine((i * 2) * step, 0, (i * 2) * step, height, xPaint);
        }



        //繪製折線
        Path path = new Path();
        path.moveTo(0, height);
        for (int i = 0; i < data.size(); i++) {
            float x = (i + 1) * step;  //這是x座標
            float y = height - (data.get(i) * y_step);//這是y座標  總高度-y座標,是爲了從下往上


            path.lineTo(x, y);

        }

        path.lineTo(width, height);
        canvas.drawPath(path, linePaint);


        Shader mShader = new LinearGradient(0, height + 10, 0, 0, getResources().getColor(R.color.colorAccent1), getResources().getColor(R.color.colorAccent5), Shader.TileMode.REPEAT);
//新建一個線性漸變,前兩個參數是漸變開始的點座標,第三四個參數是漸變結束的點的座標。鏈接這2個點就拉出一條漸變線了,
// 。而後那個數組是漸變的顏色。下一個參數是漸變顏色的分佈,若是爲空,每一個顏色就是均勻分佈的。最後是模式,這裏設置的是循環漸變

        mPaintShader.setShader(mShader);
        canvas.drawPath(path, mPaintShader);
    }

複製代碼

回過頭看看,這一切實現起來不麻煩吧,只要日常多分析分析,碰到需求能夠適當嘗試一下本身實現,畢竟技術進階之路不是一味的搬輪子~~不喜勿碰orm

相關文章
相關標籤/搜索