Skip to content

Commit 2e82d33

Browse files
committed
fix regression: onZero should be backward compatibility. And clarify comments.
1 parent fbe49c8 commit 2e82d33

10 files changed

Lines changed: 82 additions & 79 deletions

File tree

src/chart/helper/axisSnippets.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ export function createBandWidthBasedAxisContainShapeHandler(axisStatKey: AxisSta
4343
// |----|----------------------|--|
4444
// minValNew minValOld maxValOld maxValNew
4545
// (Note: `|---|` above represents "pixels" rather than "data".)
46-
// Regarding single data item case:
47-
// (See test/axis-extreme2.html)
48-
// - TimeScale and OrdinalScale do not need to handle it, since they have
49-
// ensured single data item is laid out at the middle of the axis.
50-
// - IntervalScale and LogScale ...................
5146

5247
return function (axis, ecModel) {
5348
const bandWidthResult = calcBandWidth(axis, {fromStat: {key: axisStatKey}});

src/component/dataZoom/AxisProxy.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import {
3636
AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM, scaleRawExtentInfoCreate,
3737
ScaleRawExtentResultForZoom,
3838
} from '../../coord/scaleRawExtentInfo';
39-
import { discourageOnAxisZero } from '../../coord/axisHelper';
4039

4140

4241
interface MinMaxSpan {
@@ -353,8 +352,6 @@ class AxisProxy {
353352
const axis = this.getAxisModel().axis;
354353
scaleRawExtentInfoCreate(this.ecModel, axis, AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM);
355354

356-
discourageOnAxisZero(axis, {dz: true});
357-
358355
const rawExtentInfo = axis.scale.rawExtentInfo;
359356
this._extent = rawExtentInfo.makeNoZoom();
360357

src/coord/axisBand.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,17 @@ export type AxisBandWidthResult = {
4545
w2: number;
4646
};
4747

48-
/**
49-
* PENDING: Should the `bandWidth` strategy be chosen by users, or auto-determined basesd on
50-
* performance?
51-
*/
5248
type CalculateBandWidthOpt = {
5349
// Only used on non-'category' axes. Calculate `bandWidth` based on statistics.
5450
// Require `requireAxisStatistics` to be called.
5551
fromStat?: {
56-
// Either `axisStatKey` or `series` is required.
57-
// If multiple axis statistics can be queried by `series`, currently we only support to return a
58-
// maximum `bandWidth`, which is suitable for cases like "axis pointer shadow".
59-
sers?: (SeriesModel | NullUndefined)[] | NullUndefined;
52+
// Either `key` or `sers` is required.
53+
// - `key`: Calculate `bandWidth` based on a series collection defined by the `AxisStatKey`.
6054
key?: AxisStatKey;
55+
// - `sers`: Query all keys by the given series collection and union the corresponding bandWidth.
56+
// PENDING: If multiple axis statistics can be queried by `series`, currently we only support
57+
// to return a maximum `bandWidth`, which is suitable for cases like "axis pointer shadow".
58+
sers?: (SeriesModel | NullUndefined)[] | NullUndefined;
6159
};
6260
// It also act as a fallback for NaN/null/undefined result.
6361
min?: number;

src/coord/axisHelper.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,9 @@ import ComponentModel from '../model/Component';
5959

6060

6161
const axisInner = makeInner<{
62-
noOnMyZero: DiscourageOnAxisZeroCondition;
62+
noOnMyZero: boolean;
6363
}, Axis>();
6464

65-
type DiscourageOnAxisZeroCondition = {
66-
dz?: boolean;
67-
base?: boolean;
68-
};
69-
7065

7166
export function determineAxisType(
7267
model: Model<Pick<AxisBaseOption, 'type'>>
@@ -162,20 +157,15 @@ export const SCALE_VALUE_POSITION_KIND_EDGE = 2;
162157
export const SCALE_VALUE_POSITION_KIND_OUTSIDE = 3;
163158

164159

165-
export function discourageOnAxisZero(axis: Axis, reason: Partial<DiscourageOnAxisZeroCondition>): void {
166-
zrUtil.defaults(axisInner(axis).noOnMyZero || (axisInner(axis).noOnMyZero = {}), reason);
160+
export function discourageOnAxisZero(axis: Axis): void {
161+
axisInner(axis).noOnMyZero = true;
167162
}
168163

169164
/**
170165
* `true`: Prevent orthoganal axes from positioning at the zero point of this axis.
171166
*/
172167
export function isOnAxisZeroDiscouraged(axis: Axis): boolean {
173-
const noOnMyZero = axisInner(axis).noOnMyZero;
174-
// Empirically, onZero causes weird effect when dataZoom is used on an "base axis". Consider
175-
// bar series as an example. And also consider when `SCALE_EXTENT_KIND_MAPPING` is used, where
176-
// the axis line is likely to cross the series shapes unexpectedly.
177-
// Conservatively, we use "&&" rather than "||" here.
178-
return noOnMyZero && noOnMyZero.dz && noOnMyZero.base;
168+
return axisInner(axis).noOnMyZero;
179169
}
180170

181171
/**

src/coord/axisStatistics.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,12 @@ export type AxisStatKeyedClient = {
126126

127127
/**
128128
* Within each individual axis, different groups of relevant series and statistics are
129-
* designated by `AxisStatKey`. In most case `seriesType` is used as `AxisStatKey`.
129+
* designated by a `AxisStatKey`.
130+
* In most case `seriesType` is used as `AxisStatKey`.
130131
*/
131132
export type AxisStatKey = string & {_: 'AxisStatKey'}; // Nominal to avoid misusing.
132-
type ClientQueryKey = string & {_: 'ClientQueryKey'}; // Nominal to avoid misusing; internal usage.
133+
134+
type ClientLookupKey = string & {_: 'ClientLookupKey'}; // Nominal to avoid misusing; internal usage.
133135

134136
export type AxisStatMetrics = {
135137

@@ -468,7 +470,7 @@ function performStatisticsForRecord(
468470
// For performance optimization.
469471
const tmpValueBuffer = tryEnsureTypedArray(
470472
{ctor: Float64ArrayCtor},
471-
50 // arbitrary. May be expanded if needed.
473+
50 // An arbitrary initial capability.
472474
);
473475

474476
/**
@@ -525,8 +527,8 @@ export function associateSeriesWithAxis(
525527
const seriesType = seriesModel.subType;
526528
const isBaseAxis = seriesModel.getBaseAxis() === axis;
527529

528-
const client = clientsByQueryKey.get(makeClientQueryKey(seriesType, isBaseAxis, coordSysType))
529-
|| clientsByQueryKey.get(makeClientQueryKey(seriesType, isBaseAxis, null));
530+
const client = clientsForLookup.get(makeClientLookupKey(seriesType, isBaseAxis, coordSysType))
531+
|| clientsForLookup.get(makeClientLookupKey(seriesType, isBaseAxis, null));
530532
if (!client) {
531533
return;
532534
}
@@ -554,16 +556,16 @@ export function associateSeriesWithAxis(
554556
* NOTE: Currently, the scenario is simple enough to look up clients by hash map.
555557
* Otherwise, a caller-provided `filter` may be an alternative if more complex requirements arise.
556558
*/
557-
function makeClientQueryKey(
559+
function makeClientLookupKey(
558560
seriesType: ComponentSubType,
559561
isBaseAxis: boolean | NullUndefined,
560562
coordSysType: CoordinateSystem['type'] | NullUndefined
561-
): ClientQueryKey {
563+
): ClientLookupKey {
562564
return (
563565
seriesType
564566
+ AXIS_STAT_KEY_DELIMITER + retrieve2(isBaseAxis, true)
565567
+ AXIS_STAT_KEY_DELIMITER + (coordSysType || '')
566-
) as ClientQueryKey;
568+
) as ClientLookupKey;
567569
}
568570

569571
/**
@@ -575,18 +577,18 @@ export function requireAxisStatistics(
575577
registers: EChartsExtensionInstallRegisters,
576578
client: AxisStatKeyedClient
577579
): void {
578-
const queryKey = makeClientQueryKey(client.seriesType, client.baseAxis, client.coordSysType);
580+
const clientKey = makeClientLookupKey(client.seriesType, client.baseAxis, client.coordSysType);
579581

580582
if (__DEV__) {
581583
assert(client.seriesType
582584
&& client.key
583-
&& !clientsCheckStatKey.get(client.key)
584-
&& !clientsByQueryKey.get(queryKey)
585+
&& !clientsForCheckingStatKey.get(client.key)
586+
&& !clientsForLookup.get(clientKey)
585587
); // More checking is performed in `axSerPairCheck`.
586-
clientsCheckStatKey.set(client.key, 1);
588+
clientsForCheckingStatKey.set(client.key, 1);
587589
}
588590

589-
clientsByQueryKey.set(queryKey, client);
591+
clientsForLookup.set(clientKey, client);
590592

591593
callOnlyOnce(registers, function () {
592594
registers.registerProcessor(registers.PRIORITY.PROCESSOR.AXIS_STATISTICS, {
@@ -597,8 +599,8 @@ export function requireAxisStatistics(
597599
});
598600
}
599601

600-
let clientsCheckStatKey: HashMap<1, AxisStatKey>;
602+
let clientsForCheckingStatKey: HashMap<1, AxisStatKey>;
601603
if (__DEV__) {
602-
clientsCheckStatKey = createHashMap();
604+
clientsForCheckingStatKey = createHashMap();
603605
}
604-
const clientsByQueryKey: HashMap<AxisStatKeyedClient, ClientQueryKey> = createHashMap();
606+
const clientsForLookup: HashMap<AxisStatKeyedClient, ClientLookupKey> = createHashMap();

src/coord/cartesian/Grid.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
shouldAxisShow,
3333
retrieveAxisBreaksOption,
3434
determineAxisType,
35-
discourageOnAxisZero,
3635
isOnAxisZeroDiscouraged,
3736
SCALE_VALUE_POSITION_KIND_OUTSIDE,
3837
SCALE_VALUE_POSITION_KIND_EDGE,
@@ -454,8 +453,6 @@ class Grid implements CoordinateSystemMaster {
454453

455454
cartesian.addAxis(xAxis);
456455
cartesian.addAxis(yAxis);
457-
458-
discourageOnAxisZero(cartesian.getBaseAxis(), {base: true});
459456
});
460457
});
461458

@@ -699,6 +696,13 @@ function canOnZeroToAxis(
699696
&& kindEffective !== SCALE_VALUE_POSITION_KIND_OUTSIDE;
700697

701698
if (can && onZeroOption === 'auto'
699+
// Historically, "value" axis and "log" axis has been using `onZero: true` as the default.
700+
// It suitable for mathematic cases, even when dataZoom exists (e.g., `clip.html`), or cases
701+
// need to distinguish positive and negative data. However, it probably causes odd effect if
702+
// a "value axis" is laid on zero of a "base axis" in bar/candlestick, where the axis line
703+
// would likely cross shapes when `SCALE_EXTENT_KIND_MAPPING` is applied.
704+
// Therefore, we preserve backward compatibility of the default `onZero: true`, but exclude
705+
// cases that `containShape` is applied.
702706
&& (
703707
isOnAxisZeroDiscouraged(axis)
704708
|| (

src/coord/scaleRawExtentInfo.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import {
3737
unionExtentEndFromNumber,
3838
ensureExtentAscSimply,
3939
} from '../util/model';
40-
import { getDataDimensionsOnAxis, isAxisOnBand } from './axisHelper';
40+
import { discourageOnAxisZero, getDataDimensionsOnAxis, isAxisOnBand } from './axisHelper';
4141
import {
4242
getCoordForCoordSysUsageKindBox
4343
} from '../core/CoordinateSystem';
@@ -786,6 +786,8 @@ export function adoptScaleExtentKindMapping(
786786
linearSupplement = linearSupplement || [0, 0];
787787
unionExtentStartFromNumber(linearSupplement, singleLinearSupplement[0]);
788788
unionExtentEndFromNumber(linearSupplement, singleLinearSupplement[1]);
789+
790+
discourageOnAxisZero(axis);
789791
}
790792
}
791793
});

src/core/Scheduler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ interface OverallTaskContext extends TaskContext {
108108
}
109109
interface StubTaskContext extends TaskContext {
110110
model: SeriesModel;
111-
dirtyOnOverallProgress: boolean;
111+
dirtyOnOverallProgress: StageHandler['dirtyOnOverallProgress'];
112112
};
113113

114114
class Scheduler {

src/util/types.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ export interface StageHandler {
379379
*
380380
* The `overallReset` method is called iff this task is "dirty" (See `Task['dirty']`).
381381
* See EC_TASK_DIRTY for a summary of possible `dirty()` calls.
382+
*
383+
* @see dirtyOnOverallProgress If a OVERALL_STAGE_TASK need to handle series data.
382384
*/
383385
overallReset?: StageHandlerOverallReset;
384386

@@ -402,10 +404,12 @@ export interface StageHandler {
402404
/**
403405
* This is a temporary mechanism primarily for a dataZoom case in `appendData`.
404406
*
405-
* Ordinarily, `overallReset` is not called in progress in the subsequent frames,
406-
* but `dirtyOnOverallProgress: true` allows all pipelines to be blocked until
407-
* this stage, thereby no `overallReset` call being omitted.
408-
* (See PerformStageTaskOpt['block'] for its meaning.)
407+
* Ordinarily, `overallReset` is NOT called in progress in the subsequent frames, which is suitable
408+
* for most OVERALL_STAGE_TASK, where no series data related operations is performed (e.g., color
409+
* palette task).
410+
* But some certain OVERALL_STAGE_TASK need to handle series data, where `dirtyOnOverallProgress: true`
411+
* is required. It allows all pipelines to be blocked until this stage, thereby no `overallReset` call
412+
* being omitted. (See PerformStageTaskOpt['block'] for its meaning.) (e.g., dataZoom task)
409413
*
410414
* NOTE_IMPL: It will set this OVERALL_STAGE_TASK dirty when the pipeline progress.
411415
* Moreover, to avoid calling the OVERALL_STAGE_TASK each frame (too frequent),

0 commit comments

Comments
 (0)