You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2022/01/05 09:55:29 UTC
[echarts] 01/01: feat(tooltip): add valueFormatter
This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch tooltip-value-formatter
in repository https://gitbox.apache.org/repos/asf/echarts.git
commit 4c7d9a4ab57e6da1a7ce89d494ab73a1a7cc1883
Author: pissang <bm...@gmail.com>
AuthorDate: Wed Jan 5 17:54:03 2022 +0800
feat(tooltip): add valueFormatter
---
src/component/tooltip/TooltipView.ts | 24 ++-
src/component/tooltip/tooltipMarkup.ts | 320 +++++++++++++++------------------
src/model/mixin/dataFormat.ts | 13 +-
src/util/types.ts | 7 +
test/tooltip-valueFormatter.html | 96 ++++++++++
5 files changed, 266 insertions(+), 194 deletions(-)
diff --git a/src/component/tooltip/TooltipView.ts b/src/component/tooltip/TooltipView.ts
index bc1e3a7..fc69ecf 100644
--- a/src/component/tooltip/TooltipView.ts
+++ b/src/component/tooltip/TooltipView.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { bind, each, clone, trim, isString, isFunction, isArray, isObject } from 'zrender/src/core/util';
+import { bind, each, clone, trim, isString, isFunction, isArray, isObject, extend } from 'zrender/src/core/util';
import env from 'zrender/src/core/env';
import TooltipHTMLContent from './TooltipHTMLContent';
import TooltipRichContent from './TooltipRichContent';
@@ -585,11 +585,16 @@ class TooltipView extends ComponentView {
const seriesTooltipResult = normalizeTooltipFormatResult(
series.formatTooltip(dataIndex, true, null)
);
- if (seriesTooltipResult.markupFragment) {
- axisSectionMarkup.blocks.push(seriesTooltipResult.markupFragment);
+ const frag = seriesTooltipResult.frag;
+ if (frag) {
+ const valueFormatter = buildTooltipModel(
+ [series as Model<TooltipableOption>],
+ globalTooltipModel
+ ).get('valueFormatter');
+ axisSectionMarkup.blocks.push(valueFormatter ? extend({ valueFormatter }, frag) : frag);
}
- if (seriesTooltipResult.markupText) {
- markupTextArrLegacy.push(seriesTooltipResult.markupText);
+ if (seriesTooltipResult.text) {
+ markupTextArrLegacy.push(seriesTooltipResult.text);
}
cbParamsList.push(cbParams);
});
@@ -682,16 +687,17 @@ class TooltipView extends ComponentView {
dataModel.formatTooltip(dataIndex, false, dataType)
);
const orderMode = tooltipModel.get('order');
- const markupText = seriesTooltipResult.markupFragment
- ? buildTooltipMarkup(
- seriesTooltipResult.markupFragment,
+ const valueFormatter = tooltipModel.get('valueFormatter');
+ const frag = seriesTooltipResult.frag;
+ const markupText = frag ? buildTooltipMarkup(
+ valueFormatter ? extend({ valueFormatter }, frag) : frag,
markupStyleCreator,
renderMode,
orderMode,
ecModel.get('useUTC'),
tooltipModel.get('textStyle')
)
- : seriesTooltipResult.markupText;
+ : seriesTooltipResult.text;
const asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;
diff --git a/src/component/tooltip/tooltipMarkup.ts b/src/component/tooltip/tooltipMarkup.ts
index 2e88c1d..03aeab0 100644
--- a/src/component/tooltip/tooltipMarkup.ts
+++ b/src/component/tooltip/tooltipMarkup.ts
@@ -19,7 +19,7 @@
import {
Dictionary, TooltipRenderMode, ColorString,
- TooltipOrderMode, DimensionType
+ TooltipOrderMode, DimensionType, CommonTooltipOption, OptionDataValue
} from '../../util/types';
import {
TooltipMarkerType, getTooltipMarker, encodeHTML,
@@ -88,8 +88,8 @@ function getTooltipTextStyle(
type GapLevel = number;
// See `TooltipMarkupLayoutIntent['innerGapLevel']`.
// (value from UI design)
-const HTML_GAPS: { [key in GapLevel]: number } = [0, 10, 20, 30];
-const RICH_TEXT_GAPS: { [key in GapLevel]: string } = ['', '\n', '\n\n', '\n\n\n'];
+const HTML_GAPS: Record<GapLevel, number> = [0, 10, 20, 30];
+const RICH_TEXT_GAPS: Record<GapLevel, string> = ['', '\n', '\n\n', '\n\n\n'];
/**
* This is an abstract layer to insulate the upper usage of tooltip content
@@ -128,7 +128,6 @@ export type TooltipMarkupBlockFragment =
interface TooltipMarkupBlock {
// Use to make comparison when `sortBlocks: true`.
sortParam?: unknown;
- __gapLevelBetweenSubBlocks?: number;
}
export interface TooltipMarkupSection extends TooltipMarkupBlock {
@@ -141,6 +140,8 @@ export interface TooltipMarkupSection extends TooltipMarkupBlock {
blocks?: TooltipMarkupBlockFragment[];
// Enable to sort blocks when making final html or richText.
sortBlocks?: boolean;
+
+ valueFormatter?: CommonTooltipOption<unknown>['valueFormatter']
}
export interface TooltipMarkupNameValueBlock extends TooltipMarkupBlock {
@@ -161,6 +162,8 @@ export interface TooltipMarkupNameValueBlock extends TooltipMarkupBlock {
// null/undefined/NaN/''... (displayed as '-').
noName?: boolean;
noValue?: boolean;
+
+ valueFormatter?: CommonTooltipOption<unknown>['valueFormatter']
}
/**
@@ -180,10 +183,7 @@ export function createTooltipMarkup(type: TooltipMarkupBlockFragment['type'], op
// Can be null/undefined, which means generate nothing markup text.
type MarkupText = string;
interface TooltipMarkupFragmentBuilder {
- planLayout(
- fragment: TooltipMarkupBlockFragment
- ): void;
- build(
+ (
ctx: TooltipMarkupBuildContext,
fragment: TooltipMarkupBlockFragment,
topMarginForOuterGap: number,
@@ -191,167 +191,51 @@ interface TooltipMarkupFragmentBuilder {
): MarkupText;
}
-function getBuilder(fragment: TooltipMarkupBlockFragment): TooltipMarkupFragmentBuilder {
- return hasOwn(builderMap, fragment.type) && builderMap[fragment.type];
+function isSectionFragment(frag: TooltipMarkupBlockFragment): frag is TooltipMarkupSection {
+ return frag.type === 'section';
}
-const builderMap: { [key in TooltipMarkupBlockFragment['type']]: TooltipMarkupFragmentBuilder } = {
-
- /**
- * A `section` block is like:
- * ```
- * header
- * subBlock
- * subBlock
- * ...
- * ```
- */
- section: {
- planLayout: function (fragment: TooltipMarkupSection) {
- const subBlockLen = fragment.blocks.length;
- const thisBlockHasInnerGap = subBlockLen > 1 || (subBlockLen > 0 && !fragment.noHeader);
-
- let thisGapLevelBetweenSubBlocks = 0;
- each(fragment.blocks, function (subBlock) {
- getBuilder(subBlock).planLayout(subBlock);
- const subGapLevel = subBlock.__gapLevelBetweenSubBlocks;
-
- // If the some of the sub-blocks have some gaps (like 10px) inside, this block
- // should use a larger gap (like 20px) to distinguish those sub-blocks.
- if (subGapLevel >= thisGapLevelBetweenSubBlocks) {
- thisGapLevelBetweenSubBlocks = subGapLevel + (
- (
- thisBlockHasInnerGap && (
- // 0 always can not be readable gap level.
- !subGapLevel
- // If no header, always keep the sub gap level. Otherwise
- // look weird in case `multipleSeries`.
- || (subBlock.type === 'section' && !subBlock.noHeader)
- )
- ) ? 1 : 0
- );
- }
- });
- fragment.__gapLevelBetweenSubBlocks = thisGapLevelBetweenSubBlocks;
- },
-
- build(
- ctx,
- fragment: TooltipMarkupSection,
- topMarginForOuterGap,
- toolTipTextStyle
- ): string {
- const noHeader = fragment.noHeader;
- const gaps = getGap(fragment);
-
- const subMarkupText = buildSubBlocks(
- ctx,
- fragment,
- noHeader ? topMarginForOuterGap : gaps.html,
- toolTipTextStyle
- );
-
- if (noHeader) {
- return subMarkupText;
- }
+function getBuilder(frag: TooltipMarkupBlockFragment): TooltipMarkupFragmentBuilder {
+ return isSectionFragment(frag) ? buildSection : buildNameValue;
+}
- const displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC);
- const {nameStyle} = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode);
- if (ctx.renderMode === 'richText') {
- return wrapInlineNameRichText(ctx, displayableHeader, nameStyle as RichTextStyle) + gaps.richText
- + subMarkupText;
- }
- else {
- return wrapBlockHTML(
- `<div style="${nameStyle};${TOOLTIP_LINE_HEIGHT_CSS};">`
- + encodeHTML(displayableHeader)
- + '</div>'
- + subMarkupText,
- topMarginForOuterGap
+function getBlockGapLevel(frag: TooltipMarkupBlockFragment) {
+ if (isSectionFragment(frag)) {
+ let thisGapLevelBetweenSubBlocks = 0;
+ const subBlockLen = frag.blocks.length;
+ const thisBlockHasInnerGap = subBlockLen > 1 || (subBlockLen > 0 && !frag.noHeader);
+ each(frag.blocks, function (subBlock) {
+ const subGapLevel = getBlockGapLevel(subBlock);
+ // If the some of the sub-blocks have some gaps (like 10px) inside, this block
+ // should use a larger gap (like 20px) to distinguish those sub-blocks.
+ if (subGapLevel >= thisGapLevelBetweenSubBlocks) {
+ thisGapLevelBetweenSubBlocks = subGapLevel + (
+ (
+ thisBlockHasInnerGap && (
+ // 0 always can not be readable gap level.
+ !subGapLevel
+ // If no header, always keep the sub gap level. Otherwise
+ // look weird in case `multipleSeries`.
+ || (subBlock.type === 'section' && !subBlock.noHeader)
+ )
+ ) ? 1 : 0
);
}
- }
- },
-
- /**
- * A `nameValue` block is like:
- * ```
- * marker name value
- * ```
- */
- nameValue: {
- planLayout: function (fragment: TooltipMarkupNameValueBlock) {
- fragment.__gapLevelBetweenSubBlocks = 0;
- },
-
- build(ctx, fragment: TooltipMarkupNameValueBlock, topMarginForOuterGap, toolTipTextStyle) {
- const renderMode = ctx.renderMode;
- const noName = fragment.noName;
- const noValue = fragment.noValue;
- const noMarker = !fragment.markerType;
- const name = fragment.name;
- const value = fragment.value;
- const useUTC = ctx.useUTC;
-
- if (noName && noValue) {
- return;
- }
-
- const markerStr = noMarker
- ? ''
- : ctx.markupStyleCreator.makeTooltipMarker(
- fragment.markerType,
- fragment.markerColor || '#333',
- renderMode
- );
- const readableName = noName
- ? ''
- : makeValueReadable(name, 'ordinal', useUTC);
- const valueTypeOption = fragment.valueType;
- const readableValueList = noValue
- ? []
- : (isArray(value)
- ? map(value, (val, idx) => makeValueReadable(
- val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC
- ))
- : [makeValueReadable(
- value, isArray(valueTypeOption) ? valueTypeOption[0] : valueTypeOption, useUTC
- )]
- );
- const valueAlignRight = !noMarker || !noName;
- // It little weird if only value next to marker but far from marker.
- const valueCloseToMarker = !noMarker && noName;
-
- const {nameStyle, valueStyle} = getTooltipTextStyle(toolTipTextStyle, renderMode);
-
- return renderMode === 'richText'
- ? (
- (noMarker ? '' : markerStr)
- + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle as RichTextStyle))
- // Value has commas inside, so use ' ' as delimiter for multiple values.
- + (noValue ? '' : wrapInlineValueRichText(
- ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle as RichTextStyle
- ))
- )
- : wrapBlockHTML(
- (noMarker ? '' : markerStr)
- + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle as string))
- + (noValue ? '' : wrapInlineValueHTML(
- readableValueList, valueAlignRight, valueCloseToMarker, valueStyle as string
- )),
- topMarginForOuterGap
- );
- }
+ });
}
-};
-
+ return 0;
+}
-function buildSubBlocks(
+function buildSection(
ctx: TooltipMarkupBuildContext,
fragment: TooltipMarkupSection,
topMarginForOuterGap: number,
- tooltipTextStyle: TooltipOption['textStyle']
-): MarkupText {
+ toolTipTextStyle: TooltipOption['textStyle']
+) {
+ const noHeader = fragment.noHeader;
+
+ const gaps = getGap(getBlockGapLevel(fragment));
+
const subMarkupTextList: string[] = [];
let subBlocks = fragment.blocks || [];
assert(!subBlocks || isArray(subBlocks));
@@ -371,25 +255,102 @@ function buildSubBlocks(
}
}
- const gaps = getGap(fragment);
each(subBlocks, function (subBlock, idx) {
- const subMarkupText = getBuilder(subBlock).build(
- ctx,
+ const valueFormatter = fragment.valueFormatter;
+ const subMarkupText = getBuilder(subBlock)(
+ // Inherit valueFormatter
+ valueFormatter ? extend(extend({}, ctx), { valueFormatter }) : ctx,
subBlock,
idx > 0 ? gaps.html : 0,
- tooltipTextStyle
+ toolTipTextStyle
);
subMarkupText != null && subMarkupTextList.push(subMarkupText);
});
- if (!subMarkupTextList.length) {
+ const subMarkupText = ctx.renderMode === 'richText'
+ ? subMarkupTextList.join(gaps.richText)
+ : wrapBlockHTML(
+ subMarkupTextList.join(''),
+ topMarginForOuterGap
+ );
+
+ if (noHeader) {
+ return subMarkupText;
+ }
+
+ const displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC);
+ const {nameStyle} = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode);
+ if (ctx.renderMode === 'richText') {
+ return wrapInlineNameRichText(ctx, displayableHeader, nameStyle as RichTextStyle) + gaps.richText
+ + subMarkupText;
+ }
+ else {
+ return wrapBlockHTML(
+ `<div style="${nameStyle};${TOOLTIP_LINE_HEIGHT_CSS};">`
+ + encodeHTML(displayableHeader)
+ + '</div>'
+ + subMarkupText,
+ topMarginForOuterGap
+ );
+ }
+}
+
+function buildNameValue(
+ ctx: TooltipMarkupBuildContext,
+ fragment: TooltipMarkupNameValueBlock,
+ topMarginForOuterGap: number,
+ toolTipTextStyle: TooltipOption['textStyle']
+) {
+ const renderMode = ctx.renderMode;
+ const noName = fragment.noName;
+ const noValue = fragment.noValue;
+ const noMarker = !fragment.markerType;
+ const name = fragment.name;
+ const useUTC = ctx.useUTC;
+ 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
+ ));
+ });
+
+ if (noName && noValue) {
return;
}
- return ctx.renderMode === 'richText'
- ? subMarkupTextList.join(gaps.richText)
+ const markerStr = noMarker
+ ? ''
+ : ctx.markupStyleCreator.makeTooltipMarker(
+ fragment.markerType,
+ fragment.markerColor || '#333',
+ renderMode
+ );
+ const readableName = noName
+ ? ''
+ : makeValueReadable(name, 'ordinal', useUTC);
+ const valueTypeOption = fragment.valueType;
+ const readableValueList = noValue ? [] : valueFormatter(fragment.value as OptionDataValue);
+ const valueAlignRight = !noMarker || !noName;
+ // It little weird if only value next to marker but far from marker.
+ const valueCloseToMarker = !noMarker && noName;
+
+ const {nameStyle, valueStyle} = getTooltipTextStyle(toolTipTextStyle, renderMode);
+
+ return renderMode === 'richText'
+ ? (
+ (noMarker ? '' : markerStr)
+ + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle as RichTextStyle))
+ // Value has commas inside, so use ' ' as delimiter for multiple values.
+ + (noValue ? '' : wrapInlineValueRichText(
+ ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle as RichTextStyle
+ ))
+ )
: wrapBlockHTML(
- subMarkupTextList.join(''),
+ (noMarker ? '' : markerStr)
+ + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle as string))
+ + (noValue ? '' : wrapInlineValueHTML(
+ readableValueList, valueAlignRight, valueCloseToMarker, valueStyle as string
+ )),
topMarginForOuterGap
);
}
@@ -399,6 +360,8 @@ interface TooltipMarkupBuildContext {
renderMode: TooltipRenderMode;
orderMode: TooltipOrderMode;
markupStyleCreator: TooltipMarkupStyleCreator;
+
+ valueFormatter: CommonTooltipOption<unknown>['valueFormatter']
}
/**
@@ -417,25 +380,24 @@ export function buildTooltipMarkup(
}
const builder = getBuilder(fragment);
- builder.planLayout(fragment);
const ctx: TooltipMarkupBuildContext = {
useUTC: useUTC,
renderMode: renderMode,
orderMode: orderMode,
- markupStyleCreator: markupStyleCreator
+ markupStyleCreator: markupStyleCreator,
+ valueFormatter: fragment.valueFormatter
};
- return builder.build(ctx, fragment, 0, toolTipTextStyle);
+ return builder(ctx, fragment, 0, toolTipTextStyle);
}
-function getGap(fragment: TooltipMarkupBlock): {
+function getGap(gapLevel: number): {
html: number;
richText: string
} {
- const gapLevelBetweenSubBlocks = fragment.__gapLevelBetweenSubBlocks;
return {
- html: HTML_GAPS[gapLevelBetweenSubBlocks],
- richText: RICH_TEXT_GAPS[gapLevelBetweenSubBlocks]
+ html: HTML_GAPS[gapLevel],
+ richText: RICH_TEXT_GAPS[gapLevel]
};
}
@@ -462,7 +424,7 @@ function wrapInlineNameHTML(
}
function wrapInlineValueHTML(
- valueList: string[],
+ valueList: string | string[],
alignRight: boolean,
valueCloseToMarker: boolean,
style: string
@@ -470,6 +432,7 @@ function wrapInlineValueHTML(
// Do not too close to marker, considering there are multiple values separated by spaces.
const paddingStr = valueCloseToMarker ? '10px' : '20px';
const alignCSS = alignRight ? `float:right;margin-left:${paddingStr}` : '';
+ valueList = isArray(valueList) ? valueList : [valueList];
return (
`<span style="${alignCSS};${style}">`
// Value has commas inside, so use ' ' as delimiter for multiple values.
@@ -484,7 +447,7 @@ function wrapInlineNameRichText(ctx: TooltipMarkupBuildContext, name: string, st
function wrapInlineValueRichText(
ctx: TooltipMarkupBuildContext,
- valueList: string[],
+ values: string | string[],
alignRight: boolean,
valueCloseToMarker: boolean,
style: RichTextStyle
@@ -493,7 +456,10 @@ function wrapInlineValueRichText(
const paddingLeft = valueCloseToMarker ? 10 : 20;
alignRight && styles.push({ padding: [0, 0, 0, paddingLeft], align: 'right' });
// Value has commas inside, so use ' ' as delimiter for multiple values.
- return ctx.markupStyleCreator.wrapRichTextStyle(valueList.join(' '), styles);
+ return ctx.markupStyleCreator.wrapRichTextStyle(
+ isArray(values) ? values.join(' ') : values,
+ styles
+ );
}
diff --git a/src/model/mixin/dataFormat.ts b/src/model/mixin/dataFormat.ts
index 87cf12b..9671354 100644
--- a/src/model/mixin/dataFormat.ts
+++ b/src/model/mixin/dataFormat.ts
@@ -220,14 +220,11 @@ type TooltipFormatResult =
/**
* For backward compat, normalize the return from `formatTooltip`.
*/
-export function normalizeTooltipFormatResult(
- result: TooltipFormatResult
- // markersExisting: Dictionary<ColorString>
-): {
+export function normalizeTooltipFormatResult(result: TooltipFormatResult): {
// If `markupFragment` exists, `markupText` should be ignored.
- markupFragment: TooltipMarkupBlockFragment;
+ frag: TooltipMarkupBlockFragment;
// Can be `null`/`undefined`, means no tooltip.
- markupText: string;
+ text: string;
// Merged with `markersExisting`.
// markers: Dictionary<ColorString>;
} {
@@ -256,8 +253,8 @@ export function normalizeTooltipFormatResult(
}
return {
- markupText: markupText,
+ text: markupText,
// markers: markers || markersExisting,
- markupFragment: markupFragment
+ frag: markupFragment
};
}
diff --git a/src/util/types.ts b/src/util/types.ts
index 95e5b50..893de66 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -1253,6 +1253,13 @@ export interface CommonTooltipOption<FormatterParams> {
alwaysShowContent?: boolean
formatter?: string | TooltipFormatterCallback<FormatterParams>
+
+ /**
+ * Formatter of value.
+ *
+ * Will be ignored if tooltip.formatter is specified.
+ */
+ valueFormatter?: (value: OptionDataValue | OptionDataValue[]) => string
/**
* Absolution pixel [x, y] array. Or relative percent string [x, y] array.
* If trigger is 'item'. position can be set to 'inside' / 'top' / 'left' / 'right' / 'bottom',
diff --git a/test/tooltip-valueFormatter.html b/test/tooltip-valueFormatter.html
new file mode 100644
index 0000000..3d6f9e1
--- /dev/null
+++ b/test/tooltip-valueFormatter.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <script src="lib/simpleRequire.js"></script>
+ <script src="lib/config.js"></script>
+ <script src="lib/jquery.min.js"></script>
+ <script src="lib/facePrint.js"></script>
+ <script src="lib/testHelper.js"></script>
+ <!-- <script src="ut/lib/canteen.js"></script> -->
+ <link rel="stylesheet" href="lib/reset.css" />
+ </head>
+ <body>
+ <style>
+ </style>
+
+
+
+ <div id="main0"></div>
+
+
+
+
+
+
+ <script>
+ require([
+ 'echarts'
+ ], function (echarts) {
+ var option;
+
+ option = {
+ animation: false,
+ tooltip: {
+ position: 'top',
+ valueFormatter: (val) => val + '%'
+ },
+ xAxis: {
+ type: 'category',
+ data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: [50, 80, 70, 20, 30, 10, 100],
+ type: 'bar',
+ showBackground: true
+ }
+ ]
+ };
+
+ var chart = testHelper.create(echarts, 'main0', {
+ title: [
+ 'Basic valueFormatter of item tooltip'
+ ],
+ option: option
+ // height: 300,
+ // buttons: [{text: 'btn-txt', onclick: function () {}}],
+ // recordCanvas: true,
+ });
+
+ chart.dispatchAction({
+ type: 'showTip',
+ dataIndex: 2,
+ seriesIndex: 0
+ });
+ });
+ </script>
+
+
+ </body>
+</html>
+
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org