markerHelper.js 6.3 KB
Newer Older
S
sushuang 已提交
1
import * as zrUtil from 'zrender/src/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
            // 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]]) {
124
                    coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]);
S
sushuang 已提交
125 126 127
                }
            }
            item.coord = coord;
128
        }
S
sushuang 已提交
129 130
    }
    return item;
S
sushuang 已提交
131
}
S
sushuang 已提交
132

S
sushuang 已提交
133
export function getAxisInfo(item, data, coordSys, seriesModel) {
S
sushuang 已提交
134 135 136 137 138
    var ret = {};

    if (item.valueIndex != null || item.valueDim != null) {
        ret.valueDataDim = item.valueIndex != null
            ? data.getDimension(item.valueIndex) : item.valueDim;
139
        ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim));
S
sushuang 已提交
140
        ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
141
        ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
S
sushuang 已提交
142 143 144 145
    }
    else {
        ret.baseAxis = seriesModel.getBaseAxis();
        ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
146 147
        ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
        ret.valueDataDim = data.mapDimension(ret.valueAxis.dim);
S
sushuang 已提交
148 149 150
    }

    return ret;
S
sushuang 已提交
151
}
S
sushuang 已提交
152

153 154 155 156 157 158 159 160 161 162 163 164
function dataDimToCoordDim(seriesModel, dataDim) {
    var data = seriesModel.getData();
    var dimensions = data.dimensions;
    dataDim = data.getDimension(dataDim);
    for (var i = 0; i < dimensions.length; i++) {
        var dimItem = data.getDimensionInfo(dimensions[i]);
        if (dimItem.name === dataDim) {
            return dimItem.coordDim;
        }
    }
}

S
sushuang 已提交
165 166 167 168 169 170 171
/**
 * Filter data which is out of coordinateSystem range
 * [dataFilter description]
 * @param  {module:echarts/coord/*} [coordSys]
 * @param  {Object} item
 * @return {boolean}
 */
S
sushuang 已提交
172
export function dataFilter(coordSys, item) {
S
sushuang 已提交
173 174 175
    // Alwalys return true if there is no coordSys
    return (coordSys && coordSys.containData && item.coord && !hasXOrY(item))
        ? coordSys.containData(item.coord) : true;
S
sushuang 已提交
176
}
S
sushuang 已提交
177

S
sushuang 已提交
178
export function dimValueGetter(item, dimName, dataIndex, dimIndex) {
S
sushuang 已提交
179 180 181 182 183
    // x, y, radius, angle
    if (dimIndex < 2) {
        return item.coord && item.coord[dimIndex];
    }
    return item.value;
S
sushuang 已提交
184
}
S
sushuang 已提交
185

S
sushuang 已提交
186
export function numCalculate(data, valueDataDim, type) {
S
sushuang 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200
    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 已提交
201
}