diff --git a/src/chart/treemap/TreemapSeries.ts b/src/chart/treemap/TreemapSeries.ts index 4618ec464a..23099855d3 100644 --- a/src/chart/treemap/TreemapSeries.ts +++ b/src/chart/treemap/TreemapSeries.ts @@ -158,17 +158,14 @@ export interface TreemapSeriesOption ComponentOnCalendarOptionMixin, ComponentOnMatrixOptionMixin, BoxLayoutOptionMixin, + // NOTE: In treemap, option `"zoom"` has never been exposed. + // If users explicitly specify it in `setOption`, the behavior would be unexpected in before v6.1.0, + // and it is removed since v6.1.0. RoamOptionMixin, TreemapSeriesVisualOption { type?: 'treemap' - /** - * configuration in echarts2 - * @deprecated - */ - size?: (number | string)[] - /** * If sort in desc order. * Default to be desc. asc has strange effect diff --git a/src/chart/treemap/TreemapView.ts b/src/chart/treemap/TreemapView.ts index 36a5918cd2..b0c6226b30 100644 --- a/src/chart/treemap/TreemapView.ts +++ b/src/chart/treemap/TreemapView.ts @@ -30,7 +30,6 @@ import { import DataDiffer from '../../data/DataDiffer'; import * as helper from '../helper/treeHelper'; import Breadcrumb from './Breadcrumb'; -import type { RoamControllerHost } from '../../component/helper/roamHelper'; import RoamController, { RoamEventParams } from '../../component/helper/RoamController'; import BoundingRect, { RectLike } from 'zrender/src/core/BoundingRect'; import * as matrix from 'zrender/src/core/matrix'; @@ -43,7 +42,7 @@ import GlobalModel from '../../model/Global'; import ExtensionAPI from '../../core/ExtensionAPI'; import Model from '../../model/Model'; import { LayoutRect } from '../../util/layout'; -import { TreemapLayoutNode } from './treemapLayout'; +import { calculateCurrentZoom, treemapClampZoom, TreemapLayoutNode } from './treemapLayout'; import Element from 'zrender/src/Element'; import Displayable from 'zrender/src/graphic/Displayable'; import { makeInner, convertOptionIdName } from '../../util/model'; @@ -154,7 +153,6 @@ class TreemapView extends ChartView { private _containerGroup: graphic.Group; private _breadcrumb: Breadcrumb; private _controller: RoamController; - private _controllerHost: RoamControllerHost; private _oldTree: Tree; @@ -274,14 +272,6 @@ class TreemapView extends ChartView { this._oldTree = thisTree; this._storage = thisStorage; - if (this._controllerHost) { - const _oldRootLayout = this.seriesModel.layoutInfo; - const rootLayout = thisTree.root.getLayout(); - if (rootLayout.width === _oldRootLayout.width && rootLayout.height === _oldRootLayout.height) { - this._controllerHost.zoom = 1; - } - } - return { lastsForAnimation, willDeleteEls, @@ -479,18 +469,9 @@ class TreemapView extends ChartView { } private _resetController(api: ExtensionAPI) { - let controller = this._controller; - let controllerHost = this._controllerHost; - - if (!controllerHost) { - this._controllerHost = { - target: this.group - } as RoamControllerHost; - controllerHost = this._controllerHost; - } - const seriesModel = this.seriesModel; + let controller = this._controller; // Init controller. if (!controller) { controller = this._controller = new RoamController(api.getZr()); @@ -515,13 +496,10 @@ class TreemapView extends ChartView { }, }); - controllerHost.zoomLimit = seriesModel.get('scaleLimit'); - controllerHost.zoom = seriesModel.get('zoom'); } private _clearController() { let controller = this._controller; - this._controllerHost = null; if (controller) { controller.dispose(); controller = null; @@ -561,10 +539,11 @@ class TreemapView extends ChartView { let mouseX = e.originX; let mouseY = e.originY; const zoomDelta = e.scale; + const seriesModel = this.seriesModel; if (this._state !== 'animating') { // These param must not be cached. - const root = this.seriesModel.getData().tree.root; + const root = seriesModel.getData().tree.root; if (!root) { return; @@ -580,24 +559,12 @@ class TreemapView extends ChartView { rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height ); - // scaleLimit - let zoomLimit = null; - const _controllerHost = this._controllerHost; - zoomLimit = _controllerHost.zoomLimit; - - let newZoom = _controllerHost.zoom = _controllerHost.zoom || 1; - newZoom *= zoomDelta; - if (zoomLimit) { - const zoomMin = zoomLimit.min || 0; - const zoomMax = zoomLimit.max || Infinity; - newZoom = Math.max( - Math.min(zoomMax, newZoom), - zoomMin - ); - } - const zoomScale = newZoom / _controllerHost.zoom; - _controllerHost.zoom = newZoom; - const layoutInfo = this.seriesModel.layoutInfo; + const layoutInfo = seriesModel.layoutInfo; + const currZoom = calculateCurrentZoom(layoutInfo, rootLayout); + let newZoom = currZoom * zoomDelta; + + newZoom = treemapClampZoom(newZoom, seriesModel); + const zoomScale = newZoom / currZoom; // Transform mouse coord from global to containerGroup. mouseX -= layoutInfo.x; diff --git a/src/chart/treemap/treemapLayout.ts b/src/chart/treemap/treemapLayout.ts index 4b870b6d1c..5956a3ca75 100644 --- a/src/chart/treemap/treemapLayout.ts +++ b/src/chart/treemap/treemapLayout.ts @@ -29,7 +29,7 @@ import * as zrUtil from 'zrender/src/core/util'; import BoundingRect, { RectLike } from 'zrender/src/core/BoundingRect'; -import {parsePercent, MAX_SAFE_INTEGER} from '../../util/number'; +import {MAX_SAFE_INTEGER} from '../../util/number'; import * as layout from '../../util/layout'; import * as helper from '../helper/treeHelper'; import TreemapSeriesModel, { TreemapSeriesNodeItemOption } from './TreemapSeries'; @@ -38,10 +38,11 @@ import ExtensionAPI from '../../core/ExtensionAPI'; import { TreeNode } from '../../data/Tree'; import Model from '../../model/Model'; import { TreemapRenderPayload, TreemapMovePayload, TreemapZoomToNodePayload } from './treemapAction'; +import { RoamOptionMixin } from '../../util/types'; +import { clampByZoomLimit } from '../../component/helper/roamHelper'; const mathMax = Math.max; const mathMin = Math.min; -const retrieveValue = zrUtil.retrieve; const each = zrUtil.each; const PATH_BORDER_WIDTH = ['itemStyle', 'borderWidth'] as const; @@ -95,34 +96,35 @@ export default { const refContainer = layout.createBoxLayoutReference(seriesModel, api).refContainer; const layoutInfo = layout.getLayoutRect(seriesModel.getBoxLayoutParams(), refContainer); - const size = seriesOption.size || []; // Compatible with ec2. - const containerWidth = parsePercent( - retrieveValue(layoutInfo.width, size[0]), - refContainer.width - ); - const containerHeight = parsePercent( - retrieveValue(layoutInfo.height, size[1]), - refContainer.height - ); - // Fetch payload info. const payloadType = payload && payload.type; const types = ['treemapZoomToNode', 'treemapRootToNode']; const targetInfo = helper .retrieveTargetInfo(payload, types, seriesModel); - const rootRect = (payloadType === 'treemapRender' || payloadType === 'treemapMove') + const rootRect: RectLike = (payloadType === 'treemapRender' || payloadType === 'treemapMove') ? payload.rootRect : null; const viewRoot = seriesModel.getViewRoot(); const viewAbovePath = helper.getPathToRoot(viewRoot) as TreemapLayoutNode[]; if (payloadType !== 'treemapMove') { - const rootSize = payloadType === 'treemapZoomToNode' - ? estimateRootSize( - seriesModel, targetInfo, viewRoot, containerWidth, containerHeight + let needClampZoom = false; + const rootSize: Pick = + payloadType === 'treemapZoomToNode' ? ( + needClampZoom = true, + estimateRootSize(seriesModel, targetInfo, viewRoot, layoutInfo) ) - : rootRect - ? [rootRect.width, rootRect.height] - : [containerWidth, containerHeight]; + : rootRect ? ( + needClampZoom = true, + zrUtil.extend({}, rootRect) + ) + : zrUtil.extend({}, layoutInfo); + + if (needClampZoom) { + let zoom = calculateCurrentZoom(layoutInfo, rootSize); + zoom = treemapClampZoom(zoom, seriesModel); + rootSize.width = layoutInfo.width * zoom; + rootSize.height = layoutInfo.height * zoom; + } let sort = seriesOption.sort; if (sort && sort !== 'asc' && sort !== 'desc') { @@ -146,9 +148,9 @@ export default { let viewRootLayout = { x: 0, y: 0, - width: rootSize[0], - height: rootSize[1], - area: rootSize[0] * rootSize[1] + width: rootSize.width, + height: rootSize.height, + area: rootSize.width * rootSize.height }; viewRoot.setLayout(viewRootLayout); @@ -199,14 +201,6 @@ export default { * * with some modifications made for this program. * See the license statement at the head of this file. - * - * @protected - * @param {module:echarts/data/Tree~TreeNode} node - * @param {Object} options - * @param {string} options.sort 'asc' or 'desc' - * @param {number} options.squareRatio - * @param {boolean} hideChildren - * @param {number} depth */ function squarify( node: TreemapLayoutNode, @@ -557,18 +551,19 @@ function position( rect[wh[idx1WhenH]] -= rowOtherLength; } -// Return [containerWidth, containerHeight] as default. +// Return containerSize as default. function estimateRootSize( seriesModel: TreemapSeriesModel, targetInfo: { node: TreemapLayoutNode }, viewRoot: TreemapLayoutNode, - containerWidth: number, - containerHeight: number -) { + containerSize: Pick, +): Pick { // If targetInfo.node exists, we zoom to the node, // so estimate whole width and height by target node. let currNode = (targetInfo || {}).node; - const defaultSize = [containerWidth, containerHeight]; + const containerWidth = containerSize.width; + const containerHeight = containerSize.height; + const defaultSize = zrUtil.extend({}, containerSize); if (!currNode || currNode === viewRoot) { return defaultSize; @@ -606,7 +601,7 @@ function estimateRootSize( area < viewArea && (area = viewArea); const scale = Math.pow(area / viewArea, 0.5); - return [containerWidth * scale, containerHeight * scale]; + return {width: containerWidth * scale, height: containerHeight * scale}; } // Root position based on coord of containerGroup @@ -696,3 +691,15 @@ function prunning( function getUpperLabelHeight(model: NodeModel): number { return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0; } + +export function calculateCurrentZoom( + baseSize: Pick, + currSize: Pick +): RoamOptionMixin['zoom'] { + // width ratio and height ratio are suppposed to be the same. + return (currSize.width / baseSize.width) || (currSize.height / baseSize.height) || 1; +} + +export function treemapClampZoom(zoom: number, seriesModel: TreemapSeriesModel): number { + return clampByZoomLimit(zoom, seriesModel.get('scaleLimit', true)); +}