TreemapSeries.js 12.6 KB
Newer Older
P
pah100 已提交
1 2 3 4 5
define(function(require) {

    var SeriesModel = require('../../model/Series');
    var Tree = require('../../data/Tree');
    var zrUtil = require('zrender/core/util');
P
pah100 已提交
6
    var Model = require('../../model/Model');
P
pah100 已提交
7
    var formatUtil = require('../../util/format');
P
pah100 已提交
8
    var helper = require('./helper');
P
pah100 已提交
9 10 11
    var encodeHTML = formatUtil.encodeHTML;
    var addCommas = formatUtil.addCommas;

P
pah100 已提交
12 13 14 15 16 17 18

    return SeriesModel.extend({

        type: 'series.treemap',

        dependencies: ['grid', 'polar'],

P
pah100 已提交
19 20 21 22 23
        /**
         * @type {module:echarts/data/Tree~Node}
         */
        _viewRoot: null,

P
pah100 已提交
24
        defaultOption: {
P
pah100 已提交
25 26
            // center: ['50%', '50%'],          // not supported in ec3.
            // size: ['80%', '80%'],            // deprecated, compatible with ec2.
27 28 29 30
            left: 'center',
            top: 'middle',
            right: null,
            bottom: null,
P
pah100 已提交
31 32
            width: '80%',
            height: '80%',
P
tweak  
pah100 已提交
33 34
            sort: true,                         // Can be null or false or true
                                                // (order by desc default, asc not supported yet (strange effect))
P
pah100 已提交
35
            clipWindow: 'origin',               // Size of clipped window when zooming. 'origin' or 'fullscreen'
P
pah100 已提交
36
            squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio
P
pah100 已提交
37 38
            leafDepth: null,                    // Nodes on depth from root are regarded as leaves.
                                                // Count from zero (zero represents only view root).
P
tweak  
pah100 已提交
39
            visualDimension: 0,                 // Can be 0, 1, 2, 3.
P
pah100 已提交
40 41 42 43 44 45 46
            zoomToNodeRatio: 0.32 * 0.32,       // Be effective when using zoomToNode. Specify the proportion of the
                                                // target node area in the view area.
            roam: true,                         // true, false, 'scale' or 'zoom', 'move'.
            nodeClick: 'zoomToNode',            // Leaf node click behaviour: 'zoomToNode', 'link', false.
                                                // If leafDepth is set and clicking a node which has children but
                                                // be on left depth, the behaviour would be changing root. Otherwise
                                                // use behavious defined above.
47
            animation: true,
P
pah100 已提交
48
            animationDurationUpdate: 900,
L
Tweak  
lang 已提交
49
            animationEasing: 'quinticInOut',
P
pah100 已提交
50 51
            breadcrumb: {
                show: true,
P
pah100 已提交
52
                height: 22,
L
tweak  
lang 已提交
53 54 55 56
                left: 'center',
                top: 'bottom',
                // right
                // bottom
P
pah100 已提交
57
                emptyItemWidth: 25,             // Width of empty node.
P
pah100 已提交
58 59
                itemStyle: {
                    normal: {
P
pah100 已提交
60 61 62 63 64 65 66 67
                        color: 'rgba(0,0,0,0.7)', //'#5793f3',
                        borderColor: 'rgba(255,255,255,0.7)',
                        borderWidth: 1,
                        shadowColor: 'rgba(150,150,150,1)',
                        shadowBlur: 3,
                        shadowOffsetX: 0,
                        shadowOffsetY: 0,
                        textStyle: {
L
tweak  
lang 已提交
68
                            color: '#fff'
P
pah100 已提交
69
                        }
P
pah100 已提交
70 71 72 73 74 75 76 77
                    },
                    emphasis: {
                        textStyle: {}
                    }
                }
            },
            label: {
                normal: {
78
                    show: true,
P
pah100 已提交
79
                    position: ['50%', '50%'], // Can be 5, '5%' or position stirng like 'insideTopLeft', ...
P
pah100 已提交
80
                    textStyle: {
P
pah100 已提交
81
                        align: 'center',
P
pah100 已提交
82
                        baseline: 'middle',
P
pah100 已提交
83
                        color: '#fff',
P
tweak  
pah100 已提交
84
                        ellipsis: true
P
pah100 已提交
85 86 87 88 89
                    }
                }
            },
            itemStyle: {
                normal: {
P
pah100 已提交
90 91 92
                    color: null,            // Can be 'none' if not necessary.
                    colorAlpha: null,       // Can be 'none' if not necessary.
                    colorSaturation: null,  // Can be 'none' if not necessary.
P
pah100 已提交
93 94
                    borderWidth: 0,
                    gapWidth: 0,
P
pah100 已提交
95
                    borderColor: '#fff',
P
pah100 已提交
96 97 98
                    borderColorSaturation: null // If specified, borderColor will be ineffective, and the
                                                // border color is evaluated by color of current node and
                                                // borderColorSaturation.
P
pah100 已提交
99
                },
P
pah100 已提交
100 101 102
                emphasis: {

                }
P
pah100 已提交
103
            },
P
pah100 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
            color: 'none',              // Array. Specify color list of each level.
                                        // level[0].color would be global color list.
            colorAlpha: null,           // Array. Specify color alpha range of each level, like [0.2, 0.8]
            colorSaturation: null,      // Array. Specify color saturation of each level, like [0.2, 0.5]
            colorMappingBy: 'index',    // 'value' or 'index' or 'id'.
            visibleMin: 10,             // If area less than this threshold (unit: pixel^2), node will not
                                        // be rendered. Only works when sort is 'asc' or 'desc'.
            childrenVisibleMin: null,   // If area of a node less than this threshold (unit: pixel^2),
                                        // grandchildren will not show.
                                        // Why grandchildren? If not grandchildren but children,
                                        // some siblings show children and some not,
                                        // the appearance may be mess and not consistent,
            levels: []                  // Each item: {
                                        //     visibleMin, itemStyle, visualDimension, label
                                        // }
119 120 121 122 123 124
            // data: {
            //      value: [],
            //      children: [],
            //      link: 'http://xxx.xxx.xxx',
            //      target: 'blank' or 'self'
            // }
P
pah100 已提交
125 126 127 128 129 130
        },

        /**
         * @override
         */
        getInitialData: function (option, ecModel) {
P
treemap  
pah100 已提交
131
            var data = option.data || [];
P
pah100 已提交
132
            var rootName = option.name;
133
            rootName == null && (rootName = option.name);
P
pah100 已提交
134

P
pah100 已提交
135
            // Create a virtual root.
P
pah100 已提交
136
            var root = {name: rootName, children: option.data};
137
            var value0 = (data[0] || {}).value;
P
pah100 已提交
138

139
            completeTreeValue(root, zrUtil.isArray(value0) ? value0.length : -1);
P
pah100 已提交
140

P
treemap  
pah100 已提交
141 142
            // FIXME
            // sereis.mergeOption 的 getInitData是否放在merge后,从而能直接获取merege后的结果而非手动判断。
143
            var levels = option.levels || [];
P
treemap  
pah100 已提交
144

P
pah100 已提交
145 146
            levels = option.levels = setDefault(levels, ecModel);

P
pah100 已提交
147 148 149
            // Make sure always a new tree is created when setOption,
            // in TreemapView, we check whether oldTree === newTree
            // to choose mappings approach among old shapes and new shapes.
L
lang 已提交
150
            return Tree.createTree(root, this, levels).data;
P
pah100 已提交
151 152
        },

P
pah100 已提交
153 154
        optionUpdated: function () {
            this.resetViewRoot();
P
pah100 已提交
155 156
        },

P
pah100 已提交
157 158 159 160 161 162 163
        /**
         * @override
         * @param {number} dataIndex
         * @param {boolean} [mutipleSeries=false]
         */
        formatTooltip: function (dataIndex) {
            var data = this.getData();
L
lang 已提交
164
            var value = this.getRawValue(dataIndex);
P
pah100 已提交
165 166
            var formattedValue = zrUtil.isArray(value)
                ? addCommas(value[0]) : addCommas(value);
L
lang 已提交
167
            var name = data.getName(dataIndex);
P
pah100 已提交
168 169 170 171 172 173 174 175 176 177 178

            return encodeHTML(name) + ': ' + formattedValue;
        },

        /**
         * Add tree path to tooltip param
         *
         * @override
         * @param {number} dataIndex
         * @return {Object}
         */
179 180
        getDataParams: function (dataIndex) {
            var params = SeriesModel.prototype.getDataParams.apply(this, arguments);
P
pah100 已提交
181 182 183 184 185 186 187 188 189 190

            var data = this.getData();
            var node = data.tree.getNodeByDataIndex(dataIndex);
            var treePathInfo = params.treePathInfo = [];

            while (node) {
                var nodeDataIndex = node.dataIndex;
                treePathInfo.push({
                    name: node.name,
                    dataIndex: nodeDataIndex,
L
lang 已提交
191
                    value: this.getRawValue(nodeDataIndex)
P
pah100 已提交
192 193 194 195 196 197 198 199 200
                });
                node = node.parentNode;
            }

            treePathInfo.reverse();

            return params;
        },

P
pah100 已提交
201 202
        /**
         * @public
203 204 205 206 207 208
         * @param {Object} layoutInfo {
         *                                x: containerGroup x
         *                                y: containerGroup y
         *                                width: containerGroup width
         *                                height: containerGroup height
         *                            }
P
pah100 已提交
209
         */
210
        setLayoutInfo: function (layoutInfo) {
P
pah100 已提交
211 212
            /**
             * @readOnly
213
             * @type {Object}
P
pah100 已提交
214
             */
215 216
            this.layoutInfo = this.layoutInfo || {};
            zrUtil.extend(this.layoutInfo, layoutInfo);
P
pah100 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
        },

        /**
         * @param  {string} id
         * @return {number} index
         */
        mapIdToIndex: function (id) {
            // A feature is implemented:
            // index is monotone increasing with the sequence of
            // input id at the first time.
            // This feature can make sure that each data item and its
            // mapped color have the same index between data list and
            // color list at the beginning, which is useful for user
            // to adjust data-color mapping.

            /**
             * @private
             * @type {Object}
             */
            var idIndexMap = this._idIndexMap;

            if (!idIndexMap) {
                idIndexMap = this._idIndexMap = {};
                /**
                 * @private
                 * @type {number}
                 */
                this._idIndexMapCount = 0;
            }

            var index = idIndexMap[id];
            if (index == null) {
                idIndexMap[id] = index = this._idIndexMapCount++;
            }

            return index;
P
pah100 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        },

        getViewRoot: function () {
            return this._viewRoot;
        },

        /**
         * @param {module:echarts/data/Tree~Node} [viewRoot]
         * @return {string} direction 'drilldown' or 'rollup'
         */
        resetViewRoot: function (viewRoot) {
            viewRoot
                ? (this._viewRoot = viewRoot)
                : (viewRoot = this._viewRoot);

            var root = this.getData().tree.root;

            if (!viewRoot
                || (viewRoot !== root && !root.contains(viewRoot))
            ) {
                this._viewRoot = root;
            }
P
pah100 已提交
275 276 277 278
        }
    });

    /**
P
pah100 已提交
279
     * @param {Object} dataNode
P
pah100 已提交
280
     */
281
    function completeTreeValue(dataNode, arrValueLength) {
P
pah100 已提交
282 283 284 285 286
        // Postorder travel tree.
        // If value of none-leaf node is not set,
        // calculate it by suming up the value of all children.
        var sum = 0;

P
pah100 已提交
287
        zrUtil.each(dataNode.children, function (child) {
P
pah100 已提交
288

289
            completeTreeValue(child, arrValueLength);
P
pah100 已提交
290

P
pah100 已提交
291 292
            var childValue = child.value;
            zrUtil.isArray(childValue) && (childValue = childValue[0]);
P
treemap  
pah100 已提交
293

P
pah100 已提交
294
            sum += childValue;
P
pah100 已提交
295 296
        });

P
pah100 已提交
297 298
        var thisValue = dataNode.value;

299
        if (arrValueLength >= 0) {
P
pah100 已提交
300
            if (!zrUtil.isArray(thisValue)) {
301
                dataNode.value = new Array(arrValueLength);
P
pah100 已提交
302 303 304 305 306 307 308 309 310 311 312 313 314 315
            }
            else {
                thisValue = thisValue[0];
            }
        }

        if (thisValue == null || isNaN(thisValue)) {
            thisValue = sum;
        }
        // Value should not less than 0.
        if (thisValue < 0) {
            thisValue = 0;
        }

316
        arrValueLength >= 0
P
pah100 已提交
317 318
            ? (dataNode.value[0] = thisValue)
            : (dataNode.value = thisValue);
P
pah100 已提交
319 320
    }

P
pah100 已提交
321 322 323 324 325 326 327 328 329 330 331 332 333 334
    /**
     * set default to level configuration
     */
    function setDefault(levels, ecModel) {
        var globalColorList = ecModel.get('color');

        if (!globalColorList) {
            return;
        }

        levels = levels || [];
        var hasColorDefine;
        zrUtil.each(levels, function (levelDefine) {
            var model = new Model(levelDefine);
335
            var modelColor = model.get('color');
P
pah100 已提交
336
            if (model.get('itemStyle.normal.color')
337
                || (modelColor && modelColor !== 'none')
P
pah100 已提交
338 339 340 341 342 343 344
            ) {
                hasColorDefine = true;
            }
        });

        if (!hasColorDefine) {
            var level0 = levels[0] || (levels[0] = {});
345
            level0.color = globalColorList.slice();
P
pah100 已提交
346 347 348 349 350
        }

        return levels;
    }

P
pah100 已提交
351
});