ContinuousModel.js 8.5 KB
Newer Older
P
pah100 已提交
1 2 3 4 5
/**
 * @file Data zoom model
 */
define(function(require) {

P
pah100 已提交
6
    var VisualMapModel = require('./VisualMapModel');
P
pah100 已提交
7
    var zrUtil = require('zrender/core/util');
P
pah100 已提交
8
    var numberUtil = require('../../util/number');
P
pah100 已提交
9 10 11

    // Constant
    var DEFAULT_BAR_BOUND = [20, 140];
P
pah100 已提交
12

P
pah100 已提交
13
    var ContinuousModel = VisualMapModel.extend({
P
pah100 已提交
14

15
        type: 'visualMap.continuous',
P
pah100 已提交
16 17 18 19 20

        /**
         * @protected
         */
        defaultOption: {
P
pah100 已提交
21 22 23
            align: 'auto',          // 'auto', 'left', 'right', 'top', 'bottom'
            calculable: false,      // This prop effect default component type determine,
                                    // See echarts/component/visualMap/typeDefaulter.
P
pah100 已提交
24 25 26
            range: null,            // selected range. In default case `range` is [min, max]
                                    // and can auto change along with modification of min max,
                                    // util use specifid a range.
P
pah100 已提交
27 28 29
            realtime: true,         // Whether realtime update.
            itemHeight: null,       // The length of the range control edge.
            itemWidth: null,        // The length of the other side.
P
pah100 已提交
30 31
            hoverLink: true,        // Enable hover highlight.
            hoverLinkDataSize: null,// The size of hovered data.
S
sushuang 已提交
32 33
            hoverLinkOnHandle: null // Whether trigger hoverLink when hover handle.
                                    // If not specified, follow the value of `realtime`.
P
pah100 已提交
34 35 36 37 38
        },

        /**
         * @override
         */
P
pah100 已提交
39 40
        optionUpdated: function (newOption, isInit) {
            ContinuousModel.superApply(this, 'optionUpdated', arguments);
P
pah100 已提交
41

P
pah100 已提交
42
            this.resetTargetSeries();
P
pah100 已提交
43 44
            this.resetExtent();

P
pah100 已提交
45
            this.resetVisual(function (mappingOption) {
P
pah100 已提交
46
                mappingOption.mappingMethod = 'linear';
P
pah100 已提交
47
                mappingOption.dataExtent = this.getExtent();
P
pah100 已提交
48
            });
P
pah100 已提交
49 50 51 52

            this._resetRange();
        },

P
pah100 已提交
53 54 55 56 57
        /**
         * @protected
         * @override
         */
        resetItemSize: function () {
P
pah100 已提交
58
            ContinuousModel.superApply(this, 'resetItemSize', arguments);
P
pah100 已提交
59 60 61 62 63 64 65 66 67

            var itemSize = this.itemSize;

            this._orient === 'horizontal' && itemSize.reverse();

            (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]);
            (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]);
        },

P
pah100 已提交
68 69 70 71 72 73
        /**
         * @private
         */
        _resetRange: function () {
            var dataExtent = this.getExtent();
            var range = this.option.range;
P
pah100 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86

            if (!range || range.auto) {
                // `range` should always be array (so we dont use other
                // value like 'auto') for user-friend. (consider getOption).
                dataExtent.auto = 1;
                this.option.range = dataExtent;
            }
            else if (zrUtil.isArray(range)) {
                if (range[0] > range[1]) {
                    range.reverse();
                }
                range[0] = Math.max(range[0], dataExtent[0]);
                range[1] = Math.min(range[1], dataExtent[1]);
P
pah100 已提交
87 88 89
            }
        },

P
pah100 已提交
90 91 92 93 94
        /**
         * @protected
         * @override
         */
        completeVisualOption: function () {
P
pah100 已提交
95
            VisualMapModel.prototype.completeVisualOption.apply(this, arguments);
P
pah100 已提交
96 97 98 99 100 101 102 103 104

            zrUtil.each(this.stateList, function (state) {
                var symbolSize = this.option.controller[state].symbolSize;
                if (symbolSize && symbolSize[0] !== symbolSize[1]) {
                    symbolSize[0] = 0; // For good looking.
                }
            }, this);
        },

P
pah100 已提交
105 106 107 108 109 110
        /**
         * @override
         */
        setSelected: function (selected) {
            this.option.range = selected.slice();
            this._resetRange();
P
pah100 已提交
111 112
        },

P
pah100 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
        /**
         * @public
         */
        getSelected: function () {
            var dataExtent = this.getExtent();

            var dataInterval = numberUtil.asc(
                (this.get('range') || []).slice()
            );

            // Clamp
            dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]);
            dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]);
            dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]);
            dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]);

            return dataInterval;
        },

