Parallel.js 8.5 KB
Newer Older
P
pah100 已提交
1 2 3 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
/**
 * Parallel Coordinates
 * <https://en.wikipedia.org/wiki/Parallel_coordinates>
 */
define(function(require) {

    var layout = require('../../util/layout');
    var axisHelper = require('../../coord/axisHelper');
    var zrUtil = require('zrender/core/util');
    var ParallelAxis = require('./ParallelAxis');
    var matrix = require('zrender/core/matrix');
    var vector = require('zrender/core/vector');

    var each = zrUtil.each;

    var PI = Math.PI;

    function Parallel(parallelModel, ecModel, api) {

        /**
         * key: dimension
         * @type {Object.<string, module:echarts/coord/parallel/Axis>}
         * @private
         */
        this._axesMap = {};

        /**
         * key: dimension
         * value: {position: [], rotation, }
         * @type {Object.<string, Object>}
         * @private
         */
        this._axesLayout = {};

        /**
         * Always follow axis order.
P
pah100 已提交
37
         * @type {Array.<string>}
P
pah100 已提交
38 39
         * @readOnly
         */
P
pah100 已提交
40
        this.dimensions = parallelModel.dimensions;
P
pah100 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

        /**
         * @type {module:zrender/core/BoundingRect}
         */
        this._rect;

        this._init(parallelModel, ecModel, api);
    }

    Parallel.prototype = {

        type: 'parallel',

        constructor: Parallel,

        /**
         * Initialize cartesian coordinate systems
         * @private
         */
        _init: function (parallelModel, ecModel, api) {

P
pah100 已提交
62
            var dimensions = parallelModel.dimensions;
P
pah100 已提交
63
            var parallelAxisIndex = parallelModel.parallelAxisIndex;
P
pah100 已提交
64

P
pah100 已提交
65
            each(dimensions, function (dim, idx) {
P
pah100 已提交
66

P
pah100 已提交
67 68
                var axisIndex = parallelAxisIndex[idx];
                var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
P
pah100 已提交
69

P
pah100 已提交
70 71
                var axis = this._axesMap[dim] = new ParallelAxis(
                    dim,
P
pah100 已提交
72 73
                    axisHelper.createScaleByModel(axisModel),
                    [0, 0],
P
pah100 已提交
74 75
                    axisModel.get('type'),
                    axisIndex
P
pah100 已提交
76 77 78 79 80 81 82 83 84 85 86 87
                );

                var isCategory = axis.type === 'category';
                axis.onBand = isCategory && axisModel.get('boundaryGap');
                axis.inverse = axisModel.get('inverse');

                // Inject axis into axisModel
                axisModel.axis = axis;

                // Inject axisModel into axis
                axis.model = axisModel;

P
pah100 已提交
88 89 90 91 92 93 94 95 96 97 98 99
            }, this);

            this._updateAxesFromSeries(parallelModel, ecModel);
        },

        /**
         * Update properties from series
         * @private
         */
        _updateAxesFromSeries: function (parallelModel, ecModel) {
            ecModel.eachSeries(function (seriesModel) {

P
pah100 已提交
100
                if (!parallelModel.contains(seriesModel, ecModel)) {
P
pah100 已提交
101 102 103 104 105 106
                    return;
                }

                var data = seriesModel.getData();

                each(this.dimensions, function (dim) {
P
pah100 已提交
107
                    this._axesMap[dim].scale.unionExtent(data.getDataExtent(dim));
P
pah100 已提交
108
                }, this);
P
pah100 已提交
109 110 111 112 113 114 115 116 117 118

            }, this);
        },

        /**
         * Resize the parallel coordinate system.
         * @param {module:echarts/coord/parallel/ParallelModel} parallelModel
         * @param {module:echarts/ExtensionAPI} api
         */
        resize: function (parallelModel, api) {
119
            this._rect = layout.getLayoutRect(
L
tweak  
lang 已提交
120
                parallelModel.getBoxLayoutParams(),
P
pah100 已提交
121 122 123 124 125 126 127 128 129
                {
                    width: api.getWidth(),
                    height: api.getHeight()
                }
            );

            this._layoutAxes(parallelModel);
        },

130 131 132 133 134 135 136
        /**
         * @return {module:zrender/core/BoundingRect}
         */
        getRect: function () {
            return this._rect;
        },

P
pah100 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150
        /**
         * @private
         */
        _layoutAxes: function (parallelModel) {
            var rect = this._rect;
            var layout = parallelModel.get('layout');
            var axes = this._axesMap;
            var dimensions = this.dimensions;

            var size = [rect.width, rect.height];
            var sizeIdx = layout === 'horizontal' ? 0 : 1;
            var layoutLength = size[sizeIdx];
            var axisLength = size[1 - sizeIdx];
            var axisExtent = [0, axisLength];
P
pah100 已提交
151

P
pah100 已提交
152 153 154
            each(axes, function (axis) {
                var idx = axis.inverse ? 1 : 0;
                axis.setExtent(axisExtent[idx], axisExtent[1 - idx]);
P
pah100 已提交
155
                axisHelper.niceScaleExtent(axis, axis.model);
P
pah100 已提交
156 157 158 159 160 161 162
            });

            each(dimensions, function (dim, idx) {
                var pos = layoutLength * idx / (dimensions.length - 1);

                var positionTable = {
                    horizontal: {
P
tweak  
pah100 已提交
163 164
                        x: pos,
                        y: axisLength
P
pah100 已提交
165 166
                    },
                    vertical: {
P
tweak  
pah100 已提交
167 168
                        x: 0,
                        y: pos
P
pah100 已提交
169 170 171
                    }
                };
                var rotationTable = {
P
tweak  
pah100 已提交
172 173
                    horizontal: PI / 2,
                    vertical: 0
P
pah100 已提交
174 175 176
                };

                var position = [
P
tweak  
pah100 已提交
177 178
                    positionTable[layout].x + rect.x,
                    positionTable[layout].y + rect.y
P
pah100 已提交
179 180
                ];

P
tweak  
pah100 已提交
181
                var rotation = rotationTable[layout];
P
pah100 已提交
182 183 184 185 186 187 188 189 190 191
                var transform = matrix.create();
                matrix.rotate(transform, transform, rotation);
                matrix.translate(transform, transform, position);

                // TODO
                // tick等排布信息。

                // TODO
                // 根据axis order 更新 dimensions顺序。

P
pah100 已提交
192
                this._axesLayout[dim] = {
P
pah100 已提交
193 194
                    position: position,
                    rotation: rotation,
P
pah100 已提交
195 196 197
                    transform: transform,
                    tickDirection: 1,
                    labelDirection: 1
P
pah100 已提交
198 199 200 201
                };
            }, this);
        },

P
pah100 已提交
202 203 204 205 206 207 208 209 210
        /**
         * Get axis by dim.
         * @param {string} dim
         * @return {module:echarts/coord/parallel/ParallelAxis} [description]
         */
        getAxis: function (dim) {
            return this._axesMap[dim];
        },

P
pah100 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223
        /**
         * Convert a dim value of a single item of series data to Point.
         * @param {*} value
         * @param {string} dim
         * @return {Array}
         */
        dataToPoint: function (value, dim) {
            return this.axisCoordToPoint(
                this._axesMap[dim].dataToCoord(value),
                dim
            );
        },

P
pah100 已提交
224 225 226 227 228 229 230 231 232 233 234 235
        /**
         * @param {module:echarts/data/List} data
         * @param {Functio} cb param: {string} activeState 'active' or 'inactive' or 'normal'
         *                            {number} dataIndex
         * @param {Object} context
         */
        eachActiveState: function (data, callback, context) {
            var dimensions = this.dimensions;
            var axesMap = this._axesMap;
            var hasActiveSet = false;

            for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
P
pah100 已提交
236
                if (axesMap[dimensions[j]].model.getActiveState() !== 'normal') {
P
pah100 已提交
237 238 239 240 241
                    hasActiveSet = true;
                }
            }

            for (var i = 0, len = data.count(); i < len; i++) {
P
pah100 已提交
242
                var values = data.getValues(dimensions, i);
P
pah100 已提交
243 244 245 246 247 248 249 250
                var activeState;

                if (!hasActiveSet) {
                    activeState = 'normal';
                }
                else {
                    activeState = 'active';
                    for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
P
pah100 已提交
251 252
                        var dimName = dimensions[j];
                        var state = axesMap[dimName].model.getActiveState(values[j], j);
P
pah100 已提交
253 254 255 256 257 258 259 260 261 262 263 264

                        if (state === 'inactive') {
                            activeState = 'inactive';
                            break;
                        }
                    }
                }

                callback.call(context, activeState, i);
            }
        },

P
pah100 已提交
265 266 267 268 269 270 271 272 273
        /**
         * Convert coords of each axis to Point.
         *  Return point. For example: [10, 20]
         * @param {Array.<number>} coords
         * @param {string} dim
         * @return {Array.<number>}
         */
        axisCoordToPoint: function (coord, dim) {
            var axisLayout = this._axesLayout[dim];
P
pah100 已提交
274
            var point = [coord, 0];
P
pah100 已提交
275 276 277 278 279 280 281 282
            vector.applyTransform(point, point, axisLayout.transform);
            return point;
        },

        /**
         * Get axis layout.
         */
        getAxisLayout: function (dim) {
L
lang 已提交
283
            return zrUtil.clone(this._axesLayout[dim]);
P
pah100 已提交
284 285 286 287 288 289
        }

    };

    return Parallel;
});