图表刻度算法

背景

绘制柱状图、折线图的时候,需要根据数据,动态生成刻度的区间

需求

刻度美观、数据最大的柱状图落在顶部的区间,刻度的数量是固定的。

根据数据渲染刻度
结果预览

固定5个刻度区间,数据最大值与刻度之间的偏移对比如下

输入 每块偏移 第1段 第2段 第3段 第4段 第5段
4 1 1 2 3 4 5
27 6 6 12 18 24 30
174 35 35 70 105 140 175
13500 3000 3000 6000 9000 12000 15000
思路

区间之间的偏移量,为了美观,定义如下

单位数偏移量1~9,参考图表4、27输入
两位数开始:偏移量第二位是5的倍数,第二位以后0,如10、15、20...95 ;三位数100、150、200...950,参考图表174、13500输入

实现算法

核心就是根据最大值/区间得出偏移量,再循环从美观的偏移量里面找到离该值最近的一个大偏移量。
代码是基于java,但是对平台的依赖很少,很容易改改就移植到ios、.net上


 /**
     * 根据位数创建第一个为1的数字
     * <p>
     * 2700 =>1000
     *
     * @param delta
     * @return
     */
    public static int refreshNumber(double delta) {
        int i = 1;

        while (delta >= 10) {
            delta /= 10;
            i *= 10;
        }
        return i;
    }


    /**
     * 获取刻度的区间
     *
     * @param rangeCount 一共几个刻度从底部0开始算,比如0,20,40,60,80,100算6个,之所以不算5个是为了兼容后续的优化
     * @param maxValue   最大值
     * @return
     */
    public static List<Integer> getChartRange(int rangeCount, double maxValue) {
        int resultDelta = 0;
        boolean isFound = false;

        double delta = maxValue / (rangeCount - 1);
        if (delta == 0) delta = 1;

        //从1开始,跳过重复计算,比如delta是2700,则shift从1000开始
        int shift = refreshNumber(delta);

        while (true) {
            //个位数从1~9
            //从10位开始,从10~95 以此类推100~950
            for (float i = 0; i < 10; i += 0.5f) {
                //个位数时9.5会强转成9,相当于9计算了两次,因此不会产生浮点刻度的问题
                resultDelta = (int) (i * shift);

                //找到离自己最大的一个推荐刻度
                if (delta <= resultDelta) {
                    isFound = true;
                    break;
                }
            }
            if (isFound) break;

            shift *= 10;
        }
        List<Integer> list = new ArrayList<>(rangeCount);

        for (int i = 0; i < rangeCount; i++) {
            list.add(i * resultDelta);
        }
        return list;
    }

后续优化

  1. 对浮点型支持,这个很好做,主要是把shift改成0.1f就好了。
  2. 对于差异比较小的大数据进行对比,比如一组数据:331000,331100,331200;这个如果从0开始算的话,视觉上差异很小,这个时候如果换成从331000开始计算,这样对比差异就很直观。方法里我预留了第0个的位置的初衷就是如此。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,736评论 25 709
  • 图表思维是数据分析思维中的最简单和最基本的思维,主要是通过图形和表格对数据进行转化。 文字有局限 看到这段话,你会...
    keeya阅读 5,820评论 1 21
  • 中午和老公视频,问孩子呢?我说隔壁老王来家里吃饭,和老王在外面玩呢!我老公直接问,是谁谁谁吧?我无语了……你就不能...
    7157阅读 111评论 0 0
  • 因为帆帆的机缘,在2016年的最后一天,在太阳公元的幸福客厅,在一个正能量满满的场,我和一群以终身学习为目标的幸福...
    森和阅读 237评论 2 1
  • 大年初四的早晨,浓雾还未散去,外面一片白茫茫,隐约听见楼下说话的声音,便起床下楼看看。原来家里来客人了,只见一位陌...
    夕馨阅读 340评论 0 1