markerHelper.js 6.1 KB
Newer Older
S
sushuang 已提交
1
import * as zrUtil from 'zrender/core/util';
S
sushuang 已提交
2
import * as numberUtil from '../../util/number';
L
lang 已提交
3

S
sushuang 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
var indexOf = zrUtil.indexOf;

function hasXOrY(item) {
    return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y)));
}

function hasXAndY(item) {
    return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y));
}

function getPrecision(data, valueAxisDim, dataIndex) {
    var precision = -1;
    do {
        precision = Math.max(
            numberUtil.getPrecision(data.get(
                valueAxisDim, dataIndex
            )),
            precision
        );
        data = data.stackedOn;
    } while (data);

    return precision;
}

function markerTypeCalculatorWithExtent(
    mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex
) {
    var coordArr = [];
    var value = numCalculate(data, targetDataDim, mlType);

    var dataIndex = data.indicesOfNearest(targetDataDim, value, true)[0];
    coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex, true);
    coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex, true);

    var precision = getPrecision(data, targetDataDim, dataIndex);
    precision = Math.min(precision, 20);
    if (precision >= 0) {
        coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
L
tweak  
lang 已提交
43
    }
L
lang 已提交
44

S
sushuang 已提交
45 46
    return coordArr;
}
L
lang 已提交
47

S
sushuang 已提交
48 49 50
var curry = zrUtil.curry;
// TODO Specified percent
var markerTypeCalculator = {
L
tweak  
lang 已提交
51
    /**
S
sushuang 已提交
52 53 54 55
     * @method
     * @param {module:echarts/data/List} data
     * @param {string} baseAxisDim
     * @param {string} valueAxisDim
L
tweak  
lang 已提交
56
     */
S
sushuang 已提交
57 58 59 60 61 62 63 64
    min: curry(markerTypeCalculatorWithExtent, 'min'),
    /**
     * @method
     * @param {module:echarts/data/List} data
     * @param {string} baseAxisDim
     * @param {string} valueAxisDim
     */
    max: curry(markerTypeCalculatorWithExtent, 'max'),
L
tweak  
lang 已提交
65 66

    /**
S
sushuang 已提交
67 68 69 70
     * @method
     * @param {module:echarts/data/List} data
     * @param {string} baseAxisDim
     * @param {string} valueAxisDim
L
tweak  
lang 已提交
71
     */
S
sushuang 已提交
72 73 74 75 76 77 78 79 80 81 82 83
    average: curry(markerTypeCalculatorWithExtent, 'average')
};

/**
 * Transform markPoint data item to format used in List by do the following
 * 1. Calculate statistic like `max`, `min`, `average`
 * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array
 * @param  {module:echarts/model/Series} seriesModel
 * @param  {module:echarts/coord/*} [coordSys]
 * @param  {Object} item
 * @return {Object}
 */
S
sushuang 已提交
84
export function dataTransform(seriesModel, item) {
S
sushuang 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    var data = seriesModel.getData();
    var coordSys = seriesModel.coordinateSystem;

    // 1. If not specify the position with pixel directly
    // 2. If `coord` is not a data array. Which uses `xAxis`,
    // `yAxis` to specify the coord on each dimension

    // parseFloat first because item.x and item.y can be percent string like '20%'
    if (item && !hasXAndY(item) && !zrUtil.isArray(item.coord) && coordSys) {
        var dims = coordSys.dimensions;
        var axisInfo = getAxisInfo(item, data, coordSys, seriesModel);

        // Clone the option
        // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value
        item = zrUtil.clone(item);

        if (item.type
            && markerTypeCalculator[item.type]
            && axisInfo.baseAxis && axisInfo.valueAxis
        ) {
            var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim);
            var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim);

            item.coord = markerTypeCalculator[item.type](
                data, axisInfo.baseDataDim, axisInfo.valueDataDim,
                otherCoordIndex, targetCoordIndex
            );
            // Force to use the value of calculated value.
            item.value = item.coord[targetCoordIndex];
114 115
        }
        else {
S
sushuang 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128
            // FIXME Only has one of xAxis and yAxis.
            var coord = [
                item.xAxis != null ? item.xAxis : item.radiusAxis,
                item.yAxis != null ? item.yAxis : item.angleAxis
            ];
            // Each coord support max, min, average
            for (var i = 0; i < 2; i++) {
                if (markerTypeCalculator[coord[i]]) {
                    var dataDim = seriesModel.coordDimToDataDim(dims[i])[0];
                    coord[i] = numCalculate(data, dataDim, coord[i]);
                }
            }
            item.coord = coord;
129
        }
S
sushuang 已提交
130 131
    }
    return item;
S
sushuang 已提交
132
}
S
sushuang 已提交
133

S
sushuang 已提交
134
export function getAxisInfo(item, data, coordSys, seriesModel) {
S
sushuang 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    var ret = {};

    if (item.valueIndex != null || item.valueDim != null) {
        ret.valueDataDim = item.valueIndex != null
            ? data.getDimension(item.valueIndex) : item.valueDim;
        ret.valueAxis = coordSys.getAxis(seriesModel.dataDimToCoordDim(ret.valueDataDim));
        ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
        ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0];
    }
    else {
        ret.baseAxis = seriesModel.getBaseAxis();
        ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
        ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0];
        ret.valueDataDim = seriesModel.coordDimToDataDim(ret.valueAxis.dim)[0];
    }

    return ret;
S
sushuang 已提交
152
}
S
sushuang 已提交
153 154 155 156 157 158 159 160

/**
 * Filter data which is out of coordinateSystem range
 * [dataFilter description]
 * @param  {module:echarts/coord/*} [coordSys]
 * @param  {Object} item
 * @return {boolean}
 */
S
sushuang 已提交
161
export function dataFilter(coordSys, item) {
S
sushuang 已提交
162 163 164
    // Alwalys return true if there is no coordSys
    return (coordSys && coordSys.containData && item.coord && !hasXOrY(item))
        ? coordSys.containData(item.coord) : true;
S
sushuang 已提交
165
}
S
sushuang 已提交
166

S
sushuang 已提交
167
export function dimValueGetter(item, dimName, dataIndex, dimIndex) {
S
sushuang 已提交
168 169 170 171 172
    // x, y, radius, angle
    if (dimIndex < 2) {
        return item.coord && item.coord[dimIndex];
    }
    return item.value;
S
sushuang 已提交
173
}
S
sushuang 已提交
174

S
sushuang 已提交
175
export function numCalculate(data, valueDataDim, type) {
S
sushuang 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189
    if (type === 'average') {
        var sum = 0;
        var count = 0;
        data.each(valueDataDim, function (val, idx) {
            if (!isNaN(val)) {
                sum += val;
                count++;
            }
        }, true);
        return sum / count;
    }
    else {
        return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0];
    }
S
sushuang 已提交
190
}