Time.js 5.1 KB
Newer Older
L
lang 已提交
1 2 3 4 5 6 7 8
/**
 * Interval scale
 * @module echarts/coord/scale/Time
 */

define(function (require) {

    var zrUtil = require('zrender/core/util');
P
pah100 已提交
9
    var numberUtil = require('../util/number');
D
deqingli 已提交
10
    var formatUtil = require('../util/format');
L
lang 已提交
11 12 13 14 15 16 17

    var IntervalScale = require('./Interval');

    var intervalScaleProto = IntervalScale.prototype;

    var mathCeil = Math.ceil;
    var mathFloor = Math.floor;
18
    var ONE_DAY = 3600000 * 24;
L
lang 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31

    // FIXME 公用?
    var bisect = function (a, x, lo, hi) {
        while (lo < hi) {
            var mid = lo + hi >>> 1;
            if (a[mid][2] < x) {
                lo = mid + 1;
            }
            else {
                hi  = mid;
            }
        }
        return lo;
L
Comma  
lang 已提交
32
    };
L
lang 已提交
33 34 35 36 37

    /**
     * @alias module:echarts/coord/scale/Time
     * @constructor
     */
L
lang 已提交
38
    var TimeScale = IntervalScale.extend({
L
lang 已提交
39 40 41 42 43 44 45 46
        type: 'time',

        // Overwrite
        getLabel: function (val) {
            var stepLvl = this._stepLvl;

            var date = new Date(val);

D
deqingli 已提交
47
            return formatUtil.formatTime(stepLvl[0], date);
L
lang 已提交
48 49
        },

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
        // Overwrite
        niceExtent: function (approxTickNum, fixMin, fixMax) {
            var extent = this._extent;
            // If extent start and end are same, expand them
            if (extent[0] === extent[1]) {
                // Expand extent
                extent[0] -= ONE_DAY;
                extent[1] += ONE_DAY;
            }
            // If there are no data and extent are [Infinity, -Infinity]
            if (extent[1] === -Infinity && extent[0] === Infinity) {
                var d = new Date();
                extent[1] = new Date(d.getFullYear(), d.getMonth(), d.getDate());
                extent[0] = extent[1] - ONE_DAY;
            }

            this.niceTicks(approxTickNum, fixMin, fixMax);

            // var extent = this._extent;
            var interval = this._interval;

            if (!fixMin) {
                extent[0] = numberUtil.round(mathFloor(extent[0] / interval) * interval);
            }
            if (!fixMax) {
                extent[1] = numberUtil.round(mathCeil(extent[1] / interval) * interval);
            }
        },

L
lang 已提交
79 80 81 82 83
        // Overwrite
        niceTicks: function (approxTickNum) {
            approxTickNum = approxTickNum || 10;

            var extent = this._extent;
L
Comma  
lang 已提交
84
            var span = extent[1] - extent[0];
L
lang 已提交
85 86 87 88 89 90
            var approxInterval = span / approxTickNum;
            var scaleLevelsLen = scaleLevels.length;
            var idx = bisect(scaleLevels, approxInterval, 0, scaleLevelsLen);

            var level = scaleLevels[Math.min(idx, scaleLevelsLen - 1)];
            var interval = level[2];
91 92
            // Same with interval scale if span is much larger than 1 year
            if (level[0] === 'year') {
L
lang 已提交
93 94 95 96 97 98 99
                var yearSpan = span / interval;

                // From "Nice Numbers for Graph Labels" of Graphic Gems
                var niceYearSpan = numberUtil.nice(yearSpan, false);
                var yearStep = numberUtil.nice(niceYearSpan / approxTickNum, true);

                interval *= yearStep;
100
            }
L
lang 已提交
101 102 103 104 105 106 107 108 109 110

            var niceExtent = [
                mathCeil(extent[0] / interval) * interval,
                mathFloor(extent[1] / interval) * interval
            ];

            this._stepLvl = level;
            // Interval will be used in getTicks
            this._interval = interval;
            this._niceExtent = niceExtent;
111 112 113 114 115
        },

        parse: function (val) {
            // val might be float.
            return +numberUtil.parseDate(val);
L
lang 已提交
116
        }
L
lang 已提交
117
    });
L
lang 已提交
118

L
lang 已提交
119
    zrUtil.each(['contain', 'normalize'], function (methodName) {
L
lang 已提交
120
        TimeScale.prototype[methodName] = function (val) {
121
            return intervalScaleProto[methodName].call(this, this.parse(val));
L
lang 已提交
122
        };
L
lang 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    });

    // Steps from d3
    var scaleLevels = [
        // Format       step    interval
        ['hh:mm:ss',    1,      1000],           // 1s
        ['hh:mm:ss',    5,      1000 * 5],       // 5s
        ['hh:mm:ss',    10,     1000 * 10],      // 10s
        ['hh:mm:ss',    15,     1000 * 15],      // 15s
        ['hh:mm:ss',    30,     1000 * 30],      // 30s
        ['hh:mm\nMM-dd',1,      60000],          // 1m
        ['hh:mm\nMM-dd',5,      60000 * 5],      // 5m
        ['hh:mm\nMM-dd',10,     60000 * 10],     // 10m
        ['hh:mm\nMM-dd',15,     60000 * 15],     // 15m
        ['hh:mm\nMM-dd',30,     60000 * 30],     // 30m
        ['hh:mm\nMM-dd',1,      3600000],        // 1h
        ['hh:mm\nMM-dd',2,      3600000 * 2],    // 2h
        ['hh:mm\nMM-dd',6,      3600000 * 6],    // 6h
        ['hh:mm\nMM-dd',12,     3600000 * 12],   // 12h
142 143 144 145 146 147
        ['MM-dd\nyyyy', 1,      ONE_DAY],   // 1d
        ['week',        7,      ONE_DAY * 7],        // 7d
        ['month',       1,      ONE_DAY * 31],       // 1M
        ['quarter',     3,      ONE_DAY * 380 / 4],  // 3M
        ['half-year',   6,      ONE_DAY * 380 / 2],  // 6M
        ['year',        1,      ONE_DAY * 380]       // 1Y
L
lang 已提交
148 149 150 151 152 153 154
    ];

    /**
     * @return {module:echarts/scale/Time}
     */
    TimeScale.create = function () {
        return new TimeScale();
L
lang 已提交
155
    };
L
lang 已提交
156 157 158

    return TimeScale;
});