Parallel.js 7.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 37 38 39 40 41 42 43 44 45 46 47 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
/**
 * 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.
         * @type {Array.<number>}
         * @readOnly
         */
        this.dimensions = parallelModel.get('dimensions');

        /**
         * @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) {

            var dimensions = parallelModel.get('dimensions');
            var axisIndices = parallelModel.get('parallelAxisIndex');

            each(axisIndices, function (axisIndex, idx) {

                var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
                var parallelIndex = axisModel.get('parallelIndex');

                if (ecModel.getComponent('parallel', parallelIndex) !== parallelModel) {
                    // FIXME
                    // api.log('Axis should not be shared among coordinate systems!');
                    return;
                }

                var dim = dimensions[idx];

P
pah100 已提交
78 79
                var axis = this._axesMap[dim.name] = new ParallelAxis(
                    dim.name,
P
pah100 已提交
80 81
                    axisHelper.createScaleByModel(axisModel),
                    [0, 0],
P
pah100 已提交
82
                    dim.axisType // FIXME 检查和 axisModel.get('type') 的不一样
P
pah100 已提交
83 84 85 86 87 88 89 90 91 92 93 94
                );

                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 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
            }, this);

            this._updateAxesFromSeries(parallelModel, ecModel);
        },

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

                if (!parallelModel.containsSeries(seriesModel, ecModel)) {
                    return;
                }

                var data = seriesModel.getData();

                each(this.dimensions, function (dim) {
                    this._axesMap[dim.name].scale.unionExtent(data.getDataExtent(dim.name));
                }, this);
P
pah100 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

            }, this);
        },

        /**
         * Resize the parallel coordinate system.
         * @param {module:echarts/coord/parallel/ParallelModel} parallelModel
         * @param {module:echarts/ExtensionAPI} api
         */
        resize: function (parallelModel, api) {
            this._rect = layout.parsePositionInfo(
                {
                    x: parallelModel.get('x'),
                    y: parallelModel.get('y'),
                    x2: parallelModel.get('x2'),
                    y2: parallelModel.get('y2'),
                    width: parallelModel.get('width'),
                    height: parallelModel.get('height')
                },
                {
                    width: api.getWidth(),
                    height: api.getHeight()
                }
            );

            this._layoutAxes(parallelModel);
        },

        /**
         * @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 已提交
158

P
pah100 已提交
159 160 161
            each(axes, function (axis) {
                var idx = axis.inverse ? 1 : 0;
                axis.setExtent(axisExtent[idx], axisExtent[1 - idx]);
P
pah100 已提交
162
                axisHelper.niceScaleExtent(axis, axis.model);
P
pah100 已提交
163 164 165
            });

            each(dimensions, function (dim, idx) {
P
pah100 已提交
166
                var axis = axes[dim.name];
P
pah100 已提交
167 168 169 170 171
                var pos = layoutLength * idx / (dimensions.length - 1);
                var inverse = axis.inverse ? 'inverse' : 'forward';

                var positionTable = {
                    horizontal: {
P
pah100 已提交
172 173
                        x: {forward: pos, inverse: pos},
                        y: {forward: axisLength, inverse: 0}
P
pah100 已提交
174 175
                    },
                    vertical: {
P
pah100 已提交
176 177
                        x: {forward: 0, inverse: axisLength},
                        y: {forward: pos, inverse: pos}
P
pah100 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
                    }
                };
                var rotationTable = {
                    horizontal: {forward: PI / 2, inverse: PI * 1.5},
                    vertical: {forward: 0, inverse: PI}
                };

                var position = [
                    positionTable[layout]['x'][inverse] + rect.x,
                    positionTable[layout]['y'][inverse] + rect.y
                ];

                var rotation = rotationTable[layout][inverse];
                var transform = matrix.create();
                matrix.rotate(transform, transform, rotation);
                matrix.translate(transform, transform, position);

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

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

P
pah100 已提交
201
                this._axesLayout[dim.name] = {
P
pah100 已提交
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
                    position: position,
                    rotation: rotation,
                    transform: transform
                };
            }, this);
        },

        /**
         * 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
            );
        },

        /**
         * 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 已提交
231
            var point = [coord, 0];
P
pah100 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
            vector.applyTransform(point, point, axisLayout.transform);
            return point;
        },

        /**
         * Get axis layout.
         */
        getAxisLayout: function (dim) {
            return zrUtil.clone(this._axesLayout[dim], true);
        }

    };

    return Parallel;
});