P
pah100 已提交
132 133 134 135
        /**
         * @override
         */
        getValueState: function (value) {
P
pah100 已提交
136
            var range = this.option.range;
137 138 139 140 141 142 143 144
            var dataExtent = this.getExtent();

            // When range[0] === dataExtent[0], any value larger than dataExtent[0] maps to 'inRange'.
            // range[1] is processed likewise.
            return (
                (range[0] <= dataExtent[0] || range[0] <= value)
                && (range[1] >= dataExtent[1] || value <= range[1])
            ) ? 'inRange' : 'outOfRange';
P
pah100 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
        },

        /**
         * @params {Array.<number>} range target value: range[0] <= value && value <= range[1]
         * @return {Array.<Object>} [{seriesId, dataIndices: <Array.<number>>}, ...]
         */
        findTargetDataIndices: function (range) {
            var result = [];

            this.eachTargetSeries(function (seriesModel) {
                var dataIndices = [];
                var data = seriesModel.getData();

                data.each(this.getDataDimension(data), function (value, dataIndex) {
                    range[0] <= value && value <= range[1] && dataIndices.push(dataIndex);
                }, true, this);

P
pah100 已提交
162
                result.push({seriesId: seriesModel.id, dataIndex: dataIndices});
P
pah100 已提交
163 164
            }, this);

P
pah100 已提交
165 166 167
            return result;
        },

168 169 170 171 172 173 174 175 176 177 178 179 180 181
        /**
         * @implement
         */
        getVisualMeta: function (getColorVisual) {
            var oVals = getColorStopValues(this, 'outOfRange', this.getExtent());
            var iVals = getColorStopValues(this, 'inRange', this.option.range.slice());
            var stops = [];

            function setStop(value, valueState) {
                stops.push({
                    value: value,
                    color: getColorVisual(value, valueState)
                });
            }
P
pah100 已提交
182

183 184 185 186 187
            // Format to: outOfRange -- inRange -- outOfRange.
            var iIdx = 0;
            var oIdx = 0;
            var iLen = iVals.length;
            var oLen = oVals.length;
188

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
            for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) {
                // If oVal[oIdx] === iVals[iIdx], oVal[oIdx] should be ignored.
                if (oVals[oIdx] < iVals[iIdx]) {
                    setStop(oVals[oIdx], 'outOfRange');
                }
            }
            for (var first = 1; iIdx < iLen; iIdx++, first = 0) {
                // If range is full, value beyond min, max will be clamped.
                // make a singularity
                first && stops.length && setStop(iVals[iIdx], 'outOfRange');
                setStop(iVals[iIdx], 'inRange');
            }
            for (var first = 1; oIdx < oLen; oIdx++) {
                if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) {
                    // make a singularity
                    if (first) {
                        stops.length && setStop(stops[stops.length - 1].value, 'outOfRange');
                        first = 0;
                    }
                    setStop(oVals[oIdx], 'outOfRange');
                }
            }

            var stopsLen = stops.length;

            return {
                stops: stops,
                outerColors: [
                    stopsLen ? stops[0].color : 'transparent',
                    stopsLen ? stops[stopsLen - 1].color : 'transparent'
                ]
            };
P
pah100 已提交
221 222 223 224
        }

    });

P
pah100 已提交
225
    function getColorStopValues(visualMapModel, valueState, dataExtent) {
226
        if (dataExtent[0] === dataExtent[1]) {
P
pah100 已提交
227 228 229
            return dataExtent.slice();
        }

230 231 232 233 234 235
        // When using colorHue mapping, it is not linear color any more.
        // Moreover, canvas gradient seems not to be accurate linear.
        // FIXME
        // Should be arbitrary value 100? or based on pixel size?
        var count = 200;
        var step = (dataExtent[1] - dataExtent[0]) / count;
P
pah100 已提交
236 237 238

        var value = dataExtent[0];
        var stopValues = [];
239
        for (var i = 0; i <= count && value < dataExtent[1]; i++) {
P
pah100 已提交
240 241 242 243 244 245 246 247
            stopValues.push(value);
            value += step;
        }
        stopValues.push(dataExtent[1]);

        return stopValues;
    }

P
pah100 已提交
248 249
    return ContinuousModel;

P
pah100 已提交
250
});