Skip to content

Commit fe932a2

Browse files
committed
refactor&feature:
(1) Uniform series data union logic; previous they are implemented in several inconsistent ways and error-prone. And also strict the extent calculation with uniformed utilities. (2) Refactor Scale - uniform the implementation of the numeric transformations (such as axis breaks, logarithm, ordinal related handling) with a decorator pattern and decouple them from Scale class hierarchy. This brings consistent handling for details and enables further extension. (3) Refactor Scale - decouple "axis nice" logic from Scale and make the "axis nice" and "axis align" implemented in the same code style. This removes override (hard to read and maintain), and uniforms the parameters of IntervalScale (previous its parameters can be generated by itself or outside, which is confusing), and reduce scale-type-specified handling (e.g., if (isLogScale) ...) in calculation. (4) Enable "value" axis and "log" axis to render "bar" and "pictorialBar" series without overflowing the axis. Previously only "time" axis enables that on only "bar" series. Introduce "SCALE_EXTENT_KIND_MAPPING" to cover this generalized behavior and use strict "clip" for bar series without extra margin (a previous compromise). And clarify `barGrid` code accordingly, which removes duplicated time-consuming calculation in "bandWidth" calculation. Close#19972. Close#17858. Close#12720. Close#13321. Close#20718. Close#20421. Close#20503.
1 parent 64305a4 commit fe932a2

53 files changed

