/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var zrUtil = require("zrender/lib/core/util"); var SeriesModel = require("../../model/Series"); var Tree = require("../../data/Tree"); var Model = require("../../model/Model"); var _format = require("../../util/format"); var encodeHTML = _format.encodeHTML; var addCommas = _format.addCommas; var _treeHelper = require("../helper/treeHelper"); var wrapTreePathInfo = _treeHelper.wrapTreePathInfo; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var _default = SeriesModel.extend({ type: 'series.treemap', layoutMode: 'box', dependencies: ['grid', 'polar'], /** * @type {module:echarts/data/Tree~Node} */ _viewRoot: null, defaultOption: { // Disable progressive rendering progressive: 0, hoverLayerThreshold: Infinity, // center: ['50%', '50%'], // not supported in ec3. // size: ['80%', '80%'], // deprecated, compatible with ec2. left: 'center', top: 'middle', right: null, bottom: null, width: '80%', height: '80%', sort: true, // Can be null or false or true // (order by desc default, asc not supported yet (strange effect)) clipWindow: 'origin', // Size of clipped window when zooming. 'origin' or 'fullscreen' squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio leafDepth: null, // Nodes on depth from root are regarded as leaves. // Count from zero (zero represents only view root). drillDownIcon: '▶', // Use html character temporarily because it is complicated // to align specialized icon. ▷▶❒❐▼✚ 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. animation: true, animationDurationUpdate: 900, animationEasing: 'quinticInOut', breadcrumb: { show: true, height: 22, left: 'center', top: 'bottom', // right // bottom emptyItemWidth: 25, // Width of empty node. itemStyle: { 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: { color: '#fff' } }, emphasis: { textStyle: {} } }, label: { show: true, // Do not use textDistance, for ellipsis rect just the same as treemap node rect. distance: 0, padding: 5, position: 'inside', // Can be [5, '5%'] or position stirng like 'insideTopLeft', ... // formatter: null, color: '#fff', ellipsis: true // align // verticalAlign }, upperLabel: { // Label when node is parent. show: false, position: [0, '50%'], height: 20, // formatter: null, color: '#fff', ellipsis: true, // align: null, verticalAlign: 'middle' }, itemStyle: { color: null, // Can be 'none' if not necessary. colorAlpha: null, // Can be 'none' if not necessary. colorSaturation: null, // Can be 'none' if not necessary. borderWidth: 0, gapWidth: 0, borderColor: '#fff', borderColorSaturation: null // If specified, borderColor will be ineffective, and the // border color is evaluated by color of current node and // borderColorSaturation. }, emphasis: { upperLabel: { show: true, position: [0, '50%'], color: '#fff', ellipsis: true, verticalAlign: 'middle' } }, visualDimension: 0, // Can be 0, 1, 2, 3. visualMin: null, visualMax: null, color: [], // + treemapSeries.color should not be modified. Please only modified // level[n].color (if necessary). // + Specify color list of each level. level[0].color would be global // color list if not specified. (see method `setDefault`). // + But set as a empty array to forbid fetch color from global palette // when using nodeModel.get('color'), otherwise nodes on deep level // will always has color palette set and are not able to inherit color // from parent node. // + TreemapSeries.color can not be set as 'none', otherwise effect // legend color fetching (see seriesColor.js). 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 // } // data: { // value: [], // children: [], // link: 'http://xxx.xxx.xxx', // target: 'blank' or 'self' // } }, /** * @override */ getInitialData: function (option, ecModel) { // Create a virtual root. var root = { name: option.name, children: option.data }; completeTreeValue(root); var levels = option.levels || []; levels = option.levels = setDefault(levels, ecModel); var treeOption = {}; treeOption.levels = levels; // 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. return Tree.createTree(root, this, treeOption).data; }, optionUpdated: function () { this.resetViewRoot(); }, /** * @override * @param {number} dataIndex * @param {boolean} [mutipleSeries=false] */ formatTooltip: function (dataIndex) { var data = this.getData(); var value = this.getRawValue(dataIndex); var formattedValue = zrUtil.isArray(value) ? addCommas(value[0]) : addCommas(value); var name = data.getName(dataIndex); return encodeHTML(name + ': ' + formattedValue); }, /** * Add tree path to tooltip param * * @override * @param {number} dataIndex * @return {Object} */ getDataParams: function (dataIndex) { var params = SeriesModel.prototype.getDataParams.apply(this, arguments); var node = this.getData().tree.getNodeByDataIndex(dataIndex); params.treePathInfo = wrapTreePathInfo(node, this); return params; }, /** * @public * @param {Object} layoutInfo { * x: containerGroup x * y: containerGroup y * width: containerGroup width * height: containerGroup height * } */ setLayoutInfo: function (layoutInfo) { /** * @readOnly * @type {Object} */ this.layoutInfo = this.layoutInfo || {}; zrUtil.extend(this.layoutInfo, layoutInfo); }, /** * @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 = zrUtil.createHashMap(); /** * @private * @type {number} */ this._idIndexMapCount = 0; } var index = idIndexMap.get(id); if (index == null) { idIndexMap.set(id, index = this._idIndexMapCount++); } return index; }, getViewRoot: function () { return this._viewRoot; }, /** * @param {module:echarts/data/Tree~Node} [viewRoot] */ resetViewRoot: function (viewRoot) { viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot; var root = this.getRawData().tree.root; if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) { this._viewRoot = root; } } }); /** * @param {Object} dataNode */ function completeTreeValue(dataNode) { // 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; zrUtil.each(dataNode.children, function (child) { completeTreeValue(child); var childValue = child.value; zrUtil.isArray(childValue) && (childValue = childValue[0]); sum += childValue; }); var thisValue = dataNode.value; if (zrUtil.isArray(thisValue)) { thisValue = thisValue[0]; } if (thisValue == null || isNaN(thisValue)) { thisValue = sum; } // Value should not less than 0. if (thisValue < 0) { thisValue = 0; } zrUtil.isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue; } /** * 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); var modelColor = model.get('color'); if (model.get('itemStyle.color') || modelColor && modelColor !== 'none') { hasColorDefine = true; } }); if (!hasColorDefine) { var level0 = levels[0] || (levels[0] = {}); level0.color = globalColorList.slice(); } return levels; } module.exports = _default;