Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/component/tooltip/TooltipView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import { normalizeTooltipFormatResult } from '../../model/mixin/dataFormat';
import { createTooltipMarkup, buildTooltipMarkup, TooltipMarkupStyleCreator } from './tooltipMarkup';
import { findEventDispatcher } from '../../util/event';
import { clear, createOrUpdate } from '../../util/throttle';
import { isTimeScale } from '../../scale/helper';

const proxyRect = new Rect({
shape: { x: -1, y: -1, width: 2, height: 2 }
Expand Down Expand Up @@ -132,6 +133,7 @@ type TooltipCallbackDataParams = CallbackDataParams & {
// TODO: TYPE Value type
axisValue?: string | number
axisValueLabel?: string
axisTimeZone?: string
marker?: TooltipMarker
};

Expand Down Expand Up @@ -568,6 +570,9 @@ class TooltipView extends ComponentView {
axisItem.seriesDataIndices,
axisItem.valueLabelOpt
);
const axisTimeZone = isTimeScale(axis.scale)
? axis.scale.getTimeZone()
: ecModel.getTimeZone();
const axisSectionMarkup = createTooltipMarkup('section', {
header: axisValueLabel,
noHeader: !trim(axisValueLabel),
Expand All @@ -593,6 +598,7 @@ class TooltipView extends ComponentView {
axisModel.axis, { value: axisValueParsed }
);
cbParams.axisValueLabel = axisValueLabel;
cbParams.axisTimeZone = axisTimeZone;
// Pre-create marker style for makers. Users can assemble richText
// text in `formatter` callback and use those markers style.
cbParams.marker = markupStyleCreator.makeTooltipMarker(
Expand Down Expand Up @@ -627,7 +633,7 @@ class TooltipView extends ComponentView {
const orderMode = singleTooltipModel.get('order');

const builtMarkupText = buildTooltipMarkup(
articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'),
articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.getTimeZone(),
singleTooltipModel.get('textStyle')
);
builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText);
Expand Down Expand Up @@ -711,7 +717,7 @@ class TooltipView extends ComponentView {
markupStyleCreator,
renderMode,
orderMode,
ecModel.get('useUTC'),
ecModel.getTimeZone(),
tooltipModel.get('textStyle')
)
: seriesTooltipResult.text;
Expand Down Expand Up @@ -846,12 +852,15 @@ class TooltipView extends ComponentView {

if (formatter) {
if (isString(formatter)) {
const useUTC = tooltipModel.ecModel.get('useUTC');
const params0 = isArray(params) ? params[0] : params;
const isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0;
html = formatter;
if (isTimeAxis) {
html = timeFormat(params0.axisValue, html, useUTC);
html = timeFormat(
params0.axisValue,
html,
params0.axisTimeZone || tooltipModel.ecModel.getTimeZone()
);
}
html = formatTpl(html, params, true);
}
Expand Down
22 changes: 20 additions & 2 deletions src/component/tooltip/seriesFormatTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
} from './tooltipMarkup';
import { retrieveRawValue } from '../../data/helper/dataProvider';
import { isNameSpecified } from '../../util/model';
import { isTimeScale } from '../../scale/helper';


export function defaultSeriesFormatTooltip(opt: {
Expand All @@ -51,12 +52,14 @@ export function defaultSeriesFormatTooltip(opt: {
// Complicated rule for pretty tooltip.
let inlineValue;
let inlineValueType: DimensionType | DimensionType[];
let inlineTimeZone: string | string[];
let subBlocks: TooltipMarkupBlockFragment[];
let sortParam: unknown;
if (tooltipDimLen > 1 || (isValueArr && !tooltipDimLen)) {
const formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor);
inlineValue = formatArrResult.inlineValues;
inlineValueType = formatArrResult.inlineValueTypes;
inlineTimeZone = formatArrResult.inlineTimeZones;
subBlocks = formatArrResult.blocks;
// Only support tooltip sort by the first inline value. It's enough in most cases.
sortParam = formatArrResult.inlineValues[0];
Expand All @@ -65,6 +68,7 @@ export function defaultSeriesFormatTooltip(opt: {
const dimInfo = data.getDimensionInfo(tooltipDims[0]);
sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]);
inlineValueType = dimInfo.type;
inlineTimeZone = getDimensionTimeZone(series, dimInfo);
}
else {
sortParam = inlineValue = isValueArr ? value[0] : value;
Expand Down Expand Up @@ -94,6 +98,7 @@ export function defaultSeriesFormatTooltip(opt: {
noName: !trim(inlineName),
value: inlineValue,
valueType: inlineValueType,
timeZone: inlineTimeZone,
rawDataIndex: data.getRawIndex(dataIndex),
})
].concat(subBlocks || [] as any)
Expand All @@ -109,6 +114,7 @@ function formatTooltipArrayValue(
): {
inlineValues: unknown[];
inlineValueTypes: DimensionType[];
inlineTimeZones: string[];
blocks: TooltipMarkupBlockFragment[];
} {
// check: category-no-encode-has-axis-data in dataset.html
Expand All @@ -121,6 +127,7 @@ function formatTooltipArrayValue(

const inlineValues: unknown[] = [];
const inlineValueTypes: DimensionType[] = [];
const inlineTimeZones: string[] = [];
const blocks: TooltipMarkupBlockFragment[] = [];

tooltipDims.length
Expand All @@ -142,14 +149,25 @@ function formatTooltipArrayValue(
markerColor: colorStr,
name: dimInfo.displayName,
value: val,
valueType: dimInfo.type
valueType: dimInfo.type,
timeZone: getDimensionTimeZone(series, dimInfo)
}));
}
else {
inlineValues.push(val);
inlineValueTypes.push(dimInfo.type);
inlineTimeZones.push(getDimensionTimeZone(series, dimInfo));
}
}

return { inlineValues, inlineValueTypes, blocks };
return { inlineValues, inlineValueTypes, inlineTimeZones, blocks };
}

function getDimensionTimeZone(series: SeriesModel, dimInfo: {coordDim?: string}): string {
const axis = dimInfo.coordDim != null
? series.coordinateSystem?.getAxis?.(dimInfo.coordDim)
: null;
return axis && isTimeScale(axis.scale)
? axis.scale.getTimeZone()
: series.ecModel.getTimeZone();
}
Comment thread
konzen marked this conversation as resolved.
20 changes: 13 additions & 7 deletions src/component/tooltip/tooltipMarkup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ export interface TooltipMarkupNameValueBlock extends TooltipMarkupBlock {
// If needs to display original string with numeric guessing, set as 'ordinal'.
// If both `value` and `valueType` are array, each valueType[i] cooresponds to value[i].
valueType?: DimensionType | DimensionType[];
// Time zone for a temporal value. If both are arrays, each timeZone[i]
// corresponds to value[i].
timeZone?: string | string[];
// If `noName` or `noValue` is `true`, do not display name or value.
// Otherwise, always display them even if they are
// null/undefined/NaN/''... (displayed as '-').
Expand Down Expand Up @@ -293,7 +296,7 @@ function buildSection(
return subMarkupText;
}

const displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC);
const displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.timeZone);
const {nameStyle} = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode);
const tooltipLineHeight = getTooltipLineHeight(toolTipTextStyle);
if (ctx.renderMode === 'richText') {
Expand Down Expand Up @@ -323,11 +326,14 @@ function buildNameValue(
const noValue = fragment.noValue;
const noMarker = !fragment.markerType;
const name = fragment.name;
const useUTC = ctx.useUTC;
const timeZone = ctx.timeZone;
const valueTimeZone = fragment.timeZone;
const valueFormatter = fragment.valueFormatter || ctx.valueFormatter || ((value) => {
value = isArray(value) ? value : [value];
return map(value as unknown[], (val, idx) => makeValueReadable(
val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC
val,
isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption,
(isArray(valueTimeZone) ? valueTimeZone[idx] : valueTimeZone) || timeZone
));
});

Expand All @@ -344,7 +350,7 @@ function buildNameValue(
);
const readableName = noName
? ''
: makeValueReadable(name, 'ordinal', useUTC);
: makeValueReadable(name, 'ordinal', timeZone);
const valueTypeOption = fragment.valueType;
const readableValueList = noValue
? []
Expand Down Expand Up @@ -376,7 +382,7 @@ function buildNameValue(
}

interface TooltipMarkupBuildContext {
useUTC: boolean;
timeZone: string;
renderMode: TooltipRenderMode;
orderMode: TooltipOrderMode;
markupStyleCreator: TooltipMarkupStyleCreator;
Expand All @@ -392,7 +398,7 @@ export function buildTooltipMarkup(
markupStyleCreator: TooltipMarkupStyleCreator,
renderMode: TooltipRenderMode,
orderMode: TooltipOrderMode,
useUTC: boolean,
timeZone: string,
toolTipTextStyle: TooltipOption['textStyle']
): MarkupText {
if (!fragment) {
Expand All @@ -401,7 +407,7 @@ export function buildTooltipMarkup(

const builder = getBuilder(fragment);
const ctx: TooltipMarkupBuildContext = {
useUTC: useUTC,
timeZone: timeZone,
renderMode: renderMode,
orderMode: orderMode,
markupStyleCreator: markupStyleCreator,
Expand Down
5 changes: 5 additions & 0 deletions src/coord/axisCommonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ export interface LogAxisBaseOption extends NumericAxisBaseOptionCommon {
}
export interface TimeAxisBaseOption extends NumericAxisBaseOptionCommon {
type?: 'time';
/**
* IANA time zone used to align and format ticks on this axis.
* Overrides the global `timeZone` option.
*/
timeZone?: string;
axisLabel?: AxisLabelOption<'time'>;
}

Expand Down
12 changes: 9 additions & 3 deletions src/coord/axisHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ import {
OptionAxisType,
AXIS_TYPES,
CategoryTickLabelSplitBuildingOption,
TimeAxisBaseOption
} from './axisCommonTypes';
import SeriesData from '../data/SeriesData';
import { getStackedDimension } from '../data/helper/dataStackHelper';
import { Dictionary, DimensionName, NullUndefined, ScaleTick } from '../util/types';
import { ScaleExtentFixMinMax } from './scaleRawExtentInfo';
import { parseTimeAxisLabelFormatter } from '../util/time';
import { parseTimeAxisLabelFormatter, validateTimeZone } from '../util/time';
import { getScaleBreakHelper } from '../scale/break';
import { error } from '../util/log';
import {
Expand Down Expand Up @@ -87,6 +88,7 @@ export function createScaleByModel(
{type?: string}
& Pick<LogAxisBaseOption, 'logBase'>
& Pick<AxisBaseOptionCommon, 'breaks'>
& Pick<TimeAxisBaseOption, 'timeZone'>
>
& Partial<Pick<
AxisModelExtendedInCreator,
Expand All @@ -110,12 +112,16 @@ export function createScaleByModel(
: model.getCategories(),
extent: initExtentForUnion(),
});
case 'time':
case 'time': {
const timeZone = model.get('timeZone', true);
return new TimeScale({
locale: model.ecModel.getLocaleModel(),
useUTC: model.ecModel.get('useUTC'),
timeZone: timeZone != null
? validateTimeZone(timeZone)
: model.ecModel.getTimeZone(),
breakOption,
});
}
case 'log':
// See also #3749
return new LogScale({
Expand Down
27 changes: 26 additions & 1 deletion src/model/Global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { concatInternalOptions } from './internalComponentCreator';
import { LocaleOption } from '../core/locale';
import {PaletteMixin} from './mixin/palette';
import { error, warn } from '../util/log';
import { getSystemTimeZone, validateTimeZone } from '../util/time';

export interface GlobalModelSetOptionOpts {
replaceMerge: ComponentMainType | ComponentMainType[];
Expand Down Expand Up @@ -163,6 +164,8 @@ class GlobalModel extends Model<ECUnitOption> {

private _optionManager: OptionManager;

private _timeZone: string;

private _componentsMap: HashMap<ComponentModel[], ComponentMainType>;

/**
Expand Down Expand Up @@ -218,7 +221,6 @@ class GlobalModel extends Model<ECUnitOption> {
opts: GlobalModelSetOptionOpts,
optionPreprocessorFuncs: OptionPreprocessor[]
): void {

if (__DEV__) {
assert(option != null, 'option is null/undefined');
assert(
Expand Down Expand Up @@ -314,6 +316,18 @@ class GlobalModel extends Model<ECUnitOption> {
opt: InnerSetOptionOpts
): void {
const option = this.option;
const timeZone = newOption.timeZone != null
? newOption.timeZone
: option.timeZone;
if (timeZone != null) {
this._timeZone = validateTimeZone(timeZone);
}
else if (newOption.useUTC != null) {
this._timeZone = resolveTimeZone(newOption);
}
else if (this._timeZone == null) {
this._timeZone = resolveTimeZone(option);
}
Comment thread
konzen marked this conversation as resolved.
const componentsMap = this._componentsMap;
const componentsCount = this._componentsCount;
const newCmptTypes: ComponentMainType[] = [];
Expand Down Expand Up @@ -861,6 +875,10 @@ echarts.use([${seriesImportName}]);`);
return (this._seriesIndices || []).slice();
}

getTimeZone(): string {
return this._timeZone;
}

filterSeries<T>(
cb: (this: T, series: SeriesModel, rawSeriesIndex: number) => boolean,
context?: T
Expand Down Expand Up @@ -933,6 +951,7 @@ echarts.use([${seriesImportName}]);`);
// i.e. `chart.setOption(chart.getModel().option);` is forbidden.
ecModel.option = {} as ECUnitOption;
ecModel.option[OPTION_INNER_KEY] = OPTION_INNER_VALUE;
ecModel._timeZone = null;

// Init with series: [], in case of calling findSeries method
// before series initialized.
Expand All @@ -957,6 +976,12 @@ echarts.use([${seriesImportName}]);`);
})();
}

function resolveTimeZone(option: ECUnitOption): string {
return option.timeZone != null
? validateTimeZone(option.timeZone)
: option.useUTC ? 'UTC' : getSystemTimeZone();
}


/**
* Either `mainType` or `query` should be provided.
Expand Down
Loading