Lines changed: 3987 additions & 1973 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎src/chart/bar/BarView.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ function getClipArea(coord: CoordSysOfBar, data: SeriesData) {
9696
constcoordSysClipArea=coord.getArea&&coord.getArea();
9797
if(isCoordinateSystemType<Cartesian2D>(coord,'cartesian2d')){
9898
constbaseAxis=coord.getBaseAxis();
99-
// When boundaryGap is false or using time axis. bar may exceed the grid.
99+
// When boundaryGap is false in category axis, bar may exceed the grid.
100100
// We should not clip this part.
101101
// See test/bar2.html
102-
if(baseAxis.type!=='category'||!baseAxis.onBand){
102+
if(baseAxis.type==='category'&&!baseAxis.onBand){
103103
constexpandWidth=data.getLayout('bandWidth');
104104
if(baseAxis.isHorizontal()){
105105
(coordSysClipAreaasCartesianCoordArea).x-=expandWidth;
@@ -225,6 +225,7 @@ class BarView extends ChartView {
225225
group.removeClipPath();
226226
// We don't use clipPath in normal mode because we needs a perfect animation
227227
// And don't want the label are clipped.
228+
// Instead, `Clipper` is used in normal mode.
228229

229230
constroundCap=seriesModel.get('roundCap',true);
230231

‎src/chart/bar/install.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import{EChartsExtensionInstallRegisters}from'../../extension';
2121
import*aszrUtilfrom'zrender/src/core/util';
22-
import{layout,createProgressiveLayout}from'../../layout/barGrid';
22+
import{layout,createProgressiveLayout,registerBarGridAxisContainShapeHandler}from'../../layout/barGrid';
2323
importdataSamplefrom'../../processor/dataSample';
2424

2525
importBarSeriesfrom'./BarSeries';
@@ -67,4 +67,5 @@ export function install(registers: EChartsExtensionInstallRegisters) {
6767
);
6868
});
6969

70+
registerBarGridAxisContainShapeHandler(registers);
7071
}

‎src/chart/bar/installPictorialBar.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import{EChartsExtensionInstallRegisters}from'../../extension';
2121
importPictorialBarViewfrom'./PictorialBarView';
2222
importPictorialBarSeriesModelfrom'./PictorialBarSeries';
23-
import{createProgressiveLayout,layout}from'../../layout/barGrid';
23+
import{createProgressiveLayout,layout,registerBarGridAxisContainShapeHandler}from'../../layout/barGrid';
2424
import{curry}from'zrender/src/core/util';
2525

2626
exportfunctioninstall(registers: EChartsExtensionInstallRegisters){
@@ -30,4 +30,6 @@ export function install(registers: EChartsExtensionInstallRegisters) {
3030
registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT,curry(layout,'pictorialBar'));
3131
// Do layout after other overall layout, which can prepare some information.
3232
registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT,createProgressiveLayout('pictorialBar'));
33+
34+
registerBarGridAxisContainShapeHandler(registers);
3335
}

‎src/chart/custom/CustomSeries.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import Displayable from 'zrender/src/graphic/Displayable';
2121
import{ImageProps,ImageStyleProps}from'zrender/src/graphic/Image';
2222
import{PathProps,PathStyleProps}from'zrender/src/graphic/Path';
2323
import{ZRenderType}from'zrender/src/zrender';
24-
import{BarGridLayoutOptionForCustomSeries,BarGridLayoutResult}from'../../layout/barGrid';
24+
import{
25+
BarGridLayoutOptionForCustomSeries,
26+
BarGridLayoutResultForCustomSeries
27+
}from'../../layout/barGrid';
2528
import{
2629
AnimationOption,
2730
BlurScope,
@@ -296,7 +299,7 @@ export interface CustomSeriesRenderItemAPI extends
296299
): VTextendsNonStyleVisualProps ? DefaultDataVisual[VT]
297300
: VTextendsStyleVisualProps ? PathStyleProps[typeofSTYLE_VISUAL_TYPE[VT]]
298301
: void;
299-
barLayout(opt: BarGridLayoutOptionForCustomSeries): BarGridLayoutResult;
302+
barLayout(opt: BarGridLayoutOptionForCustomSeries): BarGridLayoutResultForCustomSeries;
300303
currentSeriesIndices(): number[];
301304
font(opt: Pick<TextCommonOption,'fontStyle'|'fontWeight'|'fontSize'|'fontFamily'>): string;
302305
}

‎src/chart/custom/CustomView.ts‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import * as graphicUtil from '../../util/graphic';
2525
import{setDefaultStateProxy,toggleHoverEmphasis}from'../../util/states';
2626
import*aslabelStyleHelperfrom'../../label/labelStyle';
2727
import{getDefaultLabel}from'../helper/labelHelper';
28-
import{getLayoutOnAxis}from'../../layout/barGrid';
28+
import{
29+
BarGridLayoutOptionForCustomSeries,BarGridLayoutResultForCustomSeries,
30+
getLayoutOnAxis
31+
}from'../../layout/barGrid';
2932
importDataDifferfrom'../../data/DataDiffer';
3033
importModelfrom'../../model/Model';
3134
importChartViewfrom'../../view/Chart';
@@ -43,7 +46,7 @@ import {
4346
ECElement,
4447
DisplayStateNonNormal,
4548
OrdinalRawValue,
46-
InnerDecalObject
49+
InnerDecalObject,
4750
}from'../../util/types';
4851
importElement,{ElementTextConfig}from'zrender/src/Element';
4952
importprepareCartesian2dfrom'../../coord/cartesian/prepareCustom';
@@ -90,7 +93,8 @@ import CustomSeriesModel, {
9093
CustomPathOption,
9194
CustomRootElementOption,
9295
CustomSeriesOption,
93-
CustomCompoundPathOption
96+
CustomCompoundPathOption,
97+
CustomSeriesRenderItemCoordinateSystemAPI
9498
}from'./CustomSeries';
9599
import{PatternObject}from'zrender/src/graphic/Pattern';
96100
import{
@@ -916,8 +920,8 @@ function makeRenderItem(
916920
* @return If not support, return undefined.
917921
*/
918922
functionbarLayout(
919-
opt: Omit<Parameters<typeofgetLayoutOnAxis>[0],'axis'>
920-
): ReturnType<typeofgetLayoutOnAxis>{
923+
opt: BarGridLayoutOptionForCustomSeries
924+
): BarGridLayoutResultForCustomSeries{
921925
if(coordSys.type==='cartesian2d'){
922926
constbaseAxis=coordSys.getBaseAxis()asAxis2D;
923927
returngetLayoutOnAxis(defaults({axis: baseAxis},opt));

‎src/chart/heatmap/HeatmapView.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,10 @@ class HeatmapView extends ChartView {
241241
if(isNaN(data.get(dataDims[2],idx)asnumber)
242242
||isNaN(dataDimXasnumber)
243243
||isNaN(dataDimYasnumber)
244-
||dataDimX<xAxisExtent[0]
245-
||dataDimX>xAxisExtent[1]
246-
||dataDimY<yAxisExtent[0]
247-
||dataDimY>yAxisExtent[1]
244+
||(dataDimXasnumber)<xAxisExtent[0]
245+
||(dataDimXasnumber)>xAxisExtent[1]
246+
||(dataDimYasnumber)<yAxisExtent[0]
247+
||(dataDimYasnumber)>yAxisExtent[1]
248248
){
249249
continue;
250250
}

‎src/chart/line/LineView.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ function xyExtentFromPoints(points: ArrayLike<number>) {
9292
constx=points[i++];
9393
consty=points[i++];
9494
if(!isPointIllegal(x,y)){
95-
modelUtil.unionExtent(xExtent,x);
96-
modelUtil.unionExtent(yExtent,y);
95+
modelUtil.unionExtentFromNumber(xExtent,x);
96+
modelUtil.unionExtentFromNumber(yExtent,y);
9797
}
9898
}
9999
return[xExtent,yExtent];

‎src/component/axis/AxisBuilder.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ import ExtensionAPI from '../../core/ExtensionAPI';
6565
import{makeInner}from'../../util/model';
6666
import{getAxisBreakHelper}from'./axisBreakHelper';
6767
import{AXIS_BREAK_EXPAND_ACTION_TYPE,BaseAxisBreakPayload}from'./axisAction';
68-
import{getScaleBreakHelper}from'../../scale/break';
68+
import{getScaleBreakHelper,hasBreaks}from'../../scale/break';
6969
importBoundingRectfrom'zrender/src/core/BoundingRect';
7070
importPointfrom'zrender/src/core/Point';
7171
import{copyTransform}from'zrender/src/core/Transformable';
@@ -709,7 +709,7 @@ const builders: Record<AxisBuilderAxisPartName, AxisElementsBuilder> = {
709709
style: lineStyle,
710710
};
711711

712-
if(axisModel.get(['axisLine','breakLine'])&&axisModel.axis.scale.hasBreaks()){
712+
if(axisModel.get(['axisLine','breakLine'])&&hasBreaks(axisModel.axis.scale)){
713713
getAxisBreakHelper()!.buildAxisBreakLine(axisModel,group,transformGroup,pathBaseProp);
714714
}
715715
else{

‎src/component/axisPointer/modelHelper.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,7 @@ export function fixValue(axisModel: AxisBaseModel) {
373373
option.status=useHandle ? 'show' : 'hide';
374374
}
375375

376-
constextent=scale.getExtent().slice();
377-
extent[0]>extent[1]&&extent.reverse();
376+
constextent=scale.getExtent();
378377

379378
if(// Pick a value on axis when initializing.
380379
value==null

‎src/component/dataZoom/AxisProxy.ts‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ import { Dictionary, NullUndefined } from '../../util/types';
3030
importDataZoomModelfrom'./DataZoomModel';
3131
import{AxisBaseModel}from'../../coord/AxisBaseModel';
3232
import{getAxisMainType,isCoordSupported,DataZoomAxisDimension}from'./helper';
33-
import{initExtentForUnion,SINGLE_REFERRING}from'../../util/model';
33+
import{SINGLE_REFERRING}from'../../util/model';
3434
import{isOrdinalScale,isTimeScale}from'../../scale/helper';
35-
import{AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM,axisExtentInfoFinalBuild,ensureScaleRawExtentInfo}from'../../coord/scaleRawExtentInfo';
35+
import{
36+
AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM,scaleRawExtentInfoReallyCreate,
37+
}from'../../coord/scaleRawExtentInfo';
3638

3739

3840
interfaceMinMaxSpan{
@@ -69,7 +71,7 @@ class AxisProxy {
6971

7072
private_window: AxisProxyWindow;
7173

72-
private_dataExtent: [number,number];
74+
private_dataExtent: number[];
7375

7476
private_minMaxSpan: MinMaxSpan;
7577

@@ -260,7 +262,7 @@ class AxisProxy {
260262
constpxSpan=mathAbs(pxExtent[1]-pxExtent[0]);
261263
constprecision=isScaleOrdinalOrTime
262264
? 0
263-
: getAcceptableTickPrecision(valueWindow[1]-valueWindow[0],pxSpan,0.5);
265+
: getAcceptableTickPrecision(valueWindow,pxSpan,0.5);
264266
each([[0,mathCeil],[1,mathFloor]]asconst,function([idx,ceilOrFloor]){
265267
if(!needRound[idx]||!isFinite(precision)){
266268
return;
@@ -320,10 +322,10 @@ class AxisProxy {
320322
// Nevertheless, user can set min/max/scale on axes to make extent of axes
321323
// consistent.
322324
constaxis=this.getAxisModel().axis;
323-
axisExtentInfoFinalBuild(this.ecModel,axis,AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM);
324-
constrawExtentInfo=ensureScaleRawExtentInfo(axis)
325-
constrawExtentResult=rawExtentInfo.calculate();
326-
this._dataExtent=[rawExtentResult.min,rawExtentResult.max];
325+
scaleRawExtentInfoReallyCreate(this.ecModel,axis,AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM);
326+
327+
constrawExtentInfo=axis.scale.rawExtentInfo;
328+
this._dataExtent=rawExtentInfo.makeForZoom();
327329

328330
// `calculateDataWindow` uses min/maxSpan.
329331
this._updateMinMaxSpan();
@@ -342,10 +344,10 @@ class AxisProxy {
342344
// `axisHelper.getScaleExtent`. But the different just affects the experience a
343345
// little when zooming. So it will not be fixed until some users require it strongly.
344346
if(percent[0]!==0){
345-
rawExtentInfo.setDeterminedMinMax('min',value[0]);
347+
rawExtentInfo.setZoomMinMax(0,value[0]);
346348
}
347349
if(percent[1]!==100){
348-
rawExtentInfo.setDeterminedMinMax('max',value[1]);
350+
rawExtentInfo.setZoomMinMax(1,value[1]);
349351
}
350352
}
351353

0 commit comments

Comments
 (0)