Skip to content

Commit 0661c79

Browse files
committed
fix(graph): #16904 introcuded percentage string here, such as '33%'. But it was based on canvas width/height, which is not reasonable - the unit may incorrect, and it is unpredictable if the View['_rect'] is not calculated based on the current canvas rect. Therefore the percentage value is changed to based on View['_rect'].width/height since v6. Under this definition, users can use '0%' to map the top-left of View['_rect'] to the center of View['_viewRect'].
1 parent 0b9b08a commit 0661c79

File tree

8 files changed

+396
-26
lines changed

8 files changed

+396
-26
lines changed

src/action/roamHelper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function updateCenterAndZoom(
5858
point[0] -= payload.dx;
5959
point[1] -= payload.dy;
6060

61-
view.setCenter(getCenterCoord(view, point), api);
61+
view.setCenter(getCenterCoord(view, point));
6262
}
6363
if (zoom != null) {
6464
if (zoomLimit) {
@@ -81,7 +81,7 @@ export function updateCenterAndZoom(
8181

8282
view.updateTransform();
8383
// Get the new center
84-
view.setCenter(getCenterCoord(view, point), api);
84+
view.setCenter(getCenterCoord(view, point));
8585
view.setZoom(zoom * previousZoom);
8686
}
8787

src/chart/graph/createView.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,21 +79,18 @@ export default function createViewCoordSys(ecModel: GlobalModel, api: ExtensionA
7979
const bbWidth = max[0] - min[0];
8080
const bbHeight = max[1] - min[1];
8181

82-
const viewWidth = viewRect.width;
83-
const viewHeight = viewRect.height;
84-
8582
const viewCoordSys = new View();
8683
viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');
8784

8885
viewCoordSys.setBoundingRect(
8986
min[0], min[1], bbWidth, bbHeight
9087
);
9188
viewCoordSys.setViewRect(
92-
viewRect.x, viewRect.y, viewWidth, viewHeight
89+
viewRect.x, viewRect.y, viewRect.width, viewRect.height
9390
);
9491

9592
// Update roam info
96-
viewCoordSys.setCenter(seriesModel.get('center'), api);
93+
viewCoordSys.setCenter(seriesModel.get('center'), {api, ecModel});
9794
viewCoordSys.setZoom(seriesModel.get('zoom'));
9895

9996
viewList.push(viewCoordSys);

src/chart/sankey/SankeyView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ class SankeyView extends ChartView {
376376

377377
viewCoordSys.setBoundingRect(0, 0, width, height);
378378

379-
viewCoordSys.setCenter(seriesModel.get('center'), api);
379+
viewCoordSys.setCenter(seriesModel.get('center'), {api, ecModel: seriesModel.ecModel});
380380
viewCoordSys.setZoom(seriesModel.get('zoom'));
381381

382382
this._mainGroup.x = layoutInfo.x;

src/chart/tree/TreeView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ class TreeView extends ChartView {
257257

258258
viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]);
259259

260-
viewCoordSys.setCenter(seriesModel.get('center'), api);
260+
viewCoordSys.setCenter(seriesModel.get('center'), {api, ecModel: seriesModel.ecModel});
261261
viewCoordSys.setZoom(seriesModel.get('zoom'));
262262

263263
// Here we use viewCoordSys just for computing the 'position' and 'scale' of the group

src/coord/View.ts

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ import { CoordinateSystemMaster, CoordinateSystem } from './CoordinateSystem';
3030
import GlobalModel from '../model/Global';
3131
import { ParsedModelFinder, ParsedModelFinderKnown } from '../util/model';
3232
import { parsePercent } from '../util/number';
33-
import type ExtensionAPI from '../core/ExtensionAPI';
33+
import { RoamOptionMixin } from '../util/types';
34+
import { clone } from 'zrender/src/core/util';
35+
import ExtensionAPI from '../core/ExtensionAPI';
3436

3537
const v2ApplyTransform = vector.applyTransform;
3638

@@ -65,17 +67,20 @@ class View extends Transformable implements CoordinateSystemMaster, CoordinateSy
6567
/**
6668
* This is a user specified point on the source, which will be
6769
* located to the center of the `View['_viewRect']`.
68-
* The unit this the same as `View['_rect']`.
70+
* The unit and the origin of this point is the same as that of `[View['_rect']`.
6971
*/
7072
private _center: number[];
73+
private _centerOption: RoamOptionMixin['center'];
74+
7175
private _zoom: number;
7276

7377
/**
7478
* The rect of the source, where the measure is used by "data" and "center".
7579
* Has nothing to do with roam/zoom.
7680
* The unit is defined by the source. For example,
77-
* for geo source the unit is lat/lng,
78-
* for SVG source the unit is the same as the width/height defined in SVG.
81+
* - for geo source the unit is lat/lng,
82+
* - for SVG source the unit is the same as the width/height defined in SVG.
83+
* - for series.graph/series.tree/series.sankey the uiit is px.
7984
*/
8085
private _rect: BoundingRect;
8186
/**
@@ -91,6 +96,7 @@ class View extends Transformable implements CoordinateSystemMaster, CoordinateSy
9196

9297
setBoundingRect(x: number, y: number, width: number, height: number): BoundingRect {
9398
this._rect = new BoundingRect(x, y, width, height);
99+
this._updateCenterAndZoom();
94100
return this._rect;
95101
}
96102

@@ -126,16 +132,33 @@ class View extends Transformable implements CoordinateSystemMaster, CoordinateSy
126132
}
127133

128134
/**
129-
* Set center of view
135+
* [NOTICE]
136+
* The definition of this center has always been irrelevant to some other series center like
137+
* 'series-pie.center' - this center is a point on the same coord sys as `View['_rect'].x/y`,
138+
* rather than canvas viewport, and the unit is not necessarily pixel (e.g., in geo case).
139+
* @see {View['_center']} for details.
130140
*/
131-
setCenter(centerCoord: (number | string)[], api: ExtensionAPI): void {
132-
if (!centerCoord) {
133-
return;
141+
setCenter(
142+
centerCoord: RoamOptionMixin['center'],
143+
opt?: {
144+
// Only for backward compat.
145+
ecModel?: GlobalModel
146+
api?: ExtensionAPI
147+
}
148+
): void {
149+
// #16904 introcuded percentage string here, such as '33%'. But it was based on canvas
150+
// width/height, which is not reasonable - the unit may incorrect, and it is unpredictable if
151+
// the `View['_rect']` is not calculated based on the current canvas rect. Therefore the percentage
152+
// value is changed to based on `View['_rect'].width/height` since v6. Under this definition, users
153+
// can use '0%' to map the top-left of `View['_rect']` to the center of `View['_viewRect']`.
154+
if (opt && opt.api && opt.ecModel && opt.ecModel.getShallow('legacyViewCoordSysCenterBase') && centerCoord) {
155+
centerCoord = [
156+
parsePercent(centerCoord[0], opt.api.getWidth()),
157+
parsePercent(centerCoord[1], opt.api.getWidth())
158+
];
134159
}
135-
this._center = [
136-
parsePercent(centerCoord[0], api.getWidth()),
137-
parsePercent(centerCoord[1], api.getHeight())
138-
];
160+
161+
this._centerOption = clone(centerCoord);
139162
this._updateCenterAndZoom();
140163
}
141164

@@ -181,9 +204,19 @@ class View extends Transformable implements CoordinateSystemMaster, CoordinateSy
181204
}
182205

183206
/**
184-
* Remove roam
207+
* Ensure this method is idempotent, since it should be called when
208+
* every relevant prop (e.g. _centerOption/_zoom/_rect/_viewRect) changed.
185209
*/
186210
private _updateCenterAndZoom(): void {
211+
const centerOption = this._centerOption;
212+
const rect = this._rect;
213+
if (centerOption && rect) {
214+
this._center = [
215+
parsePercent(centerOption[0], rect.width, rect.x),
216+
parsePercent(centerOption[1], rect.height, rect.y)
217+
];
218+
}
219+
187220
// Must update after view transform updated
188221
const rawTransformMatrix = this._rawTransformable.getLocalTransform();
189222
const roamTransform = this._roamTransformable;

src/util/number.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export const parsePercent = parsePositionOption;
112112
* @see {parsePositionSizeOption} and also accept a string preset.
113113
* @see {PositionSizeOption}
114114
*/
115-
export function parsePositionOption(option: unknown, percentBase: number): number {
115+
export function parsePositionOption(option: unknown, percentBase: number, percentOffset?: number): number {
116116
switch (option) {
117117
case 'center':
118118
case 'middle':
@@ -127,7 +127,7 @@ export function parsePositionOption(option: unknown, percentBase: number): numbe
127127
option = '100%';
128128
break;
129129
}
130-
return parsePositionSizeOption(option, percentBase);
130+
return parsePositionSizeOption(option, percentBase, percentOffset);
131131
}
132132

133133
/**
@@ -136,10 +136,10 @@ export function parsePositionOption(option: unknown, percentBase: number): numbe
136136
* (But allow JS type coercion (`+option`) due to backward compatibility)
137137
* @see {PositionSizeOption}
138138
*/
139-
export function parsePositionSizeOption(option: unknown, percentBase: number): number {
139+
export function parsePositionSizeOption(option: unknown, percentBase: number, percentOffset?: number): number {
140140
if (zrUtil.isString(option)) {
141141
if (_trim(option).match(/%$/)) {
142-
return parseFloat(option) / 100 * percentBase;
142+
return parseFloat(option) / 100 * percentBase + (percentOffset || 0);
143143
}
144144
return parseFloat(option);
145145
}

src/util/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,8 @@ export type ECUnitOption = {
708708
useUTC?: boolean
709709
hoverLayerThreshold?: number
710710

711+
legacyViewCoordSysCenterBase?: boolean
712+
711713
[key: string]: ComponentOption | ComponentOption[] | Dictionary<unknown> | unknown
712714

713715
stateAnimation?: AnimationOption

0 commit comments

Comments
 (0)