echart 使用

来源:互联网 发布:游戏键鼠套装推荐知乎 编辑:程序博客网 时间:2024/06/05 21:49

1.左右y轴零点不对应,分段数不对应
从github上找到的根据传入最大值,最小值,段数,重新生成最大值,最小值,段数。原文地址
https://github.com/ecomfe/echarts/pull/846/commits/f73d6fe154671ac7e73da8decc35696cf9395002
做了一些修改,根据传入左边y轴的分段坐标和零点的位置,强制设置右边y轴零点的位置,分段数,没有零点强制设0
直接调用smartSteps传入最大值,最小值,分段数,根据返回新的最大值最小值,分段数
只有左边y轴
chart.setOption({yAxis:[{max:newMax,min:newMin,interval:newStep}]});
左右y轴
chart.setOption({yAxis:[{max:leftY.max,min:leftY.min,interval:leftY.step},{max:rightY.max,min:rightY.min,interval:rightY.step}]});

/** * echarts 值轴刻度线计算方法 * * @author xieshiwei (谢世威, xieshiwei@baidu.com) *//** * 最值、跨度、步长取近似值 * @function    smartSteps * @param       {Number}    min         最小值 * @param       {Number}    max         最大值 * @param       {Number}    [sections]  段数只能是 [0, 99] 的整数,段数为 0 或者不指定段数时,将自动调整段数 * @param       {Object}    [opts]      其它扩展参数 * @param       {Array}     opts.steps  自定义步长备选值,如 [10, 12, 15, 20, 25, 30, 40, 50, 60, 80] ,但必须 => [10, 99] * @return      {Object}    {min: 新最小值, max: 新最大值, secs: 分段数, step: 每段长, fix: 小数保留位数, pnts: [分段结果]} */    var mySections  = [5, 6];    var mySteps     = [10,20,40,50];    var custSteps   = 0;    var Mt          = Math;    var Math_round  = Mt.round;//四舍五入    var Math_floor  = Mt.floor;//向下取整    var Math_ceil   = Mt.ceil;//向上取整    function Math_log(n) {return Mt.log(n) / Mt.LN10;}    function Math_pow(n) {return Mt.pow(10, n);}//返回10的n次幂    function smartSteps(min, max,sections, pntData, opts) {        // 拿公共变量来接收 opts.steps 这个参数,就不用带着参数层层传递了,注意在函数的最终出口处释放这个值        custSteps   = (opts || {}).steps || mySteps;        //如果opts.steps是(undefined,0,null,""),就是mySteps        sections    = Math_round(+sections || 0) % 99;      // 段数限定在 [0, 99]        min         = +min || 0;        max         = +max || 0;        if (min > max) {max = [min, min = max][0];}         // 最值交换        if(min<0&&max==0){       //如果最小值<0&&最大值=0,设定最大值 = -最小值            max = -min;        }        if((min=="-"||min==""||min==null||min>0)&&max>0){  //如果最小值不明确,最大值>0,让最小值=0            min = 0;        }        //设置从0开始        if(min>0){            min=0;        }        var span    = max - min;        if (span   === 0) {                                 // 跨度为零,即最大值等于最小值的情况            return forSpan0(min, max, sections);        } else if (span < (sections || 5)) {                // 跨度值小于要分的段数,步长必定要小于 1            if (min === Math_round(min) && max === Math_round(max)) { // 步长小于 1 同时两个最值都是整数,特别处理                return forInteger(min, max, sections);            }        }        return coreCalc(min, max, sections,pntData);    };    /**     * 最值、跨度、步长取近似值     * @function    smartSteps.coreCalc     * @description 参数及返回值均同 smartSteps     */    function coreCalc(min, max, sections,pntData, opts) {        custSteps       = custSteps || (opts || {}).steps || mySteps;        var step, newMin, newMax;        var tmpSection  = sections || mySections[mySections.length - 1];        var span        = getCeil(max - min);               // 求 span 的近似值,返回结果是 量级 计数法,c * 10 ^ n ,其中 c => [10, 99]        var expon       = span.n;                           // 为了让后面的计算都以整数进行,设置一个基准量级        span            = span.c;                           // 可以认为,这是跨度的最小近似值,为了满足后继条件,这个值可能会被多次延展        step            = getCeil(span / tmpSection, custSteps); // 跨度最小值 / 段数最大值 是步长最小值        if (step.n      < 0) {                              // 如果跨度小而段数多,步长出现小数时,再次放大有关值,保持整数计算            expon      += step.n;                           // 各种计算的基准量级,保证 步长(最容易出现小数的量) 是整数            span       *= Math_pow(-step.n);            step.n      = 0;        }        step            = step.c * Math_pow(step.n);        var zoom        = Math_pow(expon);        var params      = {            min:    min,            zmin:   min / zoom,            max:    max,            zmax:   max / zoom,            span:   span,            step:   step,            secs:   tmpSection,            exp:    expon        };        if (!sections) {                                    // 不指定 段数 的情况            look4sections(params);        } else {            look4step(params);        }        // 如果原始值都是整数,让输出值也保持整数        if ((min === Math_round(min)) && (max === Math_round(max))) {            step = params.step * zoom;            if (params.exp  < 0 && step !== Math_round(step)) {                step        = Math_floor(step);                span        = step * params.secs;                if (span    < max - min) {                    step   += 1;                    span    = step * params.secs;                }                if (span   >= max   - min) {                    var deltaSpan   = span - (max - min);                    params.max  = Math_round(max + deltaSpan / 2);                    params.min  = Math_round(min - deltaSpan / 2);                    params.step = step;                    params.span = span;                    params.exp  = 0;                }            }        }        var arrMM = cross0(min, max, params.min, params.max); // 避免跨 0        return makeResult(arrMM[0], arrMM[1], params.secs, params.exp,pntData,min,max);    }    function look4sections(params) {        var sections    = params.secs;        var newMin, newMax, tmpSpan, tmpStep;        var minStep     = params.step;        var minSpan     = params.step * sections;           // 上面计算了在最大段数下的最小步长,希望这对整体跨度的影响较小,但其它段数也要尝试一遍        for (var i      = mySections.length - 1; i--;) {            // 有点像二元一次方程,段数 和 步长 两个未知数            // 下面遍历可选的段数,各找一个匹配的步长,然后以 跨度最小 作为最优解的依据            sections    = mySections[i];            tmpStep     = getCeil(params.span / sections, custSteps).d;            newMin      = Math_floor(params.zmin / tmpStep) * tmpStep;            newMax      = Math_ceil(params.zmax / tmpStep) * tmpStep;            tmpSpan     = newMax - newMin;                  // 步长的误差被 段数 成倍放大,可能会给跨度造成更大的误差,使最后的段数大于预期的最大值            if (tmpSpan < minSpan) {                minSpan = tmpSpan;                minStep = tmpStep;            }        }        newMin          = Math_floor(params.zmin / minStep) * minStep;        newMax          = Math_ceil(params.zmax / minStep) * minStep;        sections        = (newMax - newMin) / minStep;        if (sections    < 3) {sections *= 2;}               // 如果查表所得步长比最小步长大得多,那么段数就可能变得很小        params.min      = newMin;        params.max      = newMax;        params.step     = minStep;        params.secs     = sections;    }    function look4step(params) {        var newMax, span;        var newMin      = params.zmax;                          // 主要是找一找个步长,能在指定的段数下,覆盖到原始最值        var step        = params.step;        while (newMin   > params.zmin) {            span        = step * params.secs;            newMax      = Math_ceil(params.zmax / step) * step; // 优先保证 max 端的误差最小,试看 min 值能否被覆盖到            newMin      = newMax - span;            step        = getCeil(step * 1.01, custSteps).d;    // 让 step 的增长允许进入更高一个量级        }        step            = span / params.secs;        var deltaMin    = params.zmin - newMin;                 // 上面的计算可能会让 min 端的误差更大,下面尝试均衡误差        var deltaMax    = newMax - params.zmax;        var deltaDelta  = deltaMin - deltaMax;        if (deltaDelta  >= 20) {                                // 当 min 端的误差比 max 端大很多时,考虑将 newMin newMax 同时上移            deltaDelta  = getCeil(deltaDelta / 2, custSteps, true);            if (params.exp  - deltaDelta.n < 1) {               // 前面对 span 做了放大,所以还要看 误差修正值 与 span 的量级关系                newMin     += deltaDelta.d;                newMax     += deltaDelta.d;            }        }        params.min      = newMin;        params.max      = newMax;        params.step     = step;    }    /**     * 构造返回值,主要是小数计算精度处理     * @param   {Number}    newMin      最小值     * @param   {Number}    newMax      最大值     * @param   {Number}    sections    分段数     * @param   {Number}    [expon]     放大率指数,用于避免小数计算的精度问题     * @return  {Object}                同 smartSteps     */    function makeResult(newMin, newMax, sections, expon,pntData,min,max) {        expon       = expon || 0;        var zoom    = Math_pow(expon);                      //10的expon次幂        var step    = (newMax - newMin) / sections;        var fixTo   = 0;        var points  = [];        for (var i  = sections + 1; i--;) {                 // 因为点数比段数多 1            points[i] = (newMin + step * i) * zoom;         // 如果不涉及小数问题,这里就直接使用数值型        }        if (expon   < 0) {            fixTo   = decimals(zoom);                       // 前面的计算使得 zoom 的小数位数多于 step 的真实小数位,decimal返回小数点后的位数            step    = +(step * zoom).toFixed(fixTo);        // toFixed() number  四舍五入为指定小数位数的数字            fixTo   = decimals(step);                       // 经过上面的处理,可以得到 step 的真实小数位数了            newMin  = +(newMin * zoom).toFixed(fixTo);            newMax  = +(newMax * zoom).toFixed(fixTo);            for (var i = points.length; i--;) {                points[i] = points[i].toFixed(fixTo);       // 为保证小数点对齐,统一转为字符型                +points[i] === 0 && (points[i] = 0);      // 0.000 不好看            }        } else {            newMin *= zoom;            newMax *= zoom;            step   *= zoom;        }        var oldStep=step;        custSteps   = 0;        //划分的阶段没有0值        if(points.indexOf(0)==-1){            var inc =1;            var poi = parseInt(points.length/2);            do{                 var stepone = oldStep*inc;                for(var po = 0;po<points.length;po++){                    points[po]=0;                    if(po<poi){                        points[po]=-(poi-po)*stepone;                    }else if (po==poi){                        points[po]=0;                    }else{                        points[po]=(po-poi)*stepone;                    }                }                    inc++;                    newMin = points[0];                    newMax = points[points.length-1];            }while((max>newMax)||(min<newMin))      }        // custSteps 这个公共变量可能持用了对用户参数的引用        // 这里是函数的最终出口,释放引用          //如果y轴零点不对应,根据传入的做左y轴零点的位置来确定右y轴零点的位置          if(pntData!=null&&pntData!=undefined){             var result= $.inArray(0, pntData);   //确认左y轴零点位置               var result1 = $.inArray(0,points); //确认右y轴零点位置                if((result!=result1)){  //位置不相等                    var intc =1;                    do{                         step = oldStep*intc;                         intc++;                        for(var i=0;i<points.length;i++){                            points[i]=0;                            if(i<result){                                points[i]=-(result-i)*step;                            }else if (i==result){                                points[result]=0;                            }else{                                points[i]=(i-result)*step;                            }                        }                        newMin = points[0];                        newMax = points[points.length-1];                    }while((max>newMax)||(min<newMin))               }          }         return {             min:    newMin,             // 新最小值             max:    newMax,             // 新最大值             secs:   sections,           // 分段数             step:   step,               // 每段长             fix:    fixTo,              // 小数保留位数,0 则为整数             pnts:   points              // 分段结果,整数都是数值型,小数时为了对齐小数点,都是字符型,但其中 0 不带小数点,即没有 "0.000"         };    }    /**     * 求不小于原数的近似数,结果用 量级 计数法表示:c * 10 ^ n ,其中 c n 都是整数,且 c => [10, 99]     * @param   {Number}    num         原数值,不适用于高精度需求     * @param   {Array}     [rounds]    在取近似时,提供预置选项,让 c 近似到 rounds 中的某项     * @param   {Boolean}   [butFloor]  为 true 时不用 Math.ceil 反而用 Math.floor 取近似,原始值 >= c * 10 ^ n     * @return  {Object}    {c: c, n: n, d: d} 其中 c n 都是整数,且 c => [10, 99] ,原始值 <= c * 10 ^ n     */    function getCeil(num, rounds, butFloor) {        var n_10    = Math_floor(Math_log(num)) - 1;        // 类似科学记数法,姑且称为 量级 记数法,故意将指数减 1,于是小数部分被放大 10 倍,以避免小数计算的精度问题        var c_10    = +(num * Math_pow(-n_10)).toFixed(9);  // 此时的 c_10 => [10, 100),下面取近似之后是 [10, 100],toFixed 处理小数精度问题,所以不适用于高精度需求        if (!rounds) {            c_10    = butFloor ? Math_floor(c_10) : Math_ceil(c_10);        } else {            var i;            if (butFloor) {                i   = rounds.length;                while (c_10 < rounds[--i]) {}               // 在预置的近似数中,挑一个最接近但不大于目标值的项,如果挑不出来,则下标溢出 while 结束            } else {                i   = -1;                while (c_10 > rounds[++i]) {}               // 按 接近但不小于目标值 的标准挑数            }            c_10    = custSteps[i];                         // 如果预置数都小于目标值,则下标溢出,c_10 = undefined        }        if (!c_10 || c_10 > 99 || c_10 < 10) {            c_10    = 10;            n_10   += butFloor ? -1 : 1;                    // 如果是向下取近似,则 c_10 一定是向下超出区间 [10, 99] ,所以 n_10 - 1 ,反之亦然        }        return {            c: c_10,            n: n_10,            d: c_10 * Math_pow(n_10)        };    }    /**     * 取一个数的小数位数     * @param   {Number}    num         原数值     * @return  {Number}    decimals    整数则返回 0 ,小数则返回小数点后的位数     */    function decimals(num) {        num     = String(+num).split('.');        return num.length > 1 ? num.pop().length : 0;    }/** * 最大值与最小值相等的情况 * @param min 最小值 * @param max 最大值 * @param sections 步数 */    function forSpan0(min, max, sections) {        sections    = sections || 5;                        // 当最大值等于最小值时,就可以随便分几段了        if (max    == 0) {            return makeResult(0, sections, sections);       // 如果全部值都是 0 ,则以 0 为起点,步长按 1 分段        }        var delta   = Mt.abs(max / sections);               // 以最值为中心,上下各延展一小段        return coreCalc(min - delta, max + delta, sections);    }/** * 最大值减去最小值小于要分的段数的情况 */    function forInteger(min, max, sections) {               // 都是整数,且跨度小于段数,特别处理        sections    = sections || 5;        var span_2  = (sections - max + min) / 2;           // 向上下延展跨度        var newMax  = Math_round(max + span_2);        var newMin  = Math_round(min - span_2);        var arrMM   = cross0(min, max, newMin, newMax);     // 避免跨 0        return makeResult(arrMM[0], arrMM[1], sections);    }    function cross0(min, max, newMin, newMax) {        if (newMin  < 0 && min >= 0) {                      // 当原始值都在 0 以上时,让新值也都在 0 以上            newMax -= newMin;            newMin  = 0;        } else if (newMax > 0 && max <= 0) {                // 尽量不让调整后的最值横跨 0 线            newMin -= newMax;            newMax  = 0;        }        return [newMin, newMax];    }
1 0