diff --git a/.asf.yaml b/.asf.yaml index c35ff79788..63abb9c295 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -28,3 +28,36 @@ github: - data-viz - canvas - svg + protected_branches: + master: + required_status_checks: + # strict means "Require branches to be up to date before merging". + strict: false + # contexts are the names of checks that must pass + # contexts: + # - gh-infra/jenkins + required_pull_request_reviews: + dismiss_stale_reviews: true + require_code_owner_reviews: false + required_approving_review_count: 1 + required_linear_history: false + required_signatures: false + release: + required_status_checks: + strict: false + required_pull_request_reviews: + dismiss_stale_reviews: true + require_code_owner_reviews: false + required_approving_review_count: 1 + required_linear_history: false + required_signatures: false + next: + required_status_checks: + strict: false + required_pull_request_reviews: + dismiss_stale_reviews: true + require_code_owner_reviews: false + required_approving_review_count: 1 + required_linear_history: false + required_signatures: false + diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 6d589b6763..0000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,60 +0,0 @@ -# Configuration for probot-stale - https://github.com/probot/stale - -# Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 731 # two years - -# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. -# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 7 - -# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) -onlyLabels: [] - -# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable -exemptLabels: - - "maybe-later" - - "priority: high" - -# Set to true to ignore issues in a project (defaults to false) -exemptProjects: true - -# Set to true to ignore issues in a milestone (defaults to false) -exemptMilestones: false - -# Set to true to ignore issues with an assignee (defaults to false) -exemptAssignees: false - -# Label to use when marking as stale -staleLabel: stale - -# Comment to post when marking as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. - -# Comment to post when removing the stale label. -unmarkComment: > - This issue is marked to be `stale` and is going to be closed within a week. If you think it shouldn't be closed, please leave a comment. - -# Comment to post when closing a stale Issue or Pull Request. -# closeComment: > -# Your comment here. - -# Limit the number of actions per hour, from 1-30. Default is 30 -limitPerRun: 30 - -# Limit to only `issues` or `pulls` -# only: issues - -# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': -# pulls: -# daysUntilStale: 30 -# markComment: > -# This pull request has been automatically marked as stale because it has not had -# recent activity. It will be closed if no further activity occurs. Thank you -# for your contributions. - -# issues: -# exemptLabels: -# - confirmed diff --git a/.github/workflows/nightly-next.yml b/.github/workflows/nightly-next.yml new file mode 100644 index 0000000000..7028c1db06 --- /dev/null +++ b/.github/workflows/nightly-next.yml @@ -0,0 +1,37 @@ +name: Publish Nightly Next + +on: + schedule: + - cron: '0 9 * * *' # After zrender nightly published + # committers can manually trigger with workflow_dispatch + workflow_dispatch: {} + repository_dispatch: + types: publish-nightly-next + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [12.x] + + steps: + - uses: actions/checkout@v2 + with: + ref: next + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + registry-url: https://registry.npmjs.org/ + - name: Setup and publish nightly + run: | + npm ci + npm run release + npm run test + npm run test:dts + node build/prepareNightly.js --next + npm publish --tag next + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000..18f55567c5 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,28 @@ +name: Closing Stale Issues + +permissions: + issues: write + pull-requests: write + +on: + schedule: + - cron: '0 21 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - name: Close Stale Issues + uses: actions/stale@v4.0.0 + with: + days-before-stale: 730 + days-before-close: 7 + stale-issue-label: stale + stale-pr-label: stale + stale-issue-message: 'This issue has been automatically marked as stale because it did not have recent activity. It will be closed in 7 days if no further activity occurs. If you wish not to mark it as stale, please leave a comment in this issue.' + close-issue-message: 'This issue has been automatically closed because it did not have recent activity. If this remains to be a problem with the latest version of Apache ECharts, please open a new issue and link this to it. Thanks!' + stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. If you wish not to mark it as stale, please leave a comment in this PR. We are sorry for this but 2 years is a long time and the code base has been changed a lot. Thanks for your contribution anyway.' + close-pr-message: 'This PR has been automatically closed because it has not had recent activity. Sorry for that and we are looking forward to your next contribution.' + exempt-issue-labels: 'FAQ,priority: high' + operations-per-run: 500 + ascending: true diff --git a/build/prepareNightly.js b/build/prepareNightly.js index 442d3d508f..44d20ccec1 100644 --- a/build/prepareNightly.js +++ b/build/prepareNightly.js @@ -23,26 +23,36 @@ const packageJsonPath = __dirname + '/../package.json'; const nightlyPackageName = 'echarts-nightly'; const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); -const version = packageJson.version; -const parts = /(\d+)\.(\d+)\.(\d+)($|\-.*)/.exec(version); -if (!parts) { - throw new Error(`Invalid version number ${version}`); -} -// Add date to version. -const major = +parts[1]; -const minor = +parts[2]; -let patch = +parts[3]; -const notDev = !(parts[4] && parts[4].includes('-dev')); -if (notDev) { - // It's previous stable or rc version. Dev version should be higher. - patch++; -} -const date = new Date().toISOString().replace(/:|T|\.|-/g, '').slice(0, 8); -const nightlyVersion = `${major}.${minor}.${patch}-dev.${date}`; +function updateVersion(version) { + const isNext = process.argv.includes('--next'); + const parts = /(\d+)\.(\d+)\.(\d+)($|\-)/.exec(version); + if (!parts) { + throw new Error(`Invalid version number ${version}`); + } + // Add date to version. + const major = +parts[1]; + let minor = +parts[2]; + let patch = +parts[3]; + const isStable = !parts[4]; + if (isStable) { + // It's previous stable version. Dev version should be higher. + if (isNext) { + // Increase minor version for next branch. + minor++; + } + else { + // Increase main version for master branch. + patch++; + } + } + + const date = new Date().toISOString().replace(/:|T|\.|-/g, '').slice(0, 8); + return `${major}.${minor}.${patch}-dev.${date}`; +} packageJson.name = nightlyPackageName; -packageJson.version = nightlyVersion; +packageJson.version = updateVersion(packageJson.version); fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8'); diff --git a/index.d.ts b/index.d.ts index 20195af345..811908a873 100644 --- a/index.d.ts +++ b/index.d.ts @@ -17,4 +17,7 @@ * under the License. */ -export * from './types/dist/echarts'; \ No newline at end of file +import * as echarts from './types/dist/echarts'; +// Export for UMD module. +export as namespace echarts; +export = echarts; \ No newline at end of file diff --git a/src/chart/bar/BarSeries.ts b/src/chart/bar/BarSeries.ts index 8c97a8b616..d2b76ab3a7 100644 --- a/src/chart/bar/BarSeries.ts +++ b/src/chart/bar/BarSeries.ts @@ -26,7 +26,9 @@ import { OptionDataItemObject, SeriesSamplingOptionMixin, SeriesLabelOption, - SeriesEncodeOptionMixin + SeriesEncodeOptionMixin, + DefaultStatesMixinEmpasis, + CallbackDataParams } from '../../util/types'; import type Cartesian2D from '../../coord/cartesian/Cartesian2D'; import createSeriesData from '../helper/createSeriesData'; @@ -41,21 +43,28 @@ export type PolarBarLabelPosition = SeriesLabelOption['position'] export type BarSeriesLabelOption = Omit & {position?: PolarBarLabelPosition | 'outside'}; -export interface BarStateOption { - itemStyle?: BarItemStyleOption +export interface BarStateOption { + itemStyle?: BarItemStyleOption label?: BarSeriesLabelOption } -export interface BarItemStyleOption extends ItemStyleOption { +interface BarStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} + +export interface BarItemStyleOption extends ItemStyleOption { // Border radius is not supported for bar on polar borderRadius?: number | number[] } -export interface BarDataItemOption extends BarStateOption, StatesOptionMixin, +export interface BarDataItemOption extends BarStateOption, + StatesOptionMixin, OptionDataItemObject { cursor?: string } -export interface BarSeriesOption extends BaseBarSeriesOption, BarStateOption, +export interface BarSeriesOption + extends BaseBarSeriesOption, BarStatesMixin>, + BarStateOption, SeriesStackOptionMixin, SeriesSamplingOptionMixin, SeriesEncodeOptionMixin { type?: 'bar' @@ -151,7 +160,7 @@ class BarSeriesModel extends BaseBarSeriesModel { }, realtimeSort: false - }); + } as BarSeriesOption); } diff --git a/src/chart/bar/BarView.ts b/src/chart/bar/BarView.ts index e4be916699..dce754a46c 100644 --- a/src/chart/bar/BarView.ts +++ b/src/chart/bar/BarView.ts @@ -746,18 +746,9 @@ const elementCreator: { seriesModel, data, newIndex, layout: SectorLayout, isRadial: boolean, animationModel, axisModel, isUpdate, roundCap ) { - // Keep the same logic with bar in catesion: use end value to control - // direction. Notice that if clockwise is true (by default), the sector - // will always draw clockwisely, no matter whether endAngle is greater - // or less than startAngle. - const clockwise = layout.startAngle < layout.endAngle; - const ShapeClass = (!isRadial && roundCap) ? Sausage : Sector; - const sector = new ShapeClass({ - shape: defaults({ - clockwise: clockwise - }, layout), + shape: layout, z2: 1 }); @@ -909,7 +900,8 @@ const getLayout: { r0: layout.r0, r: layout.r, startAngle: layout.startAngle, - endAngle: layout.endAngle + endAngle: layout.endAngle, + clockwise: layout.clockwise } as SectorLayout; } }; diff --git a/src/chart/bar/BaseBarSeries.ts b/src/chart/bar/BaseBarSeries.ts index d4c3fa5d19..e94e53d7e6 100644 --- a/src/chart/bar/BaseBarSeries.ts +++ b/src/chart/bar/BaseBarSeries.ts @@ -24,14 +24,14 @@ import { SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin, ScaleDataValue, - DefaultExtraStateOpts + DefaultStatesMixin } from '../../util/types'; import GlobalModel from '../../model/Global'; import Cartesian2D from '../../coord/cartesian/Cartesian2D'; import SeriesData from '../../data/SeriesData'; -export interface BaseBarSeriesOption +export interface BaseBarSeriesOption extends SeriesOption, SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin { diff --git a/src/chart/boxplot/BoxplotSeries.ts b/src/chart/boxplot/BoxplotSeries.ts index 60cbc41871..b87276b39b 100644 --- a/src/chart/boxplot/BoxplotSeries.ts +++ b/src/chart/boxplot/BoxplotSeries.ts @@ -28,7 +28,8 @@ import { OptionDataValueNumeric, StatesOptionMixin, SeriesEncodeOptionMixin, - DefaultEmphasisFocus + DefaultEmphasisFocus, + CallbackDataParams } from '../../util/types'; import type Axis2D from '../../coord/cartesian/Axis2D'; import Cartesian2D from '../../coord/cartesian/Cartesian2D'; @@ -37,9 +38,8 @@ import { mixin } from 'zrender/src/core/util'; // [min, Q1, median (or Q2), Q3, max] type BoxplotDataValue = OptionDataValueNumeric[]; - -export interface BoxplotStateOption { - itemStyle?: ItemStyleOption +export interface BoxplotStateOption { + itemStyle?: ItemStyleOption label?: SeriesLabelOption } @@ -55,7 +55,9 @@ interface ExtraStateOption { } } -export interface BoxplotSeriesOption extends SeriesOption, BoxplotStateOption, +export interface BoxplotSeriesOption + extends SeriesOption, ExtraStateOption>, + BoxplotStateOption, SeriesOnCartesianOptionMixin, SeriesEncodeOptionMixin { type?: 'boxplot' diff --git a/src/chart/candlestick/CandlestickSeries.ts b/src/chart/candlestick/CandlestickSeries.ts index d71cecd57d..e9079ca37b 100644 --- a/src/chart/candlestick/CandlestickSeries.ts +++ b/src/chart/candlestick/CandlestickSeries.ts @@ -28,17 +28,17 @@ import { ColorString, SeriesLabelOption, SeriesLargeOptionMixin, - OptionDataValueNumeric, StatesOptionMixin, SeriesEncodeOptionMixin, - DefaultEmphasisFocus + DefaultEmphasisFocus, + OptionDataValue } from '../../util/types'; import SeriesData from '../../data/SeriesData'; import Cartesian2D from '../../coord/cartesian/Cartesian2D'; import { BrushCommonSelectorsForSeries } from '../../component/brush/selector'; import { mixin } from 'zrender/src/core/util'; -type CandlestickDataValue = OptionDataValueNumeric[]; +type CandlestickDataValue = OptionDataValue[]; interface CandlestickItemStyleOption extends ItemStyleOption { color0?: ZRColor diff --git a/src/chart/custom/CustomSeries.ts b/src/chart/custom/CustomSeries.ts index 2b8bb3c9b2..8fa8285c77 100644 --- a/src/chart/custom/CustomSeries.ts +++ b/src/chart/custom/CustomSeries.ts @@ -158,9 +158,6 @@ export interface CustomBaseElementOption extends Partial & TransitionAnyOption; // updateDuringAnimation during?(params: CustomBaseDuringAPI): void; - - focus?: 'none' | 'self' | 'series' | ArrayLike - blurScope?: BlurScope }; export interface CustomDisplayableOption extends CustomBaseElementOption, Partial @@ -204,17 +201,17 @@ export interface CustomBaseZRPathOption + rect: Partial + sector: Partial + polygon: Partial + polyline: Partial + line: Partial + arc: Partial + bezierCurve: Partial + ring: Partial + ellipse: Partial + compoundPath: Partial } interface CustomSVGPathShapeOption { @@ -270,7 +267,10 @@ export type CustomElementOption = CustomPathOption | CustomGroupOption; // Can only set focus, blur on the root element. -export type CustomChildElementOption = Omit; +export type CustomRootElementOption = CustomElementOption & { + focus?: 'none' | 'self' | 'series' | ArrayLike + blurScope?: BlurScope +}; export type CustomElementOptionOnState = CustomDisplayableOptionOnState | CustomImageOptionOnState; @@ -287,7 +287,13 @@ export interface CustomSeriesRenderItemAPI extends value(dim: DimensionLoose, dataIndexInside?: number): ParsedValue; ordinalRawValue(dim: DimensionLoose, dataIndexInside?: number): ParsedValue | OrdinalRawValue; + /** + * @deprecated + */ style(userProps?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps; + /** + * @deprecated + */ styleEmphasis(userProps?: ZRStyleProps, dataIndexInside?: number): ZRStyleProps; visual( visualType: VT, @@ -310,7 +316,7 @@ export interface CustomSeriesRenderItemCoordinateSystemAPI { ): number[]; size?( dataSize: OptionDataValue | OptionDataValue[], - dataItem: OptionDataValue | OptionDataValue[] + dataItem?: OptionDataValue | OptionDataValue[] ): number | number[]; } @@ -330,18 +336,16 @@ export interface CustomSeriesRenderItemParams { actionType?: string; } -type CustomSeriesRenderItem = ( + +export type CustomSeriesRenderItemReturn = CustomRootElementOption | undefined | null; + +export type CustomSeriesRenderItem = ( params: CustomSeriesRenderItemParams, api: CustomSeriesRenderItemAPI -) => CustomElementOption; - -interface CustomSeriesStateOption { - itemStyle?: ItemStyleOption; - label?: LabelOption; -} +) => CustomSeriesRenderItemReturn; export interface CustomSeriesOption extends - SeriesOption, // don't support StateOption in custom series. + SeriesOption, // don't support StateOption in custom series. SeriesEncodeOptionMixin, SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin, @@ -356,12 +360,33 @@ export interface CustomSeriesOption extends renderItem?: CustomSeriesRenderItem; + /** + * @deprecated + */ + itemStyle?: ItemStyleOption; + /** + * @deprecated + */ + label?: LabelOption; + + /** + * @deprecated + */ + emphasis?: { + /** + * @deprecated + */ + itemStyle?: ItemStyleOption; + /** + * @deprecated + */ + label?: LabelOption; + } + // Only works on polar and cartesian2d coordinate system. clip?: boolean; } -export interface LegacyCustomSeriesOption extends SeriesOption, CustomSeriesStateOption {} - export const customInnerStore = makeInner<{ info: CustomExtraElementInfo; customPathData: string; diff --git a/src/chart/custom/CustomView.ts b/src/chart/custom/CustomView.ts index 1ba6d86b05..f084d84228 100644 --- a/src/chart/custom/CustomView.ts +++ b/src/chart/custom/CustomView.ts @@ -82,7 +82,6 @@ import CustomSeriesModel, { CustomDisplayableOption, CustomSeriesRenderItemAPI, CustomSeriesRenderItemParams, - LegacyCustomSeriesOption, CustomGroupOption, WrapEncodeDefRet, NonStyleVisualProps, @@ -92,7 +91,8 @@ import CustomSeriesModel, { customInnerStore, LooseElementProps, PrepareCustomInfo, - CustomPathOption + CustomPathOption, + CustomRootElementOption } from './CustomSeries'; import { prepareShapeOrExtraAllPropsFinal, @@ -102,6 +102,7 @@ import { prepareTransformTransitionFrom } from './prepare'; import { PatternObject } from 'zrender/src/graphic/Pattern'; +import { CustomSeriesOption } from '../../export/option'; const transformPropNamesStr = keys(TRANSFORM_PROPS).join(', '); @@ -879,23 +880,23 @@ function makeRenderItem( // Do not support call `api` asynchronously without dataIndexInside input. let currDataIndexInside: number; - let currItemModel: Model; - let currItemStyleModels: Partial>> = {}; - let currLabelModels: Partial>> = {}; + let currItemModel: Model; + let currItemStyleModels: Partial>> = {}; + let currLabelModels: Partial>> = {}; - const seriesItemStyleModels = {} as Record>; + const seriesItemStyleModels = {} as Record>; - const seriesLabelModels = {} as Record>; + const seriesLabelModels = {} as Record>; for (let i = 0; i < STATES.length; i++) { const stateName = STATES[i]; - seriesItemStyleModels[stateName] = (customSeries as Model) + seriesItemStyleModels[stateName] = (customSeries as Model) .getModel(PATH_ITEM_STYLE[stateName]); - seriesLabelModels[stateName] = (customSeries as Model) + seriesLabelModels[stateName] = (customSeries as Model) .getModel(PATH_LABEL[stateName]); } - function getItemModel(dataIndexInside: number): Model { + function getItemModel(dataIndexInside: number): Model { return dataIndexInside === currDataIndexInside ? (currItemModel || (currItemModel = data.getItemModel(dataIndexInside))) : data.getItemModel(dataIndexInside); @@ -1148,7 +1149,7 @@ function createOrUpdateItem( api: ExtensionAPI, existsEl: Element, dataIndex: number, - elOption: CustomElementOption, + elOption: CustomRootElementOption, seriesModel: CustomSeriesModel, group: ViewRootGroup, data: SeriesData diff --git a/src/chart/effectScatter/EffectScatterSeries.ts b/src/chart/effectScatter/EffectScatterSeries.ts index 9632e400bf..19a468c5c1 100644 --- a/src/chart/effectScatter/EffectScatterSeries.ts +++ b/src/chart/effectScatter/EffectScatterSeries.ts @@ -32,7 +32,8 @@ import { SeriesLabelOption, StatesOptionMixin, SeriesEncodeOptionMixin, - CallbackDataParams + CallbackDataParams, + DefaultEmphasisFocus } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -41,14 +42,20 @@ import { BrushCommonSelectorsForSeries } from '../../component/brush/selector'; type ScatterDataValue = OptionDataValue | OptionDataValue[]; -export interface EffectScatterStateOption { - itemStyle?: ItemStyleOption +interface EffectScatterStatesOptionMixin { + emphasis?: { + focus?: DefaultEmphasisFocus + scale?: boolean + } +} +export interface EffectScatterStateOption { + itemStyle?: ItemStyleOption label?: SeriesLabelOption } export interface EffectScatterDataItemOption extends SymbolOptionMixin, EffectScatterStateOption, - StatesOptionMixin { + StatesOptionMixin { name?: string value?: ScatterDataValue @@ -56,7 +63,9 @@ export interface EffectScatterDataItemOption extends SymbolOptionMixin, rippleEffect?: SymbolDrawItemModelOption['rippleEffect'] } -export interface EffectScatterSeriesOption extends SeriesOption, EffectScatterStateOption, +export interface EffectScatterSeriesOption + extends SeriesOption, EffectScatterStatesOptionMixin>, + EffectScatterStateOption, SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin, SeriesOnCalendarOptionMixin, SeriesOnGeoOptionMixin, SeriesOnSingleOptionMixin, SymbolOptionMixin, SeriesEncodeOptionMixin { diff --git a/src/chart/funnel/FunnelSeries.ts b/src/chart/funnel/FunnelSeries.ts index 6abe848f0a..f102f793cb 100644 --- a/src/chart/funnel/FunnelSeries.ts +++ b/src/chart/funnel/FunnelSeries.ts @@ -36,7 +36,9 @@ import { LayoutOrient, VerticalAlign, SeriesLabelOption, - SeriesEncodeOptionMixin + SeriesEncodeOptionMixin, + DefaultStatesMixinEmpasis, + CallbackDataParams } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -46,14 +48,21 @@ type FunnelLabelOption = Omit & { | 'outer' | 'inner' | 'center' | 'rightTop' | 'rightBottom' | 'leftTop' | 'leftBottom' }; -export interface FunnelStateOption { - itemStyle?: ItemStyleOption +interface FunnelStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} + +export interface FunnelCallbackDataParams extends CallbackDataParams { + percent: number +} +export interface FunnelStateOption { + itemStyle?: ItemStyleOption label?: FunnelLabelOption labelLine?: LabelLineOption } export interface FunnelDataItemOption - extends FunnelStateOption, StatesOptionMixin, + extends FunnelStateOption, StatesOptionMixin, OptionDataItemObject { itemStyle?: ItemStyleOption & { @@ -62,7 +71,9 @@ export interface FunnelDataItemOption } } -export interface FunnelSeriesOption extends SeriesOption, FunnelStateOption, +export interface FunnelSeriesOption + extends SeriesOption, FunnelStatesMixin>, + FunnelStateOption, BoxLayoutOptionMixin, SeriesEncodeOptionMixin { type?: 'funnel' @@ -123,9 +134,9 @@ class FunnelSeriesModel extends SeriesModel { } // Overwrite - getDataParams(dataIndex: number) { + getDataParams(dataIndex: number): FunnelCallbackDataParams { const data = this.getData(); - const params = super.getDataParams(dataIndex); + const params = super.getDataParams(dataIndex) as FunnelCallbackDataParams; const valueDim = data.mapDimension('value'); const sum = data.getSum(valueDim); // Percent is 0 if sum is 0 diff --git a/src/chart/gauge/GaugeSeries.ts b/src/chart/gauge/GaugeSeries.ts index 729af9463d..c444a6e082 100644 --- a/src/chart/gauge/GaugeSeries.ts +++ b/src/chart/gauge/GaugeSeries.ts @@ -28,7 +28,9 @@ import { ItemStyleOption, OptionDataValueNumeric, StatesOptionMixin, - SeriesEncodeOptionMixin + SeriesEncodeOptionMixin, + DefaultStatesMixinEmpasis, + CallbackDataParams } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -102,11 +104,15 @@ interface DetailOption extends LabelOption { valueAnimation?: boolean } -export interface GaugeStateOption { - itemStyle?: ItemStyleOption +interface GaugeStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} +export interface GaugeStateOption { + itemStyle?: ItemStyleOption } -export interface GaugeDataItemOption extends GaugeStateOption, StatesOptionMixin { +export interface GaugeDataItemOption extends GaugeStateOption, + StatesOptionMixin, GaugeStatesMixin> { name?: string value?: OptionDataValueNumeric pointer?: PointerOption @@ -114,7 +120,8 @@ export interface GaugeDataItemOption extends GaugeStateOption, StatesOptionMixin title?: TitleOption detail?: DetailOption } -export interface GaugeSeriesOption extends SeriesOption, GaugeStateOption, +export interface GaugeSeriesOption extends SeriesOption, + GaugeStateOption, CircleLayoutOptionMixin, SeriesEncodeOptionMixin { type?: 'gauge' diff --git a/src/chart/graph/GraphSeries.ts b/src/chart/graph/GraphSeries.ts index 42b833d9c9..a3241c0951 100644 --- a/src/chart/graph/GraphSeries.ts +++ b/src/chart/graph/GraphSeries.ts @@ -62,8 +62,8 @@ interface GraphEdgeLineStyleOption extends LineStyleOption { curveness?: number } -export interface GraphNodeStateOption { - itemStyle?: ItemStyleOption +export interface GraphNodeStateOption { + itemStyle?: ItemStyleOption label?: SeriesLabelOption } @@ -71,16 +71,16 @@ export interface GraphNodeStateOption { interface ExtraEmphasisState { focus?: DefaultEmphasisFocus | 'adjacency' } -interface ExtraNodeStateOption { +interface GraphNodeStatesMixin { emphasis?: ExtraEmphasisState } -interface ExtraEdgeStateOption { +interface GraphEdgeStatesMixin { emphasis?: ExtraEmphasisState } export interface GraphNodeItemOption extends SymbolOptionMixin, GraphNodeStateOption, - GraphNodeStateOption, StatesOptionMixin { + GraphNodeStateOption, StatesOptionMixin { id?: string name?: string @@ -114,7 +114,7 @@ export interface GraphEdgeStateOption { } export interface GraphEdgeItemOption extends GraphEdgeStateOption, - StatesOptionMixin, + StatesOptionMixin, GraphEdgeItemObject { value?: number @@ -130,13 +130,14 @@ export interface GraphEdgeItemOption extends } export interface GraphCategoryItemOption extends SymbolOptionMixin, - GraphNodeStateOption, StatesOptionMixin { + GraphNodeStateOption, StatesOptionMixin { name?: string value?: OptionDataValue } -export interface GraphSeriesOption extends SeriesOption, +export interface GraphSeriesOption + extends SeriesOption, GraphNodeStatesMixin>, SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin, SeriesOnCalendarOptionMixin, SeriesOnGeoOptionMixin, SeriesOnSingleOptionMixin, SymbolOptionMixin, @@ -177,7 +178,7 @@ export interface GraphSeriesOption extends SeriesOption, edgeLabel?: SeriesLineLabelOption label?: SeriesLabelOption - itemStyle?: ItemStyleOption + itemStyle?: ItemStyleOption lineStyle?: GraphEdgeLineStyleOption emphasis?: { diff --git a/src/chart/heatmap/HeatmapSeries.ts b/src/chart/heatmap/HeatmapSeries.ts index 80fbb72dd4..7fcd89f918 100644 --- a/src/chart/heatmap/HeatmapSeries.ts +++ b/src/chart/heatmap/HeatmapSeries.ts @@ -29,7 +29,9 @@ import { OptionDataValue, StatesOptionMixin, SeriesEncodeOptionMixin, - SeriesOnCalendarOptionMixin + SeriesOnCalendarOptionMixin, + DefaultStatesMixinEmpasis, + CallbackDataParams } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -39,18 +41,28 @@ import type Calendar from '../../coord/calendar/Calendar'; type HeatmapDataValue = OptionDataValue[]; -export interface HeatmapStateOption { +export interface HeatmapStateOption { // Available on cartesian2d coordinate system - itemStyle?: ItemStyleOption + itemStyle?: ItemStyleOption label?: SeriesLabelOption } -export interface HeatmapDataItemOption extends HeatmapStateOption, StatesOptionMixin { +interface FunnelStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} +export interface HeatmapDataItemOption extends HeatmapStateOption, + StatesOptionMixin { value: HeatmapDataValue } -export interface HeatmapSeriesOption extends SeriesOption, HeatmapStateOption, - SeriesOnCartesianOptionMixin, SeriesOnGeoOptionMixin, SeriesOnCalendarOptionMixin, SeriesEncodeOptionMixin { +export interface HeatmapSeriesOption + extends SeriesOption, FunnelStatesMixin>, + HeatmapStateOption, + SeriesOnCartesianOptionMixin, + SeriesOnGeoOptionMixin, + SeriesOnCalendarOptionMixin, + SeriesEncodeOptionMixin { + type?: 'heatmap' coordinateSystem?: 'cartesian2d' | 'geo' | 'calendar' @@ -64,6 +76,8 @@ export interface HeatmapSeriesOption extends SeriesOption, H data?: (HeatmapDataItemOption | HeatmapDataValue)[] } + + class HeatmapSeriesModel extends SeriesModel { static readonly type = 'series.heatmap'; readonly type = HeatmapSeriesModel.type; diff --git a/src/chart/helper/LineDraw.ts b/src/chart/helper/LineDraw.ts index 60317bc7f1..5f5ff61f37 100644 --- a/src/chart/helper/LineDraw.ts +++ b/src/chart/helper/LineDraw.ts @@ -29,7 +29,8 @@ import { ZRStyleProps, StatesOptionMixin, DisplayState, - LabelOption + LabelOption, + StatesMixinBase } from '../../util/types'; import Displayable from 'zrender/src/graphic/Displayable'; import Model from '../../model/Model'; @@ -50,7 +51,8 @@ interface LineDrawStateOption { label?: LineLabelOption } -export interface LineDrawModelOption extends LineDrawStateOption, StatesOptionMixin { +export interface LineDrawModelOption extends LineDrawStateOption, + StatesOptionMixin { // If has effect effect?: { show?: boolean diff --git a/src/chart/line/LineSeries.ts b/src/chart/line/LineSeries.ts index a836132e4d..1b572b5a20 100644 --- a/src/chart/line/LineSeries.ts +++ b/src/chart/line/LineSeries.ts @@ -45,21 +45,21 @@ import {LegendIconParams} from '../../component/legend/LegendModel'; type LineDataValue = OptionDataValue | OptionDataValue[]; -interface ExtraStateOption { +interface LineStateOptionMixin { emphasis?: { focus?: DefaultEmphasisFocus scale?: boolean } } -export interface LineStateOption { - itemStyle?: ItemStyleOption +export interface LineStateOption { + itemStyle?: ItemStyleOption label?: SeriesLabelOption endLabel?: LineEndLabelOption } export interface LineDataItemOption extends SymbolOptionMixin, - LineStateOption, StatesOptionMixin { + LineStateOption, StatesOptionMixin { name?: string value?: LineDataValue @@ -70,7 +70,7 @@ export interface LineEndLabelOption extends SeriesLabelOption { } -export interface LineSeriesOption extends SeriesOption, LineStateOptionMixin & { emphasis?: { lineStyle?: LineStyleOption | { width?: 'bolder' @@ -81,7 +81,7 @@ export interface LineSeriesOption extends SeriesOption, LineStateOption, +}>, LineStateOption, SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin, SeriesStackOptionMixin, @@ -115,7 +115,7 @@ export interface LineSeriesOption extends SeriesOption; type Cartesian2DArea = ReturnType; @@ -191,9 +192,56 @@ function turnPointsIntoStep( return stepPoints; } +/** + * Clip color stops to edge. Avoid creating too large gradients. + * Which may lead to blurry when GPU acceleration is enabled. See #15680 + * + * The stops has been sorted from small to large. + */ +function clipColorStops(colorStops: ColorStop[], maxSize: number): ColorStop[] { + const newColorStops: ColorStop[] = []; + const len = colorStops.length; + // coord will always < 0 in prevOutOfRangeColorStop. + let prevOutOfRangeColorStop: ColorStop; + let prevInRangeColorStop: ColorStop; + + function lerpStop(stop0: ColorStop, stop1: ColorStop, clippedCoord: number) { + const coord0 = stop0.coord; + const p = (clippedCoord - coord0) / (stop1.coord - coord0); + const color = lerp(p, [stop0.color, stop1.color]) as string; + return { coord: clippedCoord, color } as ColorStop; + } + + for (let i = 0; i < len; i++) { + const stop = colorStops[i]; + const coord = stop.coord; + if (coord < 0) { + prevOutOfRangeColorStop = stop; + } + else if (coord > maxSize) { + if (prevInRangeColorStop) { + newColorStops.push(lerpStop(prevInRangeColorStop, stop, maxSize)); + } + // All following stop will be out of range. So just ignore them. + break; + } + else { + if (prevOutOfRangeColorStop) { + newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop, 0)); + // Reset + prevOutOfRangeColorStop = null; + } + newColorStops.push(stop); + prevInRangeColorStop = stop; + } + } + return newColorStops; +} + function getVisualGradient( data: SeriesData, - coordSys: Cartesian2D | Polar + coordSys: Cartesian2D | Polar, + api: ExtensionAPI ) { const visualMetaList = data.getVisual('visualMeta'); if (!visualMetaList || !visualMetaList.length || !data.count()) { @@ -236,19 +284,14 @@ function getVisualGradient( // LinearGradient to render `outerColors`. const axis = coordSys.getAxis(coordDim); - const axisScaleExtent = axis.scale.getExtent(); // dataToCoord mapping may not be linear, but must be monotonic. const colorStops: ColorStop[] = zrUtil.map(visualMeta.stops, function (stop) { - let coord = axis.toGlobalCoord(axis.dataToCoord(stop.value)); - // normalize the infinite value - isNaN(coord) || isFinite(coord) - || (coord = axis.toGlobalCoord(axis.dataToCoord(axisScaleExtent[+(coord < 0)]))); + // offset will be calculated later. return { - offset: 0, - coord, + coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), color: stop.color - }; + } as ColorStop; }); const stopLen = colorStops.length; const outerColors = visualMeta.outerColors.slice(); @@ -257,34 +300,40 @@ function getVisualGradient( colorStops.reverse(); outerColors.reverse(); } + const colorStopsInRange = clipColorStops( + colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight() + ); + const inRangeStopLen = colorStopsInRange.length; + if (!inRangeStopLen && stopLen) { + // All stops are out of range. All will be the same color. + return colorStops[0].coord < 0 + ? (outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color) + : (outerColors[0] ? outerColors[0] : colorStops[0].color); + } - const tinyExtent = 10; // Arbitrary value: 10px - const minCoord = colorStops[0].coord - tinyExtent; - const maxCoord = colorStops[stopLen - 1].coord + tinyExtent; + const tinyExtent = 0; // Arbitrary value: 10px + const minCoord = colorStopsInRange[0].coord - tinyExtent; + const maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent; const coordSpan = maxCoord - minCoord; if (coordSpan < 1e-3) { return 'transparent'; } - zrUtil.each(colorStops, function (stop) { + zrUtil.each(colorStopsInRange, function (stop) { stop.offset = (stop.coord - minCoord) / coordSpan; }); - colorStops.push({ - offset: stopLen ? colorStops[stopLen - 1].offset : 0.5, + colorStopsInRange.push({ + // NOTE: inRangeStopLen may still be 0 if stoplen is zero. + offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5, color: outerColors[1] || 'transparent' }); - colorStops.unshift({ // notice colorStops.length have been changed. - offset: stopLen ? colorStops[0].offset : 0.5, + colorStopsInRange.unshift({ // notice newColorStops.length have been changed. + offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5, color: outerColors[0] || 'transparent' }); - // zrUtil.each(colorStops, function (colorStop) { - // // Make sure each offset has rounded px to avoid not sharp edge - // colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start); - // }); - - const gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStops, true); + const gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStopsInRange, true); gradient[coordDim] = minCoord; gradient[coordDim + '2' as 'x2' | 'y2'] = maxCoord; @@ -626,7 +675,7 @@ class LineView extends ChartView { } } this._clipShapeForSymbol = clipShapeForSymbol; - const visualColor = getVisualGradient(data, coordSys) + const visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed if ( @@ -691,9 +740,18 @@ class LineView extends ChartView { } // Update clipPath - lineGroup.setClipPath( - createLineClipPath(this, coordSys, false, seriesModel) - ); + const oldClipPath = lineGroup.getClipPath(); + if (oldClipPath) { + const newClipPath = createLineClipPath(this, coordSys, false, seriesModel); + graphic.initProps(oldClipPath, { + shape: newClipPath.shape + }, seriesModel); + } + else { + lineGroup.setClipPath( + createLineClipPath(this, coordSys, true, seriesModel) + ); + } // Always update, or it is wrong in the case turning on legend // because points are not changed @@ -1232,17 +1290,18 @@ class LineView extends ChartView { next = turnPointsIntoStep(diff.next, coordSys, step); stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step); } - // Don't apply animation if diff is large. // For better result and avoid memory explosion problems like // https://github.com/apache/incubator-echarts/issues/12229 if (getBoundingDiff(current, next) > 3000 || (polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) ) { + polyline.stopAnimation(); polyline.setShape({ points: next }); if (polygon) { + polygon.stopAnimation(); polygon.setShape({ points: next, stackedOnPoints: stackedOnNext @@ -1287,7 +1346,6 @@ class LineView extends ChartView { } } - const updatedDataInfo: { el: SymbolExtended, ptIdx: number @@ -1306,7 +1364,6 @@ class LineView extends ChartView { } } } - if (polyline.animators && polyline.animators.length) { polyline.animators[0].during(function () { polygon && polygon.dirtyShape(); diff --git a/src/chart/lines/LinesSeries.ts b/src/chart/lines/LinesSeries.ts index 65355e062f..7598626b65 100644 --- a/src/chart/lines/LinesSeries.ts +++ b/src/chart/lines/LinesSeries.ts @@ -33,7 +33,11 @@ import { LineStyleOption, OptionDataValue, StatesOptionMixin, - SeriesLineLabelOption + SeriesLineLabelOption, + DimensionDefinitionLoose, + DefaultStatesMixinEmpasis, + ZRColor, + CallbackDataParams } from '../../util/types'; import GlobalModel from '../../model/Global'; import type { LineDrawModelOption } from '../helper/LineDraw'; @@ -71,7 +75,7 @@ type LinesCoords = number[][]; type LinesValue = OptionDataValue | OptionDataValue[]; -interface LinesLineStyleOption extends LineStyleOption { +interface LinesLineStyleOption extends LineStyleOption { curveness?: number } @@ -81,12 +85,16 @@ interface LegacyDataItemOption { name: string } -export interface LinesStateOption { - lineStyle?: LinesLineStyleOption +interface LinesStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} +export interface LinesStateOption { + lineStyle?: LinesLineStyleOption<(TCbParams extends never ? never : (params: TCbParams) => ZRColor) | ZRColor> label?: SeriesLineLabelOption } -export interface LinesDataItemOption extends LinesStateOption, StatesOptionMixin { +export interface LinesDataItemOption extends LinesStateOption, + StatesOptionMixin, LinesStatesMixin> { name?: string fromName?: string @@ -98,10 +106,12 @@ export interface LinesDataItemOption extends LinesStateOption, StatesOptionMixin coords?: LinesCoords value?: LinesValue -} -export interface LinesSeriesOption extends SeriesOption, LinesStateOption, + effect?: LineDrawModelOption['effect'] +} +export interface LinesSeriesOption + extends SeriesOption, LinesStateOption, SeriesOnCartesianOptionMixin, SeriesOnGeoOptionMixin, SeriesOnPolarOptionMixin, SeriesOnCalendarOptionMixin, SeriesLargeOptionMixin { @@ -129,6 +139,8 @@ export interface LinesSeriesOption extends SeriesOption, Lines // Stored as a flat array. In format // Points Count(2) | x | y | x | y | Points Count(3) | x | y | x | y | x | y | | ArrayLike + + dimensions?: DimensionDefinitionLoose | DimensionDefinitionLoose[] } class LinesSeriesModel extends SeriesModel { diff --git a/src/chart/map/MapSeries.ts b/src/chart/map/MapSeries.ts index 2081886e31..4aab23a2f7 100644 --- a/src/chart/map/MapSeries.ts +++ b/src/chart/map/MapSeries.ts @@ -32,7 +32,9 @@ import { ParsedValue, SeriesOnGeoOptionMixin, StatesOptionMixin, - SeriesLabelOption + SeriesLabelOption, + StatesMixinBase, + CallbackDataParams } from '../../util/types'; import { Dictionary } from 'zrender/src/core/types'; import GeoModel, { GeoCommonOptionMixin, GeoItemStyleOption } from '../../coord/geo/GeoModel'; @@ -44,11 +46,12 @@ import {createSymbol, ECSymbol} from '../../util/symbol'; import {LegendIconParams} from '../../component/legend/LegendModel'; import {Group} from '../../util/graphic'; -export interface MapStateOption { - itemStyle?: GeoItemStyleOption +export interface MapStateOption { + itemStyle?: GeoItemStyleOption label?: SeriesLabelOption } -export interface MapDataItemOption extends MapStateOption, StatesOptionMixin, +export interface MapDataItemOption extends MapStateOption, + StatesOptionMixin, OptionDataItemObject { cursor?: string } @@ -56,8 +59,8 @@ export interface MapDataItemOption extends MapStateOption, StatesOptionMixin, MapStateOption, - + SeriesOption, StatesMixinBase>, + MapStateOption, GeoCommonOptionMixin, // If `geoIndex` is not specified, a exclusive geo will be // created. Otherwise use the specified geo component, and diff --git a/src/chart/parallel/ParallelSeries.ts b/src/chart/parallel/ParallelSeries.ts index c75ea4e8fd..0b727eef0a 100644 --- a/src/chart/parallel/ParallelSeries.ts +++ b/src/chart/parallel/ParallelSeries.ts @@ -32,7 +32,10 @@ import { StatesOptionMixin, OptionEncodeValue, Dictionary, - OptionEncode + OptionEncode, + DefaultStatesMixinEmpasis, + ZRColor, + CallbackDataParams } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -42,17 +45,21 @@ import ParallelModel from '../../coord/parallel/ParallelModel'; type ParallelSeriesDataValue = OptionDataValue[]; -export interface ParallelStateOption { - lineStyle?: LineStyleOption +interface ParallelStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} +export interface ParallelStateOption { + lineStyle?: LineStyleOption<(TCbParams extends never ? never : (params: TCbParams) => ZRColor) | ZRColor> label?: SeriesLabelOption } -export interface ParallelSeriesDataItemOption extends ParallelStateOption, StatesOptionMixin { +export interface ParallelSeriesDataItemOption extends ParallelStateOption, + StatesOptionMixin { value?: ParallelSeriesDataValue[] } - export interface ParallelSeriesOption extends - SeriesOption, ParallelStateOption, + SeriesOption, ParallelStatesMixin>, + ParallelStateOption, SeriesEncodeOptionMixin { type?: 'parallel'; @@ -70,14 +77,11 @@ export interface ParallelSeriesOption extends parallelAxisDefault?: ParallelAxisOption; - emphasis?: { - label?: SeriesLabelOption; - lineStyle?: LineStyleOption; - } data?: (ParallelSeriesDataValue | ParallelSeriesDataItemOption)[] } + class ParallelSeriesModel extends SeriesModel { static type = 'series.parallel'; diff --git a/src/chart/parallel/ParallelView.ts b/src/chart/parallel/ParallelView.ts index 1704b09c90..f3b478c401 100644 --- a/src/chart/parallel/ParallelView.ts +++ b/src/chart/parallel/ParallelView.ts @@ -172,7 +172,9 @@ function createLinePoints(data: SeriesData, dataIndex: number, dimensions: strin return points; } -function addEl(data: SeriesData, dataGroup: graphic.Group, dataIndex: number, dimensions: string[], coordSys: Parallel) { +function addEl( + data: SeriesData, dataGroup: graphic.Group, dataIndex: number, dimensions: string[], coordSys: Parallel +) { const points = createLinePoints(data, dataIndex, dimensions, coordSys); const line = new graphic.Polyline({ shape: {points: points}, diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts index b68726285e..efa5bda315 100644 --- a/src/chart/pie/PieSeries.ts +++ b/src/chart/pie/PieSeries.ts @@ -40,7 +40,7 @@ import { } from '../../util/types'; import SeriesData from '../../data/SeriesData'; -interface PieItemStyleOption extends ItemStyleOption { +interface PieItemStyleOption extends ItemStyleOption { // can be 10 // which means that both innerCornerRadius and outerCornerRadius are 10 // can also be an array [20, 10] @@ -52,9 +52,13 @@ interface PieItemStyleOption extends ItemStyleOption { borderRadius?: (number | string)[] | number | string } -export interface PieStateOption { +export interface PieCallbackDataParams extends CallbackDataParams { + percent: number +} + +export interface PieStateOption { // TODO: TYPE Color Callback - itemStyle?: PieItemStyleOption + itemStyle?: PieItemStyleOption label?: PieLabelOption labelLine?: PieLabelLineOption } @@ -91,11 +95,11 @@ interface ExtraStateOption { export interface PieDataItemOption extends OptionDataItemObject, PieStateOption, StatesOptionMixin { - cursor?: string } export interface PieSeriesOption extends - Omit, 'labelLine'>, PieStateOption, + Omit, ExtraStateOption>, 'labelLine'>, + PieStateOption, CircleLayoutOptionMixin, BoxLayoutOptionMixin, SeriesEncodeOptionMixin { @@ -164,9 +168,9 @@ class PieSeriesModel extends SeriesModel { /** * @overwrite */ - getDataParams(dataIndex: number): CallbackDataParams { + getDataParams(dataIndex: number): PieCallbackDataParams { const data = this.getData(); - const params = super.getDataParams(dataIndex); + const params = super.getDataParams(dataIndex) as PieCallbackDataParams; // FIXME toFixed? const valueList: number[] = []; diff --git a/src/chart/radar/RadarSeries.ts b/src/chart/radar/RadarSeries.ts index ffc8ea47d1..c6f9bc5f62 100644 --- a/src/chart/radar/RadarSeries.ts +++ b/src/chart/radar/RadarSeries.ts @@ -32,7 +32,8 @@ import { StatesOptionMixin, OptionDataItemObject, SeriesEncodeOptionMixin, - CallbackDataParams + CallbackDataParams, + DefaultStatesMixinEmpasis } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -43,18 +44,24 @@ import { type RadarSeriesDataValue = OptionDataValue[]; -export interface RadarSeriesStateOption { +interface RadarStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} +export interface RadarSeriesStateOption { lineStyle?: LineStyleOption areaStyle?: AreaStyleOption label?: SeriesLabelOption - itemStyle?: ItemStyleOption + itemStyle?: ItemStyleOption } export interface RadarSeriesDataItemOption extends SymbolOptionMixin, - RadarSeriesStateOption, StatesOptionMixin, + RadarSeriesStateOption, + StatesOptionMixin, RadarStatesMixin>, OptionDataItemObject { } -export interface RadarSeriesOption extends SeriesOption, RadarSeriesStateOption, +export interface RadarSeriesOption + extends SeriesOption, + RadarSeriesStateOption, SymbolOptionMixin, SeriesEncodeOptionMixin { type?: 'radar' coordinateSystem?: 'radar' diff --git a/src/chart/sankey/SankeySeries.ts b/src/chart/sankey/SankeySeries.ts index 6131f56e1a..0479035203 100644 --- a/src/chart/sankey/SankeySeries.ts +++ b/src/chart/sankey/SankeySeries.ts @@ -33,7 +33,8 @@ import { OptionDataItemObject, GraphEdgeItemObject, OptionDataValueNumeric, - DefaultEmphasisFocus + DefaultEmphasisFocus, + CallbackDataParams } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; @@ -43,17 +44,16 @@ import { createTooltipMarkup } from '../../component/tooltip/tooltipMarkup'; type FocusNodeAdjacency = boolean | 'inEdges' | 'outEdges' | 'allEdges'; -export interface SankeyNodeStateOption { +export interface SankeyNodeStateOption { label?: SeriesLabelOption - itemStyle?: ItemStyleOption + itemStyle?: ItemStyleOption } export interface SankeyEdgeStateOption { lineStyle?: SankeyEdgeStyleOption } -interface SankeyBothStateOption extends SankeyNodeStateOption, SankeyEdgeStateOption { -} +interface SankeyBothStateOption extends SankeyNodeStateOption, SankeyEdgeStateOption {} interface SankeyEdgeStyleOption extends LineStyleOption { curveness?: number @@ -92,7 +92,8 @@ export interface SankeyLevelOption extends SankeyNodeStateOption, SankeyEdgeStat } export interface SankeySeriesOption - extends SeriesOption, SankeyBothStateOption, + extends SeriesOption, ExtraStateOption>, + SankeyBothStateOption, BoxLayoutOptionMixin { type?: 'sankey' diff --git a/src/chart/scatter/ScatterSeries.ts b/src/chart/scatter/ScatterSeries.ts index 40c4c73256..f79f42281e 100644 --- a/src/chart/scatter/ScatterSeries.ts +++ b/src/chart/scatter/ScatterSeries.ts @@ -42,12 +42,12 @@ import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; import { BrushCommonSelectorsForSeries } from '../../component/brush/selector'; -interface ScatterStateOption { - itemStyle?: ItemStyleOption +interface ScatterStateOption { + itemStyle?: ItemStyleOption label?: SeriesLabelOption } -interface ExtraStateOption { +interface ScatterStatesOptionMixin { emphasis?: { focus?: DefaultEmphasisFocus scale?: boolean @@ -55,11 +55,13 @@ interface ExtraStateOption { } export interface ScatterDataItemOption extends SymbolOptionMixin, - ScatterStateOption, StatesOptionMixin, + ScatterStateOption, StatesOptionMixin, OptionDataItemObject { } -export interface ScatterSeriesOption extends SeriesOption, ScatterStateOption, +export interface ScatterSeriesOption + extends SeriesOption, ScatterStatesOptionMixin>, + ScatterStateOption, SeriesOnCartesianOptionMixin, SeriesOnPolarOptionMixin, SeriesOnCalendarOptionMixin, SeriesOnGeoOptionMixin, SeriesOnSingleOptionMixin, SeriesLargeOptionMixin, SeriesStackOptionMixin, diff --git a/src/chart/sunburst/SunburstSeries.ts b/src/chart/sunburst/SunburstSeries.ts index f53b7c3150..344cbc6e4d 100644 --- a/src/chart/sunburst/SunburstSeries.ts +++ b/src/chart/sunburst/SunburstSeries.ts @@ -38,7 +38,7 @@ import SeriesData from '../../data/SeriesData'; import Model from '../../model/Model'; import enableAriaDecalForTree from '../helper/enableAriaDecalForTree'; -interface SunburstItemStyleOption extends ItemStyleOption { +interface SunburstItemStyleOption extends ItemStyleOption { // can be 10 // which means that both innerCornerRadius and outerCornerRadius are 10 // can also be an array [20, 10] @@ -65,19 +65,20 @@ interface SunburstDataParams extends CallbackDataParams { }[] } -interface ExtraStateOption { +interface SunburstStatesMixin { emphasis?: { focus?: DefaultEmphasisFocus | 'descendant' | 'ancestor' } } -export interface SunburstStateOption { - itemStyle?: SunburstItemStyleOption +export interface SunburstStateOption { + itemStyle?: SunburstItemStyleOption label?: SunburstLabelOption } export interface SunburstSeriesNodeItemOption extends - SunburstStateOption, StatesOptionMixin, + SunburstStateOption, + StatesOptionMixin, SunburstStatesMixin>, OptionDataItemObject { nodeClick?: 'rootToNode' | 'link' @@ -91,7 +92,19 @@ export interface SunburstSeriesNodeItemOption extends cursor?: string } -export interface SunburstSeriesLevelOption extends SunburstStateOption, StatesOptionMixin { +export interface SunburstSeriesLevelOption + extends SunburstStateOption, StatesOptionMixin { + + radius?: (number | string)[] + /** + * @deprecated use radius instead + */ + r?: number | string + /** + * @deprecated use radius instead + */ + r0?: number | string + highlight?: { itemStyle?: SunburstItemStyleOption label?: SunburstLabelOption @@ -105,7 +118,7 @@ interface SortParam { getValue(): number } export interface SunburstSeriesOption extends - SeriesOption, SunburstStateOption, + SeriesOption, SunburstStateOption, SunburstColorByMixin, CircleLayoutOptionMixin { @@ -150,6 +163,7 @@ class SunburstSeriesModel extends SeriesModel { ignoreStyleOnData = true; private _viewRoot: TreeNode; + private _levelModels: Model[]; getInitialData(option: SunburstSeriesOption, ecModel: GlobalModel) { // Create a virtual root. @@ -157,9 +171,10 @@ class SunburstSeriesModel extends SeriesModel { completeTreeValue(root); - const levelModels = zrUtil.map(option.levels || [], function (levelDefine) { - return new Model(levelDefine, this, ecModel); - }, this); + const levelModels = this._levelModels + = zrUtil.map(option.levels || [], function (levelDefine) { + return new Model(levelDefine, this, ecModel); + }, this); // Make sure always a new tree is created when setOption, // in TreemapView, we check whether oldTree === newTree @@ -193,6 +208,10 @@ class SunburstSeriesModel extends SeriesModel { return params; } + getLevelModel(node: TreeNode) { + return this._levelModels && this._levelModels[node.depth]; + } + static defaultOption: SunburstSeriesOption = { zlevel: 0, z: 2, diff --git a/src/chart/sunburst/sunburstLayout.ts b/src/chart/sunburst/sunburstLayout.ts index b2a15e86c5..5578eadc9d 100644 --- a/src/chart/sunburst/sunburstLayout.ts +++ b/src/chart/sunburst/sunburstLayout.ts @@ -23,6 +23,7 @@ import GlobalModel from '../../model/Global'; import ExtensionAPI from '../../core/ExtensionAPI'; import SunburstSeriesModel, { SunburstSeriesNodeItemOption, SunburstSeriesOption } from './SunburstSeries'; import { TreeNode } from '../../data/Tree'; +import SeriesModel from '../../model/Series'; // let PI2 = Math.PI * 2; const RADIAN = Math.PI / 180; @@ -119,16 +120,19 @@ export default function sunburstLayout( let rStart = r0 + rPerLevel * depth; let rEnd = r0 + rPerLevel * (depth + 1); - const itemModel = node.getModel(); - // @ts-ignore. TODO this is not provided to developer yet. Rename it. - if (itemModel.get('r0') != null) { - // @ts-ignore - rStart = parsePercent(itemModel.get('r0'), size / 2); - } - // @ts-ignore - if (itemModel.get('r') != null) { - // @ts-ignore - rEnd = parsePercent(itemModel.get('r'), size / 2); + const levelModel = seriesModel.getLevelModel(node); + if (levelModel) { + let r0 = levelModel.get('r0', true); + let r = levelModel.get('r', true); + let radius = levelModel.get('radius', true); + + if (radius != null) { + r0 = radius[0]; + r = radius[1]; + } + + (r0 != null) && (rStart = parsePercent(r0, size / 2)); + (r != null) && (rEnd = parsePercent(r, size / 2)); } node.setLayout({ diff --git a/src/chart/themeRiver/ThemeRiverSeries.ts b/src/chart/themeRiver/ThemeRiverSeries.ts index 4cd6c57fa2..2e05a9a826 100644 --- a/src/chart/themeRiver/ThemeRiverSeries.ts +++ b/src/chart/themeRiver/ThemeRiverSeries.ts @@ -33,7 +33,9 @@ import { BoxLayoutOptionMixin, ZRColor, Dictionary, - SeriesLabelOption + SeriesLabelOption, + CallbackDataParams, + DefaultStatesMixinEmpasis } from '../../util/types'; import SingleAxis from '../../coord/single/SingleAxis'; import GlobalModel from '../../model/Global'; @@ -48,12 +50,17 @@ interface ThemeRiverSeriesLabelOption extends SeriesLabelOption { type ThemerRiverDataItem = [OptionDataValueDate, OptionDataValueNumeric, string]; -export interface ThemeRiverStateOption { +interface ThemeRiverStatesMixin { + emphasis?: DefaultStatesMixinEmpasis +} +export interface ThemeRiverStateOption { label?: ThemeRiverSeriesLabelOption - itemStyle?: ItemStyleOption + itemStyle?: ItemStyleOption } -export interface ThemeRiverSeriesOption extends SeriesOption, ThemeRiverStateOption, +export interface ThemeRiverSeriesOption + extends SeriesOption, ThemeRiverStatesMixin>, + ThemeRiverStateOption, SeriesOnSingleOptionMixin, BoxLayoutOptionMixin { type?: 'themeRiver' diff --git a/src/chart/tree/TreeSeries.ts b/src/chart/tree/TreeSeries.ts index 118ffb2fad..5d7b8f5ef4 100644 --- a/src/chart/tree/TreeSeries.ts +++ b/src/chart/tree/TreeSeries.ts @@ -44,8 +44,8 @@ interface CurveLineStyleOption extends LineStyleOption{ curveness?: number } -export interface TreeSeriesStateOption { - itemStyle?: ItemStyleOption +export interface TreeSeriesStateOption { + itemStyle?: ItemStyleOption /** * Line style of the edge between node and it's parent. */ @@ -53,7 +53,7 @@ export interface TreeSeriesStateOption { label?: SeriesLabelOption } -interface ExtraStateOption { +interface TreeStatesMixin { emphasis?: { focus?: DefaultEmphasisFocus | 'ancestor' | 'descendant' scale?: boolean @@ -61,7 +61,8 @@ interface ExtraStateOption { } export interface TreeSeriesNodeItemOption extends SymbolOptionMixin, - TreeSeriesStateOption, StatesOptionMixin, + TreeSeriesStateOption, + StatesOptionMixin, TreeStatesMixin>, OptionDataItemObject { children?: TreeSeriesNodeItemOption[] @@ -75,12 +76,12 @@ export interface TreeSeriesNodeItemOption extends SymbolOptionMixin { - +export interface TreeSeriesLeavesOption + extends TreeSeriesStateOption, StatesOptionMixin { } export interface TreeSeriesOption extends - SeriesOption, TreeSeriesStateOption, + SeriesOption, TreeSeriesStateOption, SymbolOptionMixin, BoxLayoutOptionMixin, RoamOptionMixin { type?: 'tree' diff --git a/src/chart/treemap/TreemapSeries.ts b/src/chart/treemap/TreemapSeries.ts index 287540e9c4..043018c671 100644 --- a/src/chart/treemap/TreemapSeries.ts +++ b/src/chart/treemap/TreemapSeries.ts @@ -36,8 +36,7 @@ import { DecalObject, SeriesLabelOption, DefaultEmphasisFocus, - AriaOptionMixin, - ColorBy + AriaOptionMixin } from '../../util/types'; import GlobalModel from '../../model/Global'; import { LayoutRect } from '../../util/layout'; @@ -59,7 +58,7 @@ interface TreemapSeriesLabelOption extends SeriesLabelOption { formatter?: string | ((params: CallbackDataParams) => string) } -interface TreemapSeriesItemStyleOption extends ItemStyleOption { +interface TreemapSeriesItemStyleOption extends ItemStyleOption { borderRadius?: number | number[] colorAlpha?: number @@ -91,8 +90,8 @@ interface ExtraStateOption { } } -export interface TreemapStateOption { - itemStyle?: TreemapSeriesItemStyleOption +export interface TreemapStateOption { + itemStyle?: TreemapSeriesItemStyleOption label?: TreemapSeriesLabelOption upperLabel?: TreemapSeriesLabelOption } @@ -149,8 +148,8 @@ export interface TreemapSeriesNodeItemOption extends TreemapSeriesVisualOption, } export interface TreemapSeriesOption - extends SeriesOption, - TreemapStateOption, + extends SeriesOption, ExtraStateOption>, + TreemapStateOption, BoxLayoutOptionMixin, RoamOptionMixin, TreemapSeriesVisualOption { diff --git a/src/component/axis/AxisBuilder.ts b/src/component/axis/AxisBuilder.ts index c262931039..d06c0b5710 100644 --- a/src/component/axis/AxisBuilder.ts +++ b/src/component/axis/AxisBuilder.ts @@ -17,7 +17,7 @@ * under the License. */ -import {retrieve, defaults, extend, each, isObject} from 'zrender/src/core/util'; +import {retrieve, defaults, extend, each, isObject, map} from 'zrender/src/core/util'; import * as graphic from '../../util/graphic'; import {getECData} from '../../util/innerStore'; import {createTextStyle} from '../../label/labelStyle'; @@ -33,6 +33,7 @@ import { AxisBaseOption } from '../../coord/axisCommonTypes'; import Element from 'zrender/src/Element'; import { PathStyleProps } from 'zrender/src/graphic/Path'; import OrdinalScale from '../../scale/Ordinal'; +import { prepareLayoutList, hideOverlap } from '../../label/labelLayoutHelper'; const PI = Math.PI; @@ -347,6 +348,20 @@ const builders: Record<'axisLine' | 'axisTickLabel' | 'axisName', AxisElementsBu fixMinMaxLabelShow(axisModel, labelEls, ticksEls); buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); + + // This bit fixes the label overlap issue for the time chart. + // See https://github.com/apache/echarts/issues/14266 for more. + if (axisModel.get(['axisLabel', 'hideOverlap'])) { + const labelList = prepareLayoutList(map(labelEls, label => ({ + label, + priority: label.z2, + defaultAttr: { + ignore: label.ignore + } + }))); + + hideOverlap(labelList); + } }, axisName(opt, axisModel, group, transformGroup) { @@ -766,7 +781,7 @@ function buildAxisLabel( y: opt.labelOffset + opt.labelDirection * labelMargin, rotation: labelLayout.rotation, silent: silent, - z2: 10, + z2: 10 + (labelItem.level || 0), style: createTextStyle(itemLabelModel, { text: formattedLabel, align: itemLabelModel.getShallow('align', true) diff --git a/src/component/legend/LegendModel.ts b/src/component/legend/LegendModel.ts index 9026471423..855bcdd9ac 100644 --- a/src/component/legend/LegendModel.ts +++ b/src/component/legend/LegendModel.ts @@ -115,6 +115,11 @@ export interface LegendStyleOption { textStyle?: LabelOption symbolRotate?: number | 'inherit' + + /** + * @deprecated + */ + symbolKeepAspect?: boolean } interface DataItem extends LegendStyleOption { @@ -134,19 +139,20 @@ export interface LegendTooltipFormatterParams { } export interface LegendIconParams { - itemWidth: number, - itemHeight: number, + itemWidth: number + itemHeight: number /** * symbolType is from legend.icon, legend.data.icon, or series visual */ - icon: string, - iconRotate: number | 'inherit', - itemStyle: PathStyleProps, + icon: string + iconRotate: number | 'inherit' + symbolKeepAspect: boolean + itemStyle: PathStyleProps lineStyle: LineStyleProps } export interface LegendSymbolStyleOption { - itemStyle?: ItemStyleProps, + itemStyle?: ItemStyleProps lineStyle?: LineStyleProps } @@ -454,6 +460,7 @@ class LegendModel extends ComponentMode itemWidth: 25, itemHeight: 14, symbolRotate: 'inherit', + symbolKeepAspect: true, inactiveColor: '#ccc', inactiveBorderColor: '#ccc', @@ -462,11 +469,6 @@ class LegendModel extends ComponentMode itemStyle: { color: 'inherit', opacity: 'inherit', - decal: 'inherit', - shadowBlur: 0, - shadowColor: null, - shadowOffsetX: 0, - shadowOffsetY: 0, borderColor: 'inherit', borderWidth: 'auto', borderCap: 'inherit', @@ -485,11 +487,7 @@ class LegendModel extends ComponentMode cap: 'inherit', join: 'inherit', dashOffset: 'inherit', - miterLimit: 'inherit', - shadowBlur: 0, - shadowColor: null, - shadowOffsetX: 0, - shadowOffsetY: 0 + miterLimit: 'inherit' }, textStyle: { @@ -504,7 +502,7 @@ class LegendModel extends ComponentMode borderRadius: 10, padding: [3, 5, 3, 5], fontSize: 12, - fontFamily: ' sans-serif', + fontFamily: 'sans-serif', color: '#666', borderWidth: 1, borderColor: '#666' diff --git a/src/component/legend/LegendView.ts b/src/component/legend/LegendView.ts index 5e064fd5fe..f7ce4f5126 100644 --- a/src/component/legend/LegendView.ts +++ b/src/component/legend/LegendView.ts @@ -347,16 +347,15 @@ class LegendView extends ComponentView { const itemHeight = legendModel.get('itemHeight'); const isSelected = legendModel.isSelected(name); - let iconRotate = legendItemModel.get('symbolRotate'); + const iconRotate = legendItemModel.get('symbolRotate'); + const symbolKeepAspect = legendItemModel.get('symbolKeepAspect'); const legendIconType = legendItemModel.get('icon'); legendIcon = legendIconType || legendIcon || 'roundRect'; - const legendLineStyle = legendModel.getModel('lineStyle'); const style = getLegendStyle( legendIcon, legendItemModel, - legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, @@ -377,7 +376,8 @@ class LegendView extends ComponentView { icon: legendIcon, iconRotate: iconRotate, itemStyle: style.itemStyle, - lineStyle: style.lineStyle + lineStyle: style.lineStyle, + symbolKeepAspect })); } else { @@ -394,7 +394,8 @@ class LegendView extends ComponentView { icon: legendIcon, iconRotate: rotate, itemStyle: style.itemStyle, - lineStyle: style.lineStyle + lineStyle: style.lineStyle, + symbolKeepAspect })); } @@ -540,8 +541,7 @@ class LegendView extends ComponentView { function getLegendStyle( iconType: string, legendModel: LegendModel['_data'][number], - legendLineStyle: Model, - lineVisualStyle: LineStyleProps, + lineVisualStyle: PathStyleProps, itemVisualStyle: PathStyleProps, drawType: 'fill' | 'stroke', isSelected: boolean @@ -550,81 +550,49 @@ function getLegendStyle( * Use series style if is inherit; * elsewise, use legend style */ + function handleCommonProps(style: PathStyleProps, visualStyle: PathStyleProps) { + // If lineStyle.width is 'auto', it is set to be 2 if series has border + if ((style.lineWidth as any) === 'auto') { + style.lineWidth = (visualStyle.lineWidth > 0) ? 2 : 0; + } + + each(style, (propVal, propName) => { + style[propName] === 'inherit' && ((style as any)[propName] = visualStyle[propName]); + }); + } // itemStyle const legendItemModel = legendModel.getModel('itemStyle') as Model; - const itemProperties = ITEM_STYLE_KEY_MAP.concat([ - ['decal'] - ]); - const itemStyle: PathStyleProps = {}; - for (let i = 0; i < itemProperties.length; ++i) { - const propName = itemProperties[i][ - itemProperties[i].length - 1 - ] as keyof LegendItemStyleOption; - const visualName = itemProperties[i][0] as keyof PathStyleProps; - const value = legendItemModel.getShallow(propName) as LegendItemStyleOption[keyof LegendItemStyleOption]; - if (value === 'inherit') { - switch (visualName) { - case 'fill': - /** - * Series with visualDrawType as 'stroke' should have - * series stroke as legend fill - */ - itemStyle.fill = itemVisualStyle[drawType]; - break; - - case 'stroke': - /** - * icon type with "emptyXXX" should use fill color - * in visual style - */ - itemStyle.stroke = itemVisualStyle[ - iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke' - ]; - break; - - case 'opacity': - /** - * Use lineStyle.opacity if drawType is stroke - */ - itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity; - break; - - default: - (itemStyle as any)[visualName] = itemVisualStyle[visualName]; - } - } - else if (value === 'auto' && visualName === 'lineWidth') { - // If lineStyle.width is 'auto', it is set to be 2 if series has border - itemStyle.lineWidth = (itemVisualStyle.lineWidth > 0) ? 2 : 0; - } - else { - (itemStyle as any)[visualName] = value; - } + const itemStyle = legendItemModel.getItemStyle(); + const iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke'; + + itemStyle.decal = itemVisualStyle.decal; + if (itemStyle.fill === 'inherit') { + /** + * Series with visualDrawType as 'stroke' should have + * series stroke as legend fill + */ + itemStyle.fill = itemVisualStyle[drawType]; } + if (itemStyle.stroke === 'inherit') { + /** + * icon type with "emptyXXX" should use fill color + * in visual style + */ + itemStyle.stroke = itemVisualStyle[iconBrushType]; + } + if ((itemStyle.opacity as any) === 'inherit') { + /** + * Use lineStyle.opacity if drawType is stroke + */ + itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity; + } + handleCommonProps(itemStyle, itemVisualStyle); // lineStyle const legendLineModel = legendModel.getModel('lineStyle') as Model; - const lineProperties = LINE_STYLE_KEY_MAP.concat([ - ['inactiveColor'], - ['inactiveWidth'] - ]); - const lineStyle: LineStyleProps = {}; - for (let i = 0; i < lineProperties.length; ++i) { - const propName = lineProperties[i][1] as keyof LegendLineStyleOption; - const visualName = lineProperties[i][0] as keyof LineStyleProps; - const value = legendLineModel.getShallow(propName) as LegendLineStyleOption[keyof LegendLineStyleOption]; - if (value === 'inherit') { - (lineStyle as any)[visualName] = lineVisualStyle[visualName]; - } - else if (value === 'auto' && visualName === 'lineWidth') { - // If lineStyle.width is 'auto', it is set to be 2 if series has border - lineStyle.lineWidth = lineVisualStyle.lineWidth > 0 ? 2 : 0; - } - else { - (lineStyle as any)[visualName] = value; - } - } + const lineStyle: LineStyleProps = legendLineModel.getLineStyle(); + handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color (itemStyle.fill === 'auto') && (itemStyle.fill = itemVisualStyle.fill); @@ -638,14 +606,14 @@ function getLegendStyle( * there is no border in series but border in legend, so we need to * use border only when series has border if is set to be auto */ - const visualHasBorder = itemStyle[iconType.indexOf('empty') > -1 ? 'fill' : 'stroke']; + const visualHasBorder = itemStyle[iconBrushType]; itemStyle.lineWidth = borderWidth === 'auto' ? (itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0) : itemStyle.lineWidth; itemStyle.fill = legendModel.get('inactiveColor'); itemStyle.stroke = legendModel.get('inactiveBorderColor'); - lineStyle.stroke = legendLineStyle.get('inactiveColor'); - lineStyle.lineWidth = legendLineStyle.get('inactiveWidth'); + lineStyle.stroke = legendLineModel.get('inactiveColor'); + lineStyle.lineWidth = legendLineModel.get('inactiveWidth'); } return { itemStyle, lineStyle }; } @@ -658,7 +626,8 @@ function getDefaultLegendIcon(opt: LegendIconParams): ECSymbol { 0, opt.itemWidth, opt.itemHeight, - opt.itemStyle.fill + opt.itemStyle.fill, + opt.symbolKeepAspect ); icon.setStyle(opt.itemStyle); diff --git a/src/component/marker/MarkAreaModel.ts b/src/component/marker/MarkAreaModel.ts index 9136c66bda..ec2a651ffc 100644 --- a/src/component/marker/MarkAreaModel.ts +++ b/src/component/marker/MarkAreaModel.ts @@ -18,7 +18,7 @@ */ import MarkerModel, { MarkerOption, MarkerStatisticType, MarkerPositionOption } from './MarkerModel'; -import { SeriesLabelOption, ItemStyleOption, StatesOptionMixin } from '../../util/types'; +import { SeriesLabelOption, ItemStyleOption, StatesOptionMixin, StatesMixinBase } from '../../util/types'; import GlobalModel from '../../model/Global'; @@ -27,7 +27,8 @@ interface MarkAreaStateOption { label?: SeriesLabelOption } -interface MarkAreaDataItemOptionBase extends MarkAreaStateOption, StatesOptionMixin { +interface MarkAreaDataItemOptionBase extends MarkAreaStateOption, + StatesOptionMixin { name?: string } @@ -55,7 +56,8 @@ export type MarkArea2DDataItemOption = [ MarkArea2DDataItemDimOption ]; -export interface MarkAreaOption extends MarkerOption, MarkAreaStateOption, StatesOptionMixin { +export interface MarkAreaOption extends MarkerOption, MarkAreaStateOption, + StatesOptionMixin { mainType?: 'markArea' precision?: number diff --git a/src/component/marker/MarkAreaView.ts b/src/component/marker/MarkAreaView.ts index e23403cbfe..f9b762cf1e 100644 --- a/src/component/marker/MarkAreaView.ts +++ b/src/component/marker/MarkAreaView.ts @@ -27,7 +27,7 @@ import { enableHoverEmphasis, setStatesStylesFromModel } from '../../util/states import * as markerHelper from './markerHelper'; import MarkerView from './MarkerView'; import { retrieve, mergeAll, map, curry, filter, HashMap, extend } from 'zrender/src/core/util'; -import { ScaleDataValue, ParsedValue, ZRColor } from '../../util/types'; +import { ParsedValue, ScaleDataValue, ZRColor } from '../../util/types'; import { CoordinateSystem, isCoordinateSystemType } from '../../coord/CoordinateSystem'; import MarkAreaModel, { MarkArea2DDataItemOption } from './MarkAreaModel'; import SeriesModel from '../../model/Series'; @@ -41,6 +41,7 @@ import { getVisualFromData } from '../../visual/helper'; import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle'; import { getECData } from '../../util/innerStore'; import Axis2D from '../../coord/cartesian/Axis2D'; +import { parseDataValue } from '../../data/helper/dataValueHelper'; interface MarkAreaDrawGroup { group: graphic.Group @@ -362,11 +363,11 @@ function createList( maModel: MarkAreaModel ) { - let coordDimsInfos: SeriesDimensionDefine[]; let areaData: SeriesData; + let dataDims: SeriesDimensionDefine[]; const dims = ['x0', 'y0', 'x1', 'y1']; if (coordSys) { - coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + const coordDimsInfos: SeriesDimensionDefine[] = map(coordSys && coordSys.dimensions, function (coordDim) { const data = seriesModel.getData(); const info = data.getDimensionInfo( data.mapDimension(coordDim) @@ -378,19 +379,18 @@ function createList( ordinalMeta: null }); }); - areaData = new SeriesData(map(dims, function (dim, idx) { - return { - name: dim, - type: coordDimsInfos[idx % 2].type - }; - }), maModel); + dataDims = map(dims, (dim, idx) => ({ + name: dim, + type: coordDimsInfos[idx % 2].type + })); + areaData = new SeriesData(dataDims, maModel); } else { - coordDimsInfos = [{ + dataDims = [{ name: 'value', type: 'float' }]; - areaData = new SeriesData(coordDimsInfos, maModel); + areaData = new SeriesData(dataDims, maModel); } let optData = map(maModel.get('data'), curry( @@ -402,17 +402,15 @@ function createList( ); } - const dimValueGetter = coordSys ? function ( - item: MarkAreaMergedItemOption, - dimName: string, - dataIndex: number, - dimIndex: number - ) { - // TODO should convert to ParsedValue? - return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2] as ParsedValue; - } : function (item: MarkAreaMergedItemOption) { - return item.value; - }; + const dimValueGetter: markerHelper.MarkerDimValueGetter = coordSys + ? function (item, dimName, dataIndex, dimIndex) { + // TODO should convert to ParsedValue? + const rawVal = item.coord[Math.floor(dimIndex / 2)][dimIndex % 2]; + return parseDataValue(rawVal, dataDims[dimIndex]); + } + : function (item, dimName, dataIndex, dimIndex) { + return parseDataValue(item.value, dataDims[dimIndex]); + }; areaData.initData(optData, null, dimValueGetter); areaData.hasItemOption = true; return areaData; diff --git a/src/component/marker/MarkLineModel.ts b/src/component/marker/MarkLineModel.ts index 0c27667345..9cde9e024d 100644 --- a/src/component/marker/MarkLineModel.ts +++ b/src/component/marker/MarkLineModel.ts @@ -24,7 +24,8 @@ import { SeriesLineLabelOption, SymbolOptionMixin, ItemStyleOption, - StatesOptionMixin + StatesOptionMixin, + StatesMixinBase } from '../../util/types'; interface MarkLineStateOption { @@ -35,7 +36,8 @@ interface MarkLineStateOption { itemStyle?: ItemStyleOption label?: SeriesLineLabelOption } -interface MarkLineDataItemOptionBase extends MarkLineStateOption, StatesOptionMixin { +interface MarkLineDataItemOptionBase extends MarkLineStateOption, + StatesOptionMixin { name?: string } @@ -79,7 +81,8 @@ export type MarkLine2DDataItemOption = [ ]; export interface MarkLineOption extends MarkerOption, - MarkLineStateOption, StatesOptionMixin { + MarkLineStateOption, + StatesOptionMixin { mainType?: 'markLine' symbol?: string[] | string diff --git a/src/component/marker/MarkLineView.ts b/src/component/marker/MarkLineView.ts index 212ce68ced..760e92ff06 100644 --- a/src/component/marker/MarkLineView.ts +++ b/src/component/marker/MarkLineView.ts @@ -41,7 +41,6 @@ import { logError, merge, map, - defaults, curry, filter, HashMap @@ -50,6 +49,7 @@ import { makeInner } from '../../util/model'; import { LineDataVisual } from '../../visual/commonVisualTypes'; import { getVisualFromData } from '../../visual/helper'; import Axis2D from '../../coord/cartesian/Axis2D'; +import SeriesDimensionDefine from '../../data/SeriesDimensionDefine'; // Item option for configuring line and each end of symbol. // Line option. be merged from configuration of two ends. @@ -435,7 +435,7 @@ class MarkLineView extends MarkerView { function createList(coordSys: CoordinateSystem, seriesModel: SeriesModel, mlModel: MarkLineModel) { - let coordDimsInfos; + let coordDimsInfos: SeriesDimensionDefine[]; if (coordSys) { coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { const info = seriesModel.getData().getDimensionInfo( @@ -469,9 +469,9 @@ function createList(coordSys: CoordinateSystem, seriesModel: SeriesModel, mlMode optData, curry(markLineFilter, coordSys) ); } - const dimValueGetter = coordSys ? markerHelper.dimValueGetter : function (item: MarkLineMergedItemOption) { - return item.value; - }; + + const dimValueGetter = markerHelper.createMarkerDimValueGetter(!!coordSys, coordDimsInfos); + fromData.initData( map(optData, function (item) { return item[0]; diff --git a/src/component/marker/MarkPointModel.ts b/src/component/marker/MarkPointModel.ts index db5f1663eb..3fef1b30db 100644 --- a/src/component/marker/MarkPointModel.ts +++ b/src/component/marker/MarkPointModel.ts @@ -24,7 +24,8 @@ import { ItemStyleOption, SeriesLabelOption, CallbackDataParams, - StatesOptionMixin + StatesOptionMixin, + StatesMixinBase } from '../../util/types'; // interface MarkPointCallbackDataParams extends CallbackDataParams { @@ -37,7 +38,7 @@ interface MarkPointStateOption { label?: SeriesLabelOption } export interface MarkPointDataItemOption extends - MarkPointStateOption, StatesOptionMixin, + MarkPointStateOption, StatesOptionMixin, // TODO should not support callback in data SymbolOptionMixin, MarkerPositionOption { @@ -46,7 +47,7 @@ export interface MarkPointDataItemOption extends export interface MarkPointOption extends MarkerOption, SymbolOptionMixin, - StatesOptionMixin, MarkPointStateOption { + StatesOptionMixin, MarkPointStateOption { mainType?: 'markPoint' precision?: number diff --git a/src/component/marker/MarkPointView.ts b/src/component/marker/MarkPointView.ts index f0693da1fe..d5e4fc1fa7 100644 --- a/src/component/marker/MarkPointView.ts +++ b/src/component/marker/MarkPointView.ts @@ -29,10 +29,11 @@ import MarkPointModel, {MarkPointDataItemOption} from './MarkPointModel'; import GlobalModel from '../../model/Global'; import MarkerModel from './MarkerModel'; import ExtensionAPI from '../../core/ExtensionAPI'; -import { HashMap, isFunction, map, defaults, filter, curry, extend } from 'zrender/src/core/util'; +import { HashMap, isFunction, map, filter, curry, extend } from 'zrender/src/core/util'; import { getECData } from '../../util/innerStore'; import { getVisualFromData } from '../../visual/helper'; import { ZRColor } from '../../util/types'; +import SeriesDimensionDefine from '../../data/SeriesDimensionDefine'; function updateMarkerLayout( mpData: SeriesData, @@ -180,7 +181,7 @@ function createData( seriesModel: SeriesModel, mpModel: MarkPointModel ) { - let coordDimsInfos; + let coordDimsInfos: SeriesDimensionDefine[]; if (coordSys) { coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { const info = seriesModel.getData().getDimensionInfo( @@ -211,11 +212,8 @@ function createData( ); } - mpData.initData(dataOpt, null, - coordSys ? markerHelper.dimValueGetter : function (item: MarkPointDataItemOption) { - return item.value; - } - ); + const dimValueGetter = markerHelper.createMarkerDimValueGetter(!!coordSys, coordDimsInfos); + mpData.initData(dataOpt, null, dimValueGetter); return mpData; } diff --git a/src/component/marker/markerHelper.ts b/src/component/marker/markerHelper.ts index 0987473a59..f0394b7f6a 100644 --- a/src/component/marker/markerHelper.ts +++ b/src/component/marker/markerHelper.ts @@ -26,6 +26,8 @@ import { indexOf, curry, clone, isArray } from 'zrender/src/core/util'; import Axis from '../../coord/Axis'; import { CoordinateSystem } from '../../coord/CoordinateSystem'; import { ScaleDataValue, ParsedValue, DimensionLoose, DimensionName } from '../../util/types'; +import { parseDataValue } from '../../data/helper/dataValueHelper'; +import SeriesDimensionDefine from '../../data/SeriesDimensionDefine'; interface MarkerAxisInfo { valueDataDim: DimensionName @@ -34,6 +36,13 @@ interface MarkerAxisInfo { baseDataDim: DimensionName } +export type MarkerDimValueGetter = ( + item: TMarkerItemOption, + dimName: string, + dataIndex: number, + dimIndex: number +) => ParsedValue; + function hasXOrY(item: MarkerPositionOption) { return !(isNaN(parseFloat(item.x as string)) && isNaN(parseFloat(item.y as string))); } @@ -187,17 +196,21 @@ export function dataFilter( ? coordSys.containData(item.coord) : true; } -export function dimValueGetter( - item: MarkerPositionOption, - dimName: string, - dataIndex: number, - dimIndex: number -) { - // x, y, radius, angle - if (dimIndex < 2) { - return item.coord && item.coord[dimIndex] as ParsedValue; - } - return item.value; +export function createMarkerDimValueGetter( + inCoordSys: boolean, + dims: SeriesDimensionDefine[] +): MarkerDimValueGetter { + return inCoordSys + ? function (item, dimName, dataIndex, dimIndex) { + const rawVal = dimIndex < 2 + // x, y, radius, angle + ? (item.coord && item.coord[dimIndex]) + : item.value; + return parseDataValue(rawVal, dims[dimIndex]); + } + : function (item, dimName, dataIndex, dimIndex) { + return parseDataValue(item.value, dims[dimIndex]); + }; } export function numCalculate( diff --git a/src/component/tooltip/TooltipView.ts b/src/component/tooltip/TooltipView.ts index 858925464a..e83ca60fde 100644 --- a/src/component/tooltip/TooltipView.ts +++ b/src/component/tooltip/TooltipView.ts @@ -57,6 +57,7 @@ import { DataByCoordSys, DataByAxis } from '../axisPointer/axisTrigger'; import { normalizeTooltipFormatResult } from '../../model/mixin/dataFormat'; import { createTooltipMarkup, buildTooltipMarkup, TooltipMarkupStyleCreator } from './tooltipMarkup'; import { findEventDispatcher } from '../../util/event'; +import { throttle } from '../../util/throttle'; const bind = zrUtil.bind; const each = zrUtil.each; @@ -167,6 +168,8 @@ class TooltipView extends ComponentView { private _lastDataByCoordSys: DataByCoordSys[]; private _cbParamsList: TooltipCallbackDataParams[]; + private _updatePosition: ReturnType | TooltipView['_doUpdatePosition']; + init(ecModel: GlobalModel, api: ExtensionAPI) { if (env.node) { return; @@ -214,6 +217,17 @@ class TooltipView extends ComponentView { this._initGlobalListener(); this._keepShow(); + + // PENDING + // `mousemove` event will be triggered very frequently when the mouse moves fast, + // which causes that the updatePosition was also called very frequently. + // In Chrome with devtools open and Firefox, tooltip looks lagged and shaked around. See #14695. + // To avoid the frequent triggering, + // consider throttling it in 50ms. (the tested result may need to validate) + this._updatePosition = + this._renderMode === 'html' + ? throttle(bind(this._doUpdatePosition, this), 50) + : this._doUpdatePosition; } private _initGlobalListener() { @@ -856,7 +870,7 @@ class TooltipView extends ComponentView { } } - private _updatePosition( + private _doUpdatePosition( tooltipModel: Model, positionExpr: TooltipOption['position'], x: number, // Mouse x diff --git a/src/coord/Axis.ts b/src/coord/Axis.ts index a2f3e0ae89..7a334a0a4b 100644 --- a/src/coord/Axis.ts +++ b/src/coord/Axis.ts @@ -28,7 +28,7 @@ import Scale from '../scale/Scale'; import { DimensionName, ScaleDataValue, ScaleTick } from '../util/types'; import OrdinalScale from '../scale/Ordinal'; import Model from '../model/Model'; -import { AxisBaseOption, OptionAxisType } from './axisCommonTypes'; +import { AxisBaseOption, CategoryAxisBaseOption, OptionAxisType } from './axisCommonTypes'; import { AxisBaseModel } from './AxisBaseModel'; const NORMALIZED_EXTENT = [0, 1] as [number, number]; @@ -63,7 +63,7 @@ class Axis { // Injected outside model: AxisBaseModel; - onBand: AxisBaseOption['boundaryGap'] = false; + onBand: CategoryAxisBaseOption['boundaryGap'] = false; inverse: AxisBaseOption['inverse'] = false; diff --git a/src/coord/AxisBaseModel.ts b/src/coord/AxisBaseModel.ts index 18cd29a292..9b482f0cb0 100644 --- a/src/coord/AxisBaseModel.ts +++ b/src/coord/AxisBaseModel.ts @@ -20,16 +20,16 @@ /** * Base Axis Model for xAxis, yAxis, angleAxis, radiusAxis. singleAxis */ -import { AxisBaseOption } from './axisCommonTypes'; +import { AxisBaseOptionCommon } from './axisCommonTypes'; import ComponentModel from '../model/Component'; import { AxisModelCommonMixin } from './axisModelCommonMixin'; import { AxisModelExtendedInCreator } from './axisModelCreator'; import Axis from './Axis'; -export interface AxisBaseModel +export interface AxisBaseModel extends ComponentModel, AxisModelCommonMixin, - AxisModelExtendedInCreator { + AxisModelExtendedInCreator { axis: Axis } \ No newline at end of file diff --git a/src/coord/axisCommonTypes.ts b/src/coord/axisCommonTypes.ts index 9d9bf1117a..509173c033 100644 --- a/src/coord/axisCommonTypes.ts +++ b/src/coord/axisCommonTypes.ts @@ -20,16 +20,15 @@ import { TextCommonOption, LineStyleOption, OrdinalRawValue, ZRColor, AreaStyleOption, ComponentOption, ColorString, - AnimationOptionMixin, Dictionary, ScaleDataValue + AnimationOptionMixin, Dictionary, ScaleDataValue, CommonAxisPointerOption } from '../util/types'; export const AXIS_TYPES = {value: 1, category: 1, time: 1, log: 1} as const; export type OptionAxisType = keyof typeof AXIS_TYPES; - -export interface AxisBaseOption extends ComponentOption, - AnimationOptionMixin { // Support transition animation +export interface AxisBaseOptionCommon extends ComponentOption, + AnimationOptionMixin { type?: OptionAxisType; show?: boolean; // Inverse the axis. @@ -55,73 +54,103 @@ export interface AxisBaseOption extends ComponentOption, show?: boolean; }; - axisPointer?: any; // FIXME:TS axisPointerOption type? + axisLabel?: AxisLabelBaseOption; + + axisPointer?: CommonAxisPointerOption; axisLine?: AxisLineOption; axisTick?: AxisTickOption; - axisLabel?: AxisLabelOption; minorTick?: MinorTickOption; splitLine?: SplitLineOption; minorSplitLine?: MinorSplitLineOption; splitArea?: SplitAreaOption; - // The gap at both ends of the axis. - // For category axis: boolean. - // For value axis: [GAP, GAP], where - // `GAP` can be an absolute pixel number (like `35`), or percent (like `'30%'`) - boundaryGap?: boolean | [number | string, number | string]; - - // Min value of the axis. can be: - // + ScaleDataValue - // + 'dataMin': use the min value in data. - // + null/undefined: auto decide min value (consider pretty look and boundaryGap). + /** + * Min value of the axis. can be: + * + ScaleDataValue + * + 'dataMin': use the min value in data. + * + null/undefined: auto decide min value (consider pretty look and boundaryGap). + */ min?: ScaleDataValue | 'dataMin' | ((extent: {min: number, max: number}) => ScaleDataValue); - // Max value of the axis. can be: - // + ScaleDataValue - // + 'dataMax': use the max value in data. - // + null/undefined: auto decide max value (consider pretty look and boundaryGap). + /** + * Max value of the axis. can be: + * + ScaleDataValue + * + 'dataMax': use the max value in data. + * + null/undefined: auto decide max value (consider pretty look and boundaryGap). + */ max?: ScaleDataValue | 'dataMax' | ((extent: {min: number, max: number}) => ScaleDataValue); // Optional value can be: // + `false`: always include value 0. // + `true`: the extent do not consider value 0. scale?: boolean; +} - // -------------------------------------------- - // [Properties below only for 'category' axis]: - - // Set false to faster category collection. - // Only usefull in the case like: category is - // ['2012-01-01', '2012-01-02', ...], where the input - // data has been ensured not duplicate and is large data. - // null means "auto": - // if axis.data provided, do not deduplication, - // else do deduplication. - deduplication?: boolean; - data?: (OrdinalRawValue | { - value: OrdinalRawValue; - textStyle?: TextCommonOption; - })[]; - - - // ------------------------------------------------------ - // [Properties below only for 'value'/'log'/'time' axes]: - - // AxisTick and axisLabel and splitLine are caculated based on splitNumber. +interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { + /* + * The gap at both ends of the axis. + * [GAP, GAP], where + * `GAP` can be an absolute pixel number (like `35`), or percent (like `'30%'`) + */ + boundaryGap?: [number | string, number | string] + + /** + * AxisTick and axisLabel and splitLine are caculated based on splitNumber. + */ splitNumber?: number; - // Interval specifies the span of the ticks is mandatorily. + /** + * Interval specifies the span of the ticks is mandatorily. + */ interval?: number; - // Specify min interval when auto calculate tick interval. + /** + * Specify min interval when auto calculate tick interval. + */ minInterval?: number; - // Specify max interval when auto calculate tick interval. + /** + * Specify max interval when auto calculate tick interval. + */ maxInterval?: number; +} +export interface CategoryAxisBaseOption extends AxisBaseOptionCommon { + type?: 'category'; + boundaryGap?: boolean + axisLabel?: AxisLabelOption<'category'> & { + interval?: 'auto' | number | ((index: number, value: string) => boolean) + }; + data?: (OrdinalRawValue | { + value: OrdinalRawValue; + textStyle?: TextCommonOption; + })[]; + /* + * Set false to faster category collection. + * Only usefull in the case like: category is + * ['2012-01-01', '2012-01-02', ...], where the input + * data has been ensured not duplicate and is large data. + * null means "auto": + * if axis.data provided, do not deduplication, + * else do deduplication. + */ + deduplication?: boolean; - // --------------------------------------- - // [Properties below only for 'log' axis]: - + axisTick?: AxisBaseOptionCommon['axisTick'] & { + // If tick is align with label when boundaryGap is true + alignWithLabel?: boolean, + interval?: 'auto' | number | ((index: number, value: string) => boolean) + } +} +export interface ValueAxisBaseOption extends NumericAxisBaseOptionCommon { + type?: 'value'; + axisLabel?: AxisLabelOption<'value'>; +} +export interface LogAxisBaseOption extends NumericAxisBaseOptionCommon { + type?: 'log'; + axisLabel?: AxisLabelOption<'log'>; logBase?: number; } - +export interface TimeAxisBaseOption extends NumericAxisBaseOptionCommon { + type?: 'time'; + axisLabel?: AxisLabelOption<'time'>; +} interface AxisNameTextStyleOption extends TextCommonOption { rich?: Dictionary } @@ -144,18 +173,13 @@ interface AxisTickOption { // The length of axisTick. length?: number, lineStyle?: LineStyleOption - - // -------------------------------------------- - // [Properties below only for 'category' axis]: - - // If tick is align with label when boundaryGap is true - alignWithLabel?: boolean, - interval?: 'auto' | number | ((index: number, value: string) => boolean) } -export type AxisLabelFormatterOption = string | ((value: OrdinalRawValue | number, index: number) => string); +type AxisLabelValueFormatter = (value: number, index: number) => string; +type AxisLabelCategoryFormatter = (value: string, index: number) => string; -type TimeAxisLabelUnitFormatter = AxisLabelFormatterOption | string[]; +// export type AxisLabelFormatterOption = string | ((value: OrdinalRawValue | number, index: number) => string); +type TimeAxisLabelUnitFormatter = AxisLabelValueFormatter | string[] | string; export type TimeAxisLabelFormatterOption = string | ((value: number, index: number, extra: {level: number}) => string) @@ -171,7 +195,14 @@ export type TimeAxisLabelFormatterOption = string inherit?: boolean }; -interface AxisLabelOption extends Omit { +type LabelFormatters = { + value: AxisLabelValueFormatter | string + log: AxisLabelValueFormatter | string + category: AxisLabelCategoryFormatter | string + time: TimeAxisLabelFormatterOption +}; + +interface AxisLabelBaseOption extends Omit { show?: boolean, // Whether axisLabel is inside the grid or outside the grid. inside?: boolean, @@ -181,18 +212,16 @@ interface AxisLabelOption extends Omit { // true | false | null/undefined (auto) showMaxLabel?: boolean, margin?: number, - // value is supposed to be OptionDataPrimitive but for time axis, it is time stamp. - formatter?: AxisLabelFormatterOption | TimeAxisLabelFormatterOption, - - // -------------------------------------------- - // [Properties below only for 'category' axis]: - - interval?: 'auto' | number | ((index: number, value: string) => boolean) - + rich?: Dictionary + /** + * If hide overlapping labels. + */ + hideOverlap?: boolean; // Color can be callback color?: ColorString | ((value?: string | number, index?: number) => ColorString) - - rich?: Dictionary +} +interface AxisLabelOption extends AxisLabelBaseOption { + formatter?: LabelFormatters[TType] } interface MinorTickOption { @@ -220,3 +249,7 @@ interface SplitAreaOption { // colors will display in turn areaStyle?: AreaStyleOption } + + +export type AxisBaseOption = ValueAxisBaseOption | LogAxisBaseOption + | CategoryAxisBaseOption | TimeAxisBaseOption | AxisBaseOptionCommon; diff --git a/src/coord/axisHelper.ts b/src/coord/axisHelper.ts index d058db3ad1..53a60b6f5b 100644 --- a/src/coord/axisHelper.ts +++ b/src/coord/axisHelper.ts @@ -33,7 +33,13 @@ import Model from '../model/Model'; import { AxisBaseModel } from './AxisBaseModel'; import LogScale from '../scale/Log'; import Axis from './Axis'; -import { AxisBaseOption, TimeAxisLabelFormatterOption } from './axisCommonTypes'; +import { + AxisBaseOption, + CategoryAxisBaseOption, + LogAxisBaseOption, + TimeAxisLabelFormatterOption, + ValueAxisBaseOption +} from './axisCommonTypes'; import type CartesianAxisModel from './cartesian/AxisModel'; import SeriesData from '../data/SeriesData'; import { getStackedDimension } from '../data/helper/dataStackHelper'; @@ -143,7 +149,8 @@ function adjustScaleForOverflow( // Precondition of calling this method: // The scale extent has been initailized using series data extent via // `scale.setExtent` or `scale.unionExtentFromData`; -export function niceScaleExtent(scale: Scale, model: AxisBaseModel) { +export function niceScaleExtent(scale: Scale, inModel: AxisBaseModel) { + const model = inModel as AxisBaseModel; const extentInfo = getScaleExtent(scale, model); const extent = extentInfo.extent; const splitNumber = model.get('splitNumber'); @@ -221,7 +228,8 @@ export function ifAxisCrossZero(axis: Axis) { * return: {string} label string. */ export function makeLabelFormatter(axis: Axis): (tick: ScaleTick, idx?: number) => string { - const labelFormatter = axis.getLabelModel().get('formatter'); + const labelFormatter = (axis.getLabelModel() as Model) + .get('formatter'); const categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null; if (axis.scale.type === 'time') { @@ -263,7 +271,7 @@ export function makeLabelFormatter(axis: Axis): (tick: ScaleTick, idx?: number) } : null ); }; - })(labelFormatter); + })(labelFormatter as (...args: any[]) => string); } else { return function (tick: ScaleTick) { @@ -347,7 +355,7 @@ function rotateTextRect(textRect: RectLike, rotate: number) { * @return {number|String} Can be null|'auto'|number|function */ export function getOptionCategoryInterval(model: Model) { - const interval = model.get('interval'); + const interval = (model as Model).get('interval'); return interval == null ? 'auto' : interval; } diff --git a/src/coord/axisModelCreator.ts b/src/coord/axisModelCreator.ts index 5d275ee459..f7d80720cb 100644 --- a/src/coord/axisModelCreator.ts +++ b/src/coord/axisModelCreator.ts @@ -26,7 +26,7 @@ import { } from '../util/layout'; import OrdinalMeta from '../data/OrdinalMeta'; import { DimensionName, BoxLayoutOptionMixin, OrdinalRawValue } from '../util/types'; -import { AxisBaseOption, AXIS_TYPES } from './axisCommonTypes'; +import { AxisBaseOption, AXIS_TYPES, CategoryAxisBaseOption } from './axisCommonTypes'; import GlobalModel from '../model/Global'; import { each, merge } from 'zrender/src/core/util'; import { EChartsExtensionInstallRegisters } from '../extension'; @@ -34,8 +34,8 @@ import { EChartsExtensionInstallRegisters } from '../extension'; type Constructor = new (...args: any[]) => T; -export interface AxisModelExtendedInCreator { - getCategories(rawData?: boolean): OrdinalRawValue[] | Opt['data'] +export interface AxisModelExtendedInCreator { + getCategories(rawData?: boolean): OrdinalRawValue[] | CategoryAxisBaseOption['data'] getOrdinalMeta(): OrdinalMeta } @@ -60,7 +60,7 @@ export default function axisModelCreator< extraDefaultOption, true ); - class AxisModel extends BaseAxisModelClass implements AxisModelExtendedInCreator { + class AxisModel extends BaseAxisModelClass implements AxisModelExtendedInCreator { static type = axisName + 'Axis.' + axisType; type = axisName + 'Axis.' + axisType; @@ -97,13 +97,13 @@ export default function axisModelCreator< * Should not be called before all of 'getInitailData' finished. * Because categories are collected during initializing data. */ - getCategories(rawData?: boolean): OrdinalRawValue[] | AxisBaseOption['data'] { + getCategories(rawData?: boolean): OrdinalRawValue[] | CategoryAxisBaseOption['data'] { const option = this.option; // FIXME // warning if called before all of 'getInitailData' finished. if (option.type === 'category') { if (rawData) { - return option.data as AxisBaseOption['data']; + return (option as CategoryAxisBaseOption).data; } return this.__ordinalMeta.categories; } @@ -125,5 +125,5 @@ export default function axisModelCreator< function getAxisType(option: AxisBaseOption) { // Default axis with data is category axis - return option.type || (option.data ? 'category' : 'value'); + return option.type || ((option as CategoryAxisBaseOption).data ? 'category' : 'value'); } diff --git a/src/coord/axisTickLabelBuilder.ts b/src/coord/axisTickLabelBuilder.ts index 332e542e83..fbc2e5c975 100644 --- a/src/coord/axisTickLabelBuilder.ts +++ b/src/coord/axisTickLabelBuilder.ts @@ -62,6 +62,7 @@ const inner = makeInner(); export function createAxisLabels(axis: Axis): { labels: { + level?: number, formattedLabel: string, rawLabel: string, tickValue: number @@ -176,6 +177,7 @@ function makeRealNumberLabels(axis: Axis) { return { labels: zrUtil.map(ticks, function (tick, idx) { return { + level: tick.level, formattedLabel: labelFormatter(tick, idx), rawLabel: axis.scale.getLabel(tick), tickValue: tick.value diff --git a/src/coord/cartesian/AxisModel.ts b/src/coord/cartesian/AxisModel.ts index 076b1c142f..726e0fa798 100644 --- a/src/coord/cartesian/AxisModel.ts +++ b/src/coord/cartesian/AxisModel.ts @@ -31,21 +31,21 @@ import { SINGLE_REFERRING } from '../../util/model'; export type CartesianAxisPosition = 'top' | 'bottom' | 'left' | 'right'; -export interface CartesianAxisOption extends AxisBaseOption { +export type CartesianAxisOption = AxisBaseOption & { gridIndex?: number; gridId?: string; position?: CartesianAxisPosition; // Offset is for multiple axis on the same position. offset?: number; categorySortInfo?: OrdinalSortInfo; -} +}; -export interface XAXisOption extends CartesianAxisOption { +export type XAXisOption = CartesianAxisOption & { mainType?: 'xAxis' -} -export interface YAXisOption extends CartesianAxisOption { +}; +export type YAXisOption = CartesianAxisOption & { mainType?: 'yAxis' -} +}; export class CartesianAxisModel extends ComponentModel implements AxisBaseModel { @@ -60,7 +60,7 @@ export class CartesianAxisModel extends ComponentModel } export interface CartesianAxisModel extends AxisModelCommonMixin, - AxisModelExtendedInCreator {} + AxisModelExtendedInCreator {} zrUtil.mixin(CartesianAxisModel, AxisModelCommonMixin); diff --git a/src/coord/cartesian/Grid.ts b/src/coord/cartesian/Grid.ts index 6eef23eac1..aba0b732c0 100644 --- a/src/coord/cartesian/Grid.ts +++ b/src/coord/cartesian/Grid.ts @@ -47,6 +47,8 @@ import { ScaleDataValue } from '../../util/types'; import SeriesData from '../../data/SeriesData'; import OrdinalScale from '../../scale/Ordinal'; import { isCartesian2DSeries, findAxisModels } from './cartesianAxisHelper'; +import { CategoryAxisBaseOption } from '../axisCommonTypes'; +import { AxisBaseModel } from '../AxisBaseModel'; type Cartesian2DDimensionName = 'x' | 'y'; @@ -388,7 +390,7 @@ class Grid implements CoordinateSystemMaster { ); const isCategory = axis.type === 'category'; - axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.onBand = isCategory && (axisModel as AxisBaseModel).get('boundaryGap'); axis.inverse = axisModel.get('inverse'); // Inject axis into axisModel diff --git a/src/coord/geo/GeoModel.ts b/src/coord/geo/GeoModel.ts index f65553ca02..adbafee13a 100644 --- a/src/coord/geo/GeoModel.ts +++ b/src/coord/geo/GeoModel.ts @@ -35,14 +35,15 @@ import { AnimationOptionMixin, StatesOptionMixin, Dictionary, - CommonTooltipOption + CommonTooltipOption, + StatesMixinBase } from '../../util/types'; import { NameMap } from './geoTypes'; import GlobalModel from '../../model/Global'; import geoSourceManager from './geoSourceManager'; -export interface GeoItemStyleOption extends ItemStyleOption { +export interface GeoItemStyleOption extends ItemStyleOption { areaColor?: ZRColor; }; interface GeoLabelOption extends LabelOption { @@ -58,7 +59,7 @@ interface GeoLabelFormatterDataParams { status: DisplayState; } -export interface RegoinOption extends GeoStateOption, StatesOptionMixin { +export interface RegoinOption extends GeoStateOption, StatesOptionMixin { name?: string selected?: boolean tooltip?: CommonTooltipOption @@ -102,7 +103,7 @@ export interface GeoOption extends // For lens animation on geo. AnimationOptionMixin, GeoCommonOptionMixin, - StatesOptionMixin, GeoStateOption { + StatesOptionMixin, GeoStateOption { mainType?: 'geo'; show?: boolean; diff --git a/src/coord/parallel/AxisModel.ts b/src/coord/parallel/AxisModel.ts index 31beb29f8a..877dbaec85 100644 --- a/src/coord/parallel/AxisModel.ts +++ b/src/coord/parallel/AxisModel.ts @@ -40,7 +40,7 @@ export type ParallelAreaSelectStyleProps = Pick { @@ -140,7 +140,7 @@ class ParallelAxisModel extends ComponentModel { } interface ParallelAxisModel extends AxisModelCommonMixin, - AxisModelExtendedInCreator {} + AxisModelExtendedInCreator {} zrUtil.mixin(ParallelAxisModel, AxisModelCommonMixin); diff --git a/src/coord/parallel/Parallel.ts b/src/coord/parallel/Parallel.ts index e22cf9a8d7..f8c472dad1 100644 --- a/src/coord/parallel/Parallel.ts +++ b/src/coord/parallel/Parallel.ts @@ -38,6 +38,8 @@ import { Dictionary, DimensionName, ScaleDataValue } from '../../util/types'; import { CoordinateSystem, CoordinateSystemMaster } from '../CoordinateSystem'; import ParallelAxisModel, { ParallelActiveState } from './AxisModel'; import SeriesData from '../../data/SeriesData'; +import { AxisBaseModel } from '../AxisBaseModel'; +import { CategoryAxisBaseOption } from '../axisCommonTypes'; const each = zrUtil.each; const mathMin = Math.min; @@ -131,7 +133,8 @@ class Parallel implements CoordinateSystemMaster, CoordinateSystem { )); const isCategory = axis.type === 'category'; - axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.onBand = isCategory + && (axisModel as AxisBaseModel).get('boundaryGap'); axis.inverse = axisModel.get('inverse'); // Injection diff --git a/src/coord/polar/AxisModel.ts b/src/coord/polar/AxisModel.ts index 2afbc3c11e..af2414a673 100644 --- a/src/coord/polar/AxisModel.ts +++ b/src/coord/polar/AxisModel.ts @@ -27,7 +27,7 @@ import RadiusAxis from './RadiusAxis'; import { AxisBaseModel } from '../AxisBaseModel'; import { SINGLE_REFERRING } from '../../util/model'; -export interface AngleAxisOption extends AxisBaseOption { +export type AngleAxisOption = AxisBaseOption & { mainType?: 'angleAxis'; /** * Index of host polar component @@ -41,12 +41,10 @@ export interface AngleAxisOption extends AxisBaseOption { startAngle?: number; clockwise?: boolean; - splitNumber?: number; - axisLabel?: AxisBaseOption['axisLabel'] -} +}; -export interface RadiusAxisOption extends AxisBaseOption { +export type RadiusAxisOption = AxisBaseOption & { mainType?: 'radiusAxis'; /** * Index of host polar component @@ -56,7 +54,7 @@ export interface RadiusAxisOption extends AxisBaseOption { * Id of host polar component */ polarId?: string; -} +}; type PolarAxisOption = AngleAxisOption | RadiusAxisOption; @@ -72,7 +70,7 @@ class PolarAxisModel extends Compon } interface PolarAxisModel - extends AxisModelCommonMixin, AxisModelExtendedInCreator {} + extends AxisModelCommonMixin, AxisModelExtendedInCreator {} zrUtil.mixin(PolarAxisModel, AxisModelCommonMixin); diff --git a/src/coord/polar/polarCreator.ts b/src/coord/polar/polarCreator.ts index 69feeca425..4df310c1d4 100644 --- a/src/coord/polar/polarCreator.ts +++ b/src/coord/polar/polarCreator.ts @@ -38,6 +38,8 @@ import { PolarAxisModel, AngleAxisModel, RadiusAxisModel } from './AxisModel'; import SeriesModel from '../../model/Series'; import { SeriesOption } from '../../util/types'; import { SINGLE_REFERRING } from '../../util/model'; +import { AxisBaseModel } from '../AxisBaseModel'; +import { CategoryAxisBaseOption } from '../axisCommonTypes'; /** * Resize method bound to the polar @@ -115,7 +117,8 @@ function isAngleAxisModel(axisModel: AngleAxisModel | PolarAxisModel): axisModel function setAxis(axis: RadiusAxis | AngleAxis, axisModel: PolarAxisModel) { axis.type = axisModel.get('type'); axis.scale = createScaleByModel(axisModel); - axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category'; + axis.onBand = (axisModel as AxisBaseModel).get('boundaryGap') + && axis.type === 'category'; axis.inverse = axisModel.get('inverse'); if (isAngleAxisModel(axisModel)) { diff --git a/src/coord/radar/RadarModel.ts b/src/coord/radar/RadarModel.ts index 070892f064..cdcd3e8181 100644 --- a/src/coord/radar/RadarModel.ts +++ b/src/coord/radar/RadarModel.ts @@ -28,7 +28,7 @@ import { LabelOption, ColorString } from '../../util/types'; -import { AxisBaseOption } from '../axisCommonTypes'; +import { AxisBaseOption, CategoryAxisBaseOption, ValueAxisBaseOption } from '../axisCommonTypes'; import { AxisBaseModel } from '../AxisBaseModel'; import Radar from './Radar'; import {CoordinateSystemHostModel} from '../../coord/CoordinateSystem'; @@ -42,6 +42,7 @@ function defaultsShow(opt: object, show: boolean) { } export interface RadarIndicatorOption { + name?: string text?: string min?: number max?: number @@ -78,15 +79,16 @@ export interface RadarOption extends ComponentOption, CircleLayoutOptionMixin { scale?: boolean splitNumber?: number - boundaryGap?: AxisBaseOption['boundaryGap'] + boundaryGap?: CategoryAxisBaseOption['boundaryGap'] + | ValueAxisBaseOption['boundaryGap'] indicator?: RadarIndicatorOption[] } -export interface InnerIndicatorAxisOption extends AxisBaseOption { +export type InnerIndicatorAxisOption = AxisBaseOption & { // TODO Use type? // axisType?: 'value' | 'log' -} +}; class RadarModel extends ComponentModel implements CoordinateSystemHostModel { static readonly type = 'radar'; diff --git a/src/coord/scaleRawExtentInfo.ts b/src/coord/scaleRawExtentInfo.ts index 5a0abb67d2..45d2dc7d43 100644 --- a/src/coord/scaleRawExtentInfo.ts +++ b/src/coord/scaleRawExtentInfo.ts @@ -21,7 +21,7 @@ import { assert, isArray, eqNaN, isFunction } from 'zrender/src/core/util'; import Scale from '../scale/Scale'; import { AxisBaseModel } from './AxisBaseModel'; import { parsePercent } from 'zrender/src/contain/text'; -import { AxisBaseOption } from './axisCommonTypes'; +import { AxisBaseOption, CategoryAxisBaseOption } from './axisCommonTypes'; import { ScaleDataValue } from '../util/types'; @@ -129,7 +129,7 @@ export class ScaleRawExtentInfo { this._axisDataLen = model.getCategories().length; } else { - const boundaryGap = model.get('boundaryGap'); + const boundaryGap = (model as AxisBaseModel).get('boundaryGap'); const boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0]; diff --git a/src/coord/single/AxisModel.ts b/src/coord/single/AxisModel.ts index 7f761387b9..bcd85268fd 100644 --- a/src/coord/single/AxisModel.ts +++ b/src/coord/single/AxisModel.ts @@ -29,11 +29,11 @@ import { mixin } from 'zrender/src/core/util'; export type SingleAxisPosition = 'top' | 'bottom' | 'left' | 'right'; -export interface SingleAxisOption extends AxisBaseOption, BoxLayoutOptionMixin { +export type SingleAxisOption = AxisBaseOption & BoxLayoutOptionMixin & { mainType?: 'singleAxis' position?: SingleAxisPosition orient?: LayoutOrient -} +}; class SingleAxisModel extends ComponentModel implements AxisBaseModel { @@ -102,7 +102,7 @@ class SingleAxisModel extends ComponentModel } interface SingleAxisModel extends AxisModelCommonMixin, - AxisModelExtendedInCreator {} + AxisModelExtendedInCreator {} mixin(SingleAxisModel, AxisModelCommonMixin.prototype); diff --git a/src/coord/single/Single.ts b/src/coord/single/Single.ts index 5ad403169e..4632190e41 100644 --- a/src/coord/single/Single.ts +++ b/src/coord/single/Single.ts @@ -32,6 +32,8 @@ import BoundingRect from 'zrender/src/core/BoundingRect'; import SingleAxisModel from './AxisModel'; import { ParsedModelFinder, ParsedModelFinderKnown } from '../../util/model'; import { ScaleDataValue } from '../../util/types'; +import { AxisBaseModel } from '../AxisBaseModel'; +import { CategoryAxisBaseOption } from '../axisCommonTypes'; export const singleDimensions = ['single']; /** @@ -80,7 +82,7 @@ class Single implements CoordinateSystem, CoordinateSystemMaster { ); const isCategory = axis.type === 'category'; - axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.onBand = isCategory && (axisModel as AxisBaseModel).get('boundaryGap'); axis.inverse = axisModel.get('inverse'); axis.orient = axisModel.get('orient'); diff --git a/src/data/helper/transform.ts b/src/data/helper/transform.ts index 78c1a70754..6e5181f140 100644 --- a/src/data/helper/transform.ts +++ b/src/data/helper/transform.ts @@ -42,7 +42,7 @@ export type DataTransformConfig = unknown; export interface DataTransformOption { type: DataTransformType; - config: DataTransformConfig; + config?: DataTransformConfig; // Print the result via `console.log` when transform performed. Only work in dev mode for debug. print?: boolean; } diff --git a/src/export/core.ts b/src/export/core.ts index c1702f2154..d17b784b0e 100644 --- a/src/export/core.ts +++ b/src/export/core.ts @@ -24,7 +24,7 @@ export * from './api'; import { use } from '../extension'; // Import label layout by default. -// TODO remove +// TODO will be treeshaked. import {installLabelLayout} from '../label/installLabelLayout'; use(installLabelLayout); diff --git a/src/export/option.ts b/src/export/option.ts index 7ed1b4b35e..4980e4304f 100644 --- a/src/export/option.ts +++ b/src/export/option.ts @@ -86,7 +86,13 @@ import type {HeatmapSeriesOption as HeatmapSeriesOptionInner} from '../chart/hea import type {PictorialBarSeriesOption as PictorialBarSeriesOptionInner} from '../chart/bar/PictorialBarSeries'; import type {ThemeRiverSeriesOption as ThemeRiverSeriesOptionInner} from '../chart/themeRiver/ThemeRiverSeries'; import type {SunburstSeriesOption as SunburstSeriesOptionInner} from '../chart/sunburst/SunburstSeries'; -import type {CustomSeriesOption as CustomSeriesOptionInner} from '../chart/custom/CustomSeries'; +import type { + CustomSeriesOption as CustomSeriesOptionInner, + CustomSeriesRenderItemAPI, + CustomSeriesRenderItemParams, + CustomSeriesRenderItemReturn, + CustomSeriesRenderItem +} from '../chart/custom/CustomSeries'; import type { GraphicComponentLooseOption as GraphicComponentOption } from '../component/graphic/install'; import type { DatasetOption as DatasetComponentOption } from '../component/dataset/install'; @@ -264,5 +270,10 @@ export { TooltipFormatterCallback as TooltipComponentFormatterCallback, TopLevelFormatterParams as TooltipComponentFormatterCallbackParams, TooltipPositionCallback as TooltipComponentPositionCallback, - TooltipPositionCallbackParams as TooltipComponentPositionCallbackParams + TooltipPositionCallbackParams as TooltipComponentPositionCallbackParams, + + CustomSeriesRenderItemParams, + CustomSeriesRenderItemAPI, + CustomSeriesRenderItemReturn, + CustomSeriesRenderItem }; diff --git a/src/i18n/langPT-br.ts b/src/i18n/langPT-br.ts new file mode 100644 index 0000000000..8d6eb014f7 --- /dev/null +++ b/src/i18n/langPT-br.ts @@ -0,0 +1,143 @@ +/* +* 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. +*/ + +/** + * Language: Portuguese (Brazil). + */ + +export default { + time: { + month: [ + 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', + 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' + ], + monthAbbr: [ + 'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', + 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez' + ], + dayOfWeek: [ + 'Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', +'Quinta-feira', 'Sexta-feira', 'Sábado' + ], + dayOfWeekAbbr: [ + 'Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb' + ] + }, + legend: { + selector: { + all: 'Todas', + inverse: 'Inv' + } + }, + toolbox: { + brush: { + title: { + rect: 'Seleção retangular', + polygon: 'Seleção em laço', + lineX: 'Selecionar horizontalmente', + lineY: 'Selecionar verticalmente', + keep: 'Manter seleções', + clear: 'Limpar seleções' + } + }, + dataView: { + title: 'Exibição de dados', + lang: ['Exibição de dados', 'Fechar', 'Atualizar'] + }, + dataZoom: { + title: { + zoom: 'Zoom', + back: 'Restaurar Zoom' + } + }, + magicType: { + title: { + line: 'Trocar para gráfico de linhas', + bar: 'Trocar para gráfico de barras', + stack: 'Empilhar', + tiled: 'Tile' + } + }, + restore: { + title: 'Restore' + }, + saveAsImage: { + title: 'Salvar como imagem', + lang: ['Clique com o botão direito para salvar imagem'] + } + }, + series: { + typeNames: { + pie: 'Gráfico de pizza', + bar: 'Gráfico de barras', + line: 'Gráfico de linhas', + scatter: 'Gráfico de dispersão', + effectScatter: 'Gráfico de dispersão ondulado', + radar: 'Gráfico radar', + tree: 'Árvore', + treemap: 'Treemap', + boxplot: 'Boxplot', + candlestick: 'Candlestick', + k: 'Gráfico K line', + heatmap: 'Mapa de calor', + map: 'Mapa', + parallel: 'Coordenadas paralelas', + lines: 'Gráfico de linhas', + graph: 'Relationship graph', + sankey: 'Gráfico Sankey', + funnel: 'Gráfico de funil', + gauge: 'Gauge', + pictorialBar: 'Pictorial bar', + themeRiver: 'Theme River Map', + sunburst: 'Sunburst' + } + }, + aria: { + general: { + withTitle: 'Este é um gráfico entitulado "{title}"', + withoutTitle: 'Este é um gráfico' + }, + series: { + single: { + prefix: '', + withName: ' do tipo {seriesType} nomeada/nomeado como {seriesName}.', + withoutName: ' do tipo {seriesType}.' + }, + multiple: { + prefix: '. Consiste de {seriesCount} séries.', + withName: ' A {seriesId} série é um/uma {seriesType} representando {seriesName}.', + withoutName: ' A {seriesId} series é um/uma {seriesType}.', + separator: { + middle: '', + end: '' + } + } + }, + data: { + allData: 'Os dados são: ', + partialData: 'As primeiros {displayCnt} itens são: ', + withName: 'os dados para {name} são {value}', + withoutName: '{value}', + separator: { + middle: ', ', + end: '. ' + } + } + } +}; diff --git a/src/label/labelGuideHelper.ts b/src/label/labelGuideHelper.ts index ce53732d7b..c9a4b5bdb2 100644 --- a/src/label/labelGuideHelper.ts +++ b/src/label/labelGuideHelper.ts @@ -661,7 +661,7 @@ export function setLabelLineStyle( export function getLabelLineStatesModels( - itemModel: Model & Partial>>, + itemModel: Model & Partial>>, labelLineName?: LabelName ): Record { labelLineName = (labelLineName || 'labelLine') as LabelName; diff --git a/src/label/labelLayoutHelper.ts b/src/label/labelLayoutHelper.ts index d22bb77894..2f42db5c7c 100644 --- a/src/label/labelLayoutHelper.ts +++ b/src/label/labelLayoutHelper.ts @@ -24,12 +24,12 @@ import type Element from 'zrender/src/Element'; interface LabelLayoutListPrepareInput { label: ZRText - labelLine: Polyline - computedLayoutOption: LabelLayoutOption + labelLine?: Polyline + computedLayoutOption?: LabelLayoutOption priority: number defaultAttr: { ignore: boolean - labelGuideIgnore: boolean + labelGuideIgnore?: boolean } } @@ -44,7 +44,7 @@ export interface LabelLayoutInfo { layoutOption: LabelLayoutOption defaultAttr: { ignore: boolean - labelGuideIgnore: boolean + labelGuideIgnore?: boolean } transform: number[] } diff --git a/src/label/labelStyle.ts b/src/label/labelStyle.ts index e63a35117e..eb601ed5f9 100644 --- a/src/label/labelStyle.ts +++ b/src/label/labelStyle.ts @@ -293,7 +293,7 @@ function setLabelStyle( export { setLabelStyle }; export function getLabelStatesModels( - itemModel: Model & Partial>>, + itemModel: Model & Partial>>, labelName?: LabelName ): Record { labelName = (labelName || 'label') as LabelName; diff --git a/src/layout/barGrid.ts b/src/layout/barGrid.ts index 4a7c90887f..9c7807656c 100644 --- a/src/layout/barGrid.ts +++ b/src/layout/barGrid.ts @@ -77,11 +77,11 @@ type BarWidthAndOffset = Dictionary= endAngle }); } diff --git a/src/scale/Ordinal.ts b/src/scale/Ordinal.ts index 7f23c2d4cc..01139da56c 100644 --- a/src/scale/Ordinal.ts +++ b/src/scale/Ordinal.ts @@ -36,11 +36,11 @@ import { OrdinalScaleTick, ScaleTick } from '../util/types'; -import { AxisBaseOption } from '../coord/axisCommonTypes'; +import { CategoryAxisBaseOption } from '../coord/axisCommonTypes'; import { isArray, map, isObject } from 'zrender/src/core/util'; type OrdinalScaleSetting = { - ordinalMeta?: OrdinalMeta | AxisBaseOption['data']; + ordinalMeta?: OrdinalMeta | CategoryAxisBaseOption['data']; extent?: [number, number]; }; diff --git a/src/util/format.ts b/src/util/format.ts index c4950201d9..1f9749edc7 100644 --- a/src/util/format.ts +++ b/src/util/format.ts @@ -260,7 +260,7 @@ export function getTooltipMarker(inOpt: ColorString | GetTooltipMarkerOpt, extra * and `module:echarts/util/number#parseDate`. * @inner */ -export function formatTime(tpl: string, value: unknown, isUTC: boolean) { +export function formatTime(tpl: string, value: unknown, isUTC?: boolean) { if (__DEV__) { deprecateReplaceLog('echarts.format.formatTime', 'echarts.time.format'); } diff --git a/src/util/types.ts b/src/util/types.ts index ab1a6b1b2b..e6ccb589fa 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -377,6 +377,7 @@ export type ParsedValueNumeric = number | OrdinalNumber; export type ScaleDataValue = ParsedValueNumeric | OrdinalRawValue | Date; export interface ScaleTick { + level?: number, value: number }; export interface TimeScaleTick extends ScaleTick { @@ -937,29 +938,29 @@ export type SymbolOffsetCallback = (rawValue: any, params: T) => string | num * Mixin of option set to control the element symbol. * Include type of symbol, and size of symbol. */ -export interface SymbolOptionMixin { +export interface SymbolOptionMixin { /** * type of symbol, like `cirlce`, `rect`, or custom path and image. */ - symbol?: string | (unknown extends T ? never : SymbolCallback) + symbol?: string | (T extends never ? never : SymbolCallback) /** * Size of symbol. */ - symbolSize?: number | number[] | (unknown extends T ? never : SymbolSizeCallback) + symbolSize?: number | number[] | (T extends never ? never : SymbolSizeCallback) - symbolRotate?: number | (unknown extends T ? never : SymbolRotateCallback) + symbolRotate?: number | (T extends never ? never : SymbolRotateCallback) symbolKeepAspect?: boolean - symbolOffset?: string | number | (string | number)[] | (unknown extends T ? never : SymbolOffsetCallback) + symbolOffset?: string | number | (string | number)[] | (T extends never ? never : SymbolOffsetCallback) } /** * ItemStyleOption is a most common used set to config element styles. * It includes both fill and stroke style. */ -export interface ItemStyleOption extends ShadowOptionMixin, BorderOptionMixin { - color?: ZRColor +export interface ItemStyleOption extends ShadowOptionMixin, BorderOptionMixin { + color?: ZRColor | (TCbParams extends never ? never : ((params: TCbParams) => ZRColor)) opacity?: number decal?: DecalObject | 'none' } @@ -1498,15 +1499,16 @@ export type BlurScope = 'coordinateSystem' | 'series' | 'global'; */ export type InnerFocus = DefaultEmphasisFocus | ArrayLike | Dictionary>; -export interface DefaultExtraStateOpts { - emphasis: any - select: any - blur: any +export interface DefaultStatesMixin { + // FIXME + emphasis?: any + select?: any + blur?: any } export type DefaultEmphasisFocus = 'none' | 'self' | 'series'; -export interface DefaultExtraEmpasisState { +export interface DefaultStatesMixinEmpasis { /** * self: Focus self and blur all others. * series: Focus series and blur all other series. @@ -1514,19 +1516,20 @@ export interface DefaultExtraEmpasisState { focus?: DefaultEmphasisFocus } -interface ExtraStateOptsBase { - emphasis?: { - focus?: string - }, - select?: any - blur?: any +export interface StatesMixinBase { + emphasis?: unknown + select?: unknown + blur?: unknown } -export interface StatesOptionMixin { +export interface StatesOptionMixin< + StateOption, + StatesMixin extends StatesMixinBase +> { /** * Emphasis states */ - emphasis?: StateOption & ExtraStateOpts['emphasis'] & { + emphasis?: StateOption & StatesMixin['emphasis'] & { /** * Scope of blurred element when focus. * @@ -1541,11 +1544,11 @@ export interface StatesOptionMixin extends + StateOption = unknown, + StatesMixin extends StatesMixinBase = DefaultStatesMixin +> extends ComponentOption, AnimationOptionMixin, ColorPaletteOptionMixin, - StatesOptionMixin + StatesOptionMixin { mainType?: 'series' diff --git a/test/bar-polar-basic.html b/test/bar-polar-basic.html deleted file mode 100644 index 3dab721de3..0000000000 --- a/test/bar-polar-basic.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - -

click axis labe should console log

-
- - - diff --git a/test/bar-polar-clockwise.html b/test/bar-polar-clockwise.html new file mode 100644 index 0000000000..d799c3fbbf --- /dev/null +++ b/test/bar-polar-clockwise.html @@ -0,0 +1,106 @@ + + + + + + + + + + + + +

click axis label should console log

+

click update button, sectors should be in the same order

+ +
+

clockwise: true

+
+
+
+

clockwise: false

+
+
+ + + diff --git a/test/line-extraneous.html b/test/line-animation-update.html similarity index 97% rename from test/line-extraneous.html rename to test/line-animation-update.html index e749696cfe..514559e836 100644 --- a/test/line-extraneous.html +++ b/test/line-animation-update.html @@ -42,6 +42,7 @@
+
+ + diff --git a/test/line-animation.html b/test/line-animation.html index 011fd69d83..9ce3c38af2 100644 --- a/test/line-animation.html +++ b/test/line-animation.html @@ -59,6 +59,8 @@

Default Label Animation

Label Animation with animationDelay callback

+

Line Animation should be continued when calling setOption again.

+
@@ -400,6 +402,42 @@

Label Animation with animationDelay callback

+ + \ No newline at end of file diff --git a/test/line-case.html b/test/line-case.html index 066715e43e..4c2bbb873d 100644 --- a/test/line-case.html +++ b/test/line-case.html @@ -447,9 +447,6 @@ 'Test case from https://github.com/apache/echarts/issues/15380' ], option: option - // height: 300, - // buttons: [{text: 'btn-txt', onclick: function () {}}], - // recordCanvas: true, }); }); diff --git a/test/linear-gradient.html b/test/line-visual2.html similarity index 55% rename from test/linear-gradient.html rename to test/line-visual2.html index 5ec82008ac..44f2b9ba2d 100644 --- a/test/linear-gradient.html +++ b/test/line-visual2.html @@ -40,6 +40,7 @@
+
@@ -151,8 +152,7 @@ 'The series with log axis should be rendered without errors in console', 'https://github.com/apache/echarts/issues/14601' ], - option: option, - height: 600 + option: option }); }) @@ -367,6 +367,133 @@ + diff --git a/test/marker-case.html b/test/marker-case.html new file mode 100644 index 0000000000..756fa49dda --- /dev/null +++ b/test/marker-case.html @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json index 28341e7bd1..37aea6b857 100644 --- a/test/runTest/actions/__meta__.json +++ b/test/runTest/actions/__meta__.json @@ -21,6 +21,7 @@ "bar-label-rotation": 2, "bar-large": 2, "bar-overflow-time-plot": 3, + "bar-polar-clockwise": 1, "bar-polar-multi-series": 1, "bar-polar-multi-series-radial": 1, "bar-polar-null-data-radial": 1, @@ -110,10 +111,11 @@ "legend-visualMapColor": 2, "line": 1, "line-animation": 1, + "line-animation-update": 3, "line-boldWhenHover": 1, "line-crash": 1, "line-endLabel": 1, - "line-extraneous": 2, + "line-visual2": 1, "lines-bus": 1, "map": 3, "map-contour": 2, diff --git a/test/runTest/actions/bar-polar-clockwise.json b/test/runTest/actions/bar-polar-clockwise.json new file mode 100644 index 0000000000..9dbcc44e11 --- /dev/null +++ b/test/runTest/actions/bar-polar-clockwise.json @@ -0,0 +1 @@ +[{"name":"Action 1","ops":[{"type":"mousedown","time":1234,"x":34,"y":125},{"type":"mouseup","time":1393,"x":34,"y":125},{"time":1394,"delay":400,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1631523020115}] \ No newline at end of file diff --git a/test/runTest/actions/line-extraneous.json b/test/runTest/actions/line-animation-update.json similarity index 57% rename from test/runTest/actions/line-extraneous.json rename to test/runTest/actions/line-animation-update.json index 455c58f692..79b547e948 100644 --- a/test/runTest/actions/line-extraneous.json +++ b/test/runTest/actions/line-animation-update.json @@ -1 +1 @@ -[{"name":"Action 1","ops":[{"type":"mousedown","time":596,"x":28,"y":93},{"type":"mouseup","time":698,"x":28,"y":93},{"time":699,"delay":2000,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568042380534},{"name":"Action 2","ops":[{"type":"mousedown","time":736,"x":218,"y":184},{"type":"mouseup","time":827,"x":218,"y":184},{"time":828,"delay":400,"type":"screenshot-auto"}],"scrollY":416,"scrollX":0,"timestamp":1617082817083}] \ No newline at end of file +[{"name":"Action 1","ops":[{"type":"mousedown","time":596,"x":28,"y":93},{"type":"mouseup","time":698,"x":28,"y":93},{"time":699,"delay":2000,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568042380534},{"name":"Action 2","ops":[{"type":"mousedown","time":736,"x":218,"y":184},{"type":"mouseup","time":827,"x":218,"y":184},{"time":828,"delay":400,"type":"screenshot-auto"}],"scrollY":416,"scrollX":0,"timestamp":1617082817083},{"name":"Action 3","ops":[{"type":"mousedown","time":325,"x":110,"y":174},{"type":"mouseup","time":433,"x":110,"y":174},{"time":434,"delay":400,"type":"screenshot-auto"}],"scrollY":915,"scrollX":0,"timestamp":1631687531615}] \ No newline at end of file diff --git a/test/runTest/actions/line-visual2.json b/test/runTest/actions/line-visual2.json new file mode 100644 index 0000000000..f5286b345a --- /dev/null +++ b/test/runTest/actions/line-visual2.json @@ -0,0 +1 @@ +[{"name":"Action 1","ops":[{"type":"mousedown","time":425,"x":45,"y":185},{"type":"mouseup","time":524,"x":45,"y":185},{"time":525,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":737,"x":45,"y":185},{"type":"mousemove","time":937,"x":112,"y":182},{"type":"mousemove","time":1174,"x":116,"y":182},{"type":"mousedown","time":1709,"x":116,"y":182},{"type":"mouseup","time":1770,"x":116,"y":182},{"time":1771,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":2054,"x":116,"y":182},{"type":"mousemove","time":2254,"x":190,"y":179},{"type":"mousemove","time":2461,"x":223,"y":178},{"type":"mousedown","time":2963,"x":223,"y":178},{"type":"mouseup","time":3045,"x":223,"y":178},{"time":3046,"delay":400,"type":"screenshot-auto"}],"scrollY":1345,"scrollX":0,"timestamp":1631512007469}] \ No newline at end of file diff --git a/test/runTest/server.js b/test/runTest/server.js index 1e224ac22c..f74b001956 100644 --- a/test/runTest/server.js +++ b/test/runTest/server.js @@ -229,7 +229,7 @@ async function start() { let {io} = serve(); const stableVersions = await fetchVersions(false); - const nightlyVersions = await fetchVersions(true); + const nightlyVersions = (await fetchVersions(true)).slice(0, 100); stableVersions.unshift('local'); nightlyVersions.unshift('local'); diff --git a/test/timeScale.html b/test/timeScale.html index cf9bfc2cbb..47370f0e8b 100644 --- a/test/timeScale.html +++ b/test/timeScale.html @@ -153,6 +153,7 @@ min: 'dataMin', max: 'dataMax', axisLabel: { + hideOverlap: true } } ], diff --git a/test/tooltip-lag-glitch.html b/test/tooltip-lag-glitch.html new file mode 100644 index 0000000000..d5cf6a0874 --- /dev/null +++ b/test/tooltip-lag-glitch.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + +
+
+ + + + + diff --git a/test/types/basic.ts b/test/types/basic.ts index 19bfa6761f..fd39e4d0f4 100644 --- a/test/types/basic.ts +++ b/test/types/basic.ts @@ -26,7 +26,12 @@ const chart: echarts.EChartsType = echarts.init(dom); const option: echarts.EChartsOption = { series: [{ - type: 'bar' + type: 'bar', + emphasis: { + itemStyle: { + color: 'red' + } + } }] }; chart.setOption(option); \ No newline at end of file