提交 cc81a49b 编写于 作者: 1 100pah

feature:

(1) support toolbox dataZoom works on the second setOption.
(2) change the mechanism of "internal component" to support adding them dynamically.
(3) uniform the "get referring component".
(4) support toolbox dataZoom use axis id to refer axis (previously only axisIndex can be used).
(5) remove the support to restore on the second setOption temporarily.
上级 a3d29cf6
......@@ -150,7 +150,7 @@ class DataZoomModel<Opts extends DataZoomOption = DataZoomOption> extends Compon
type = DataZoomModel.type;
static dependencies = [
'xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series'
'xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series', 'toolbox'
];
......
......@@ -52,21 +52,21 @@ export function isCoordSupported(coordType: string) {
return indexOf(COORDS, coordType) >= 0;
}
export function getAxisMainType(axisDim: DimensionName): DataZoomAxisMainType {
export function getAxisMainType(axisDim: DataZoomAxisDimension): DataZoomAxisMainType {
if (__DEV__) {
assert(axisDim);
}
return axisDim + 'Axis' as DataZoomAxisMainType;
}
export function getAxisIndexPropName(axisDim: DimensionName): DataZoomAxisIndexPropName {
export function getAxisIndexPropName(axisDim: DataZoomAxisDimension): DataZoomAxisIndexPropName {
if (__DEV__) {
assert(axisDim);
}
return axisDim + 'AxisIndex' as DataZoomAxisIndexPropName;
}
export function getAxisIdPropName(axisDim: DimensionName): DataZoomAxisIdPropName {
export function getAxisIdPropName(axisDim: DataZoomAxisDimension): DataZoomAxisIdPropName {
if (__DEV__) {
assert(axisDim);
}
......
......@@ -19,7 +19,6 @@
// TODO depends on DataZoom and Brush
import * as echarts from '../../../echarts';
import * as zrUtil from 'zrender/src/core/util';
import BrushController, { BrushControllerEvents, BrushDimensionMinMax } from '../../helper/BrushController';
import BrushTargetManager, { BrushTargetInfoCartesian2D } from '../../helper/BrushTargetManager';
......@@ -36,19 +35,27 @@ import {
} from '../featureManager';
import GlobalModel from '../../../model/Global';
import ExtensionAPI from '../../../ExtensionAPI';
import { Payload, ECUnitOption, Dictionary } from '../../../util/types';
import { Payload, Dictionary, ComponentOption } from '../../../util/types';
import Cartesian2D from '../../../coord/cartesian/Cartesian2D';
import CartesianAxisModel from '../../../coord/cartesian/AxisModel';
import DataZoomModel, { DataZoomOption } from '../../dataZoom/DataZoomModel';
import { DataZoomPayloadBatchItem } from '../../dataZoom/helper';
import { ModelFinderObject, ModelFinderIndexQuery, normalizeToArray } from '../../../util/model';
import { ToolboxOption } from '../ToolboxModel';
import DataZoomModel from '../../dataZoom/DataZoomModel';
import {
DataZoomPayloadBatchItem, DataZoomAxisDimension, getAxisIndexPropName,
getAxisIdPropName, getAxisMainType
} from '../../dataZoom/helper';
import {
ModelFinderObject, ModelFinderIndexQuery, makeInternalComponentId,
queryReferringComponents, ModelFinderIdQuery
} from '../../../util/model';
import ToolboxModel from '../ToolboxModel';
import { registerInternalOptionCreator } from '../../../model/internalComponentCreator';
import Model from '../../../model/Model';
const dataZoomLang = lang.toolbox.dataZoom;
const each = zrUtil.each;
// Spectial component id start with \0ec\0, see echarts/model/Global.js~hasInnerId
const DATA_ZOOM_ID_BASE = '\0_ec_\0toolbox-dataZoom_';
const DATA_ZOOM_ID_BASE = makeInternalComponentId('toolbox-dataZoom_');
const ICON_TYPES = ['zoom', 'back'] as const;
type IconType = typeof ICON_TYPES[number];
......@@ -60,8 +67,10 @@ interface ToolboxDataZoomFeatureOption extends ToolboxFeatureOption {
// TODO: TYPE Use type in dataZoom
filterMode?: 'filter' | 'weakFilter' | 'empty' | 'none'
// Backward compat: false means 'none'
xAxisIndex?: ModelFinderIndexQuery | false
yAxisIndex?: ModelFinderIndexQuery | false
xAxisIndex?: ModelFinderIndexQuery
yAxisIndex?: ModelFinderIndexQuery
xAxisId?: ModelFinderIdQuery
yAxisId?: ModelFinderIdQuery
}
type ToolboxDataZoomFeatureModel = ToolboxFeatureModel<ToolboxDataZoomFeatureOption>;
......@@ -134,7 +143,7 @@ class DataZoomFeature extends ToolboxFeature<ToolboxDataZoomFeatureOption> {
}
else {
setBatch(
({lineX: 'x', lineY: 'y'})[brushType as 'lineX' | 'lineY'],
({lineX: 'x', lineY: 'y'} as const)[brushType as 'lineX' | 'lineY'],
coordSys,
coordRange as BrushDimensionMinMax
);
......@@ -145,7 +154,7 @@ class DataZoomFeature extends ToolboxFeature<ToolboxDataZoomFeatureOption> {
this._dispatchZoomAction(snapshot);
function setBatch(dimName: string, coordSys: Cartesian2D, minMax: number[]) {
function setBatch(dimName: DataZoomAxisDimension, coordSys: Cartesian2D, minMax: number[]) {
const axis = coordSys.getAxis(dimName);
const axisModel = axis.model;
const dataZoomModel = findDataZoom(dimName, axisModel, ecModel);
......@@ -166,7 +175,9 @@ class DataZoomFeature extends ToolboxFeature<ToolboxDataZoomFeatureOption> {
});
}
function findDataZoom(dimName: string, axisModel: CartesianAxisModel, ecModel: GlobalModel): DataZoomModel {
function findDataZoom(
dimName: DataZoomAxisDimension, axisModel: CartesianAxisModel, ecModel: GlobalModel
): DataZoomModel {
let found;
ecModel.eachComponent({mainType: 'dataZoom', subType: 'select'}, function (dzModel: DataZoomModel) {
const has = dzModel.getAxisModel(dimName, axisModel.componentIndex);
......@@ -290,79 +301,61 @@ function updateZoomBtnStatus(
);
}
registerFeature('dataZoom', DataZoomFeature);
// Create special dataZoom option for select
// FIXME consider the case of merge option, where axes options are not exists.
echarts.registerPreprocessor(function (option: ECUnitOption) {
if (!option) {
registerInternalOptionCreator('dataZoom', function (ecModel: GlobalModel): ComponentOption[] {
const toolboxModel = ecModel.getComponent('toolbox', 0) as ToolboxModel;
if (!toolboxModel) {
return;
}
const dzFeatureModel = toolboxModel.getModel(['feature', 'dataZoom'] as any);
const dzOptions = [] as ComponentOption[];
addInternalOptionForAxis(ecModel, dzOptions, 'x', dzFeatureModel);
addInternalOptionForAxis(ecModel, dzOptions, 'y', dzFeatureModel);
const dataZoomOpts = option.dataZoom = normalizeToArray(option.dataZoom) as DataZoomOption[];
let toolboxOpt = option.toolbox as ToolboxOption;
if (toolboxOpt) {
// Assume there is only one toolbox
if (zrUtil.isArray(toolboxOpt)) {
toolboxOpt = toolboxOpt[0];
}
return dzOptions;
});
if (toolboxOpt && toolboxOpt.feature) {
const dataZoomOpt = toolboxOpt.feature.dataZoom as ToolboxDataZoomFeatureOption;
// FIXME: If add dataZoom when setOption in merge mode,
// no axis info to be added. See `test/dataZoom-extreme.html`
addForAxis('xAxis', dataZoomOpt);
addForAxis('yAxis', dataZoomOpt);
}
function addInternalOptionForAxis(
ecModel: GlobalModel,
dzOptions: ComponentOption[],
axisDim: 'x' | 'y',
dzFeatureModel: Model<ToolboxDataZoomFeatureOption>
): void {
const axisIndexPropName = getAxisIndexPropName(axisDim) as 'xAxisIndex' | 'yAxisIndex';
const axisIdPropName = getAxisIdPropName(axisDim) as 'xAxisId' | 'yAxisId';
const axisMainType = getAxisMainType(axisDim);
let axisIndexOption = dzFeatureModel.get(axisIndexPropName, true);
const axisIdOption = dzFeatureModel.get(axisIdPropName, true);
if (axisIndexOption == null && axisIdOption == null) {
axisIndexOption = 'all';
}
function addForAxis(axisName: 'xAxis' | 'yAxis', dataZoomOpt: ToolboxDataZoomFeatureOption): void {
if (!dataZoomOpt) {
return;
}
// Try not to modify model, because it is not merged yet.
const axisIndicesName = axisName + 'Index' as 'xAxisIndex' | 'yAxisIndex';
let givenAxisIndices = dataZoomOpt[axisIndicesName];
if (givenAxisIndices != null
&& givenAxisIndices !== 'all'
&& !zrUtil.isArray(givenAxisIndices)
) {
givenAxisIndices = (givenAxisIndices === false || givenAxisIndices === 'none') ? [] : [givenAxisIndices];
const queryResult = queryReferringComponents(
ecModel,
axisMainType,
{
index: axisIndexOption,
id: axisIdOption
}
);
forEachComponent(axisName, function (axisOpt: unknown, axisIndex: number) {
if (givenAxisIndices != null
&& givenAxisIndices !== 'all'
&& zrUtil.indexOf(givenAxisIndices as number[], axisIndex) === -1
) {
return;
}
const newOpt = {
type: 'select',
$fromToolbox: true,
// Default to be filter
filterMode: dataZoomOpt.filterMode || 'filter',
// Id for merge mapping.
id: DATA_ZOOM_ID_BASE + axisName + axisIndex
} as Dictionary<unknown>;
// FIXME
// Only support one axis now.
newOpt[axisIndicesName] = axisIndex;
dataZoomOpts.push(newOpt);
});
}
each(queryResult.models, function (axisModel) {
const axisIndex = axisModel.componentIndex;
const newOpt = {
type: 'select',
$fromToolbox: true,
// Default to be filter
filterMode: dzFeatureModel.get('filterMode', true) || 'filter',
// Id for merge mapping.
id: DATA_ZOOM_ID_BASE + axisMainType + axisIndex
} as Dictionary<unknown>;
newOpt[axisIndexPropName] = axisIndex;
dzOptions.push(newOpt);
});
}
function forEachComponent(mainType: string, cb: (axisOpt: unknown, axisIndex: number) => void) {
let opts = option[mainType];
if (!zrUtil.isArray(opts)) {
opts = opts ? [opts] : [];
}
each(opts, cb);
}
});
export default DataZoomFeature;
......@@ -29,7 +29,7 @@ import {
ClassManager,
mountExtend
} from '../util/clazz';
import {makeInner} from '../util/model';
import {makeInner, ModelFinderIndexQuery, queryReferringComponents, ModelFinderIdQuery} from '../util/model';
import * as layout from '../util/layout';
import GlobalModel from './Global';
import {
......@@ -45,6 +45,7 @@ const inner = makeInner<{
defaultOption: ComponentOption
}, ComponentModel>();
class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Model<Opt> {
// [Caution]: Becuase this class or desecendants can be used as `XXX.extend(subProto)`,
......@@ -269,6 +270,7 @@ class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Mode
/**
* Notice: always force to input param `useDefault` in case that forget to consider it.
* The same behavior as `modelUtil.parseFinder`.
*
* @param useDefault In many cases like series refer axis and axis refer grid,
* If axis index / axis id not specified, use the first target as default.
......@@ -276,34 +278,22 @@ class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Mode
*/
getReferringComponents(mainType: ComponentMainType, useDefault: boolean): {
// Always be array rather than null/undefined, which is convenient to use.
models: ComponentModel[],
// Whether index or id are specified in option.
specified: boolean
models: ComponentModel[];
// Whether target compoent specified
specified: boolean;
} {
const indexKey = (mainType + 'Index') as keyof Opt;
const idKey = (mainType + 'Id') as keyof Opt;
const indexOption = this.get(indexKey, true);
const idOption = this.get(idKey, true);
const models = this.ecModel.queryComponents({
mainType: mainType,
index: indexOption as any,
id: idOption as any
});
// `queryComponents` will return all components if
// both index and id are null/undefined
let specified = true;
if (indexOption == null && idOption == null) {
specified = false;
// Use the first as default if `useDefault`.
models.length = (useDefault && models.length) ? 1 : 0;
}
return {
models: models,
specified: specified
};
return queryReferringComponents(
this.ecModel,
mainType,
{
index: this.get(indexKey, true) as unknown as ModelFinderIndexQuery,
id: this.get(idKey, true) as unknown as ModelFinderIdQuery
},
useDefault
);
}
getBoxLayoutParams() {
......@@ -324,6 +314,7 @@ class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Mode
static hasClass: ClassManager['hasClass'];
static registerSubTypeDefaulter: componentUtil.SubTypeDefaulterManager['registerSubTypeDefaulter'];
}
// Reset ComponentModel.extend, add preConstruct.
......@@ -373,4 +364,5 @@ function getDependencies(componentType: string): string[] {
return deps;
}
export default ComponentModel;
......@@ -57,6 +57,7 @@ import {
} from '../util/types';
import OptionManager from './OptionManager';
import Scheduler from '../stream/Scheduler';
import { concatInternalOptions } from './internalComponentCreator';
export interface GlobalModelSetOptionOpts {
replaceMerge: ComponentMainType | ComponentMainType[];
......@@ -247,7 +248,7 @@ class GlobalModel extends Model<ECUnitOption> {
// we trade it as it is declared in option as `{xxx: []}`. Because:
// (1) for normal merge, `{xxx: null/undefined}` are the same meaning as `{xxx: []}`.
// (2) some preprocessor may convert some of `{xxx: null/undefined}` to `{xxx: []}`.
replaceMergeMainTypeMap.each(function (b, mainTypeInReplaceMerge) {
replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) {
if (!newCmptTypeMap.get(mainTypeInReplaceMerge)) {
newCmptTypes.push(mainTypeInReplaceMerge);
newCmptTypeMap.set(mainTypeInReplaceMerge, true);
......@@ -266,7 +267,9 @@ class GlobalModel extends Model<ECUnitOption> {
this: GlobalModel,
mainType: ComponentMainType
): void {
const newCmptOptionList = modelUtil.normalizeToArray(newOption[mainType]);
const newCmptOptionList = concatInternalOptions(
this, mainType, modelUtil.normalizeToArray(newOption[mainType])
);
const oldCmptList = componentsMap.get(mainType);
const mergeMode = (replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType))
......@@ -407,12 +410,22 @@ class GlobalModel extends Model<ECUnitOption> {
}
/**
* @param idx 0 by default
* @param idx If not specified, return the first one.
*/
getComponent(mainType: string, idx?: number): ComponentModel {
getComponent(mainType: ComponentMainType, idx?: number): ComponentModel {
const list = this._componentsMap.get(mainType);
if (list) {
return list[idx || 0];
const cmpt = list[idx || 0];
if (cmpt) {
return cmpt;
}
else if (idx == null) {
for (let i = 0; i < list.length; i++) {
if (list[i]) {
return list[i];
}
}
}
}
}
......@@ -862,7 +875,7 @@ function queryByIdOrName<T extends { id?: string, name?: string }>(
idOrName: string | number | (string | number)[],
cmpts: T[]
): T[] {
// Here is a break from echarts4: string and number-like string are
// Here is a break from echarts4: string and number are
// traded as equal.
if (isArray(idOrName)) {
const keyMap = createHashMap<boolean>(idOrName);
......
......@@ -69,7 +69,7 @@ class OptionManager {
private _optionBackup: ParsedRawOption;
private _fakeCmptsMap: FakeComponentsMap;
// private _fakeCmptsMap: FakeComponentsMap;
private _newBaseOption: ECUnitOption;
......@@ -115,16 +115,21 @@ class OptionManager {
// For setOption at second time (using merge mode);
if (optionBackup) {
// FIXME
// the restore merge solution is essentially incorrect.
// the mapping can not be 100% consistent with ecModel, which probably brings
// potential bug!
// The first merge is delayed, becuase in most cases, users do not call `setOption` twice.
let fakeCmptsMap = this._fakeCmptsMap;
if (!fakeCmptsMap) {
fakeCmptsMap = this._fakeCmptsMap = createHashMap();
mergeToBackupOption(fakeCmptsMap, null, optionBackup.baseOption, null);
}
// let fakeCmptsMap = this._fakeCmptsMap;
// if (!fakeCmptsMap) {
// fakeCmptsMap = this._fakeCmptsMap = createHashMap();
// mergeToBackupOption(fakeCmptsMap, null, optionBackup.baseOption, null);
// }
mergeToBackupOption(
fakeCmptsMap, optionBackup.baseOption, newParsedOption.baseOption, opt
);
// mergeToBackupOption(
// fakeCmptsMap, optionBackup.baseOption, newParsedOption.baseOption, opt
// );
// For simplicity, timeline options and media options do not support merge,
// that is, if you `setOption` twice and both has timeline options, the latter
......@@ -373,76 +378,76 @@ function indicesEquals(indices1: number[], indices2: number[]): boolean {
* When "resotre" action triggered, model from `componentActionModel` will be discarded
* instead of recreating the "ecModel" from the "_optionBackup".
*/
function mergeToBackupOption(
fakeCmptsMap: FakeComponentsMap,
// `tarOption` Can be null/undefined, means init
tarOption: ECUnitOption,
newOption: ECUnitOption,
// Can be null/undefined
opt: InnerSetOptionOpts
): void {
newOption = newOption || {} as ECUnitOption;
const notInit = !!tarOption;
each(newOption, function (newOptsInMainType, mainType) {
if (newOptsInMainType == null) {
return;
}
if (!ComponentModel.hasClass(mainType)) {
if (tarOption) {
tarOption[mainType] = merge(tarOption[mainType], newOptsInMainType, true);
}
}
else {
const oldTarOptsInMainType = notInit ? normalizeToArray(tarOption[mainType]) : null;
const oldFakeCmptsInMainType = fakeCmptsMap.get(mainType) || [];
const resultTarOptsInMainType = notInit ? (tarOption[mainType] = [] as ComponentOption[]) : null;
const resultFakeCmptsInMainType = fakeCmptsMap.set(mainType, []);
const mappingResult = mappingToExists(
oldFakeCmptsInMainType,
normalizeToArray(newOptsInMainType),
(opt && opt.replaceMergeMainTypeMap.get(mainType)) ? 'replaceMerge' : 'normalMerge'
);
setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel as ComponentModelConstructor);
each(mappingResult, function (resultItem, index) {
// The same logic as `Global.ts#_mergeOption`.
let fakeCmpt = resultItem.existing;
const newOption = resultItem.newOption;
const keyInfo = resultItem.keyInfo;
let fakeCmptOpt;
if (!newOption) {
fakeCmptOpt = oldTarOptsInMainType[index];
}
else {
if (fakeCmpt && fakeCmpt.subType === keyInfo.subType) {
fakeCmpt.name = keyInfo.name;
if (notInit) {
fakeCmptOpt = merge(oldTarOptsInMainType[index], newOption, true);
}
}
else {
fakeCmpt = extend({}, keyInfo);
if (notInit) {
fakeCmptOpt = clone(newOption);
}
}
}
if (fakeCmpt) {
notInit && resultTarOptsInMainType.push(fakeCmptOpt);
resultFakeCmptsInMainType.push(fakeCmpt);
}
else {
notInit && resultTarOptsInMainType.push(void 0);
resultFakeCmptsInMainType.push(void 0);
}
});
}
});
}
// function mergeToBackupOption(
// fakeCmptsMap: FakeComponentsMap,
// // `tarOption` Can be null/undefined, means init
// tarOption: ECUnitOption,
// newOption: ECUnitOption,
// // Can be null/undefined
// opt: InnerSetOptionOpts
// ): void {
// newOption = newOption || {} as ECUnitOption;
// const notInit = !!tarOption;
// each(newOption, function (newOptsInMainType, mainType) {
// if (newOptsInMainType == null) {
// return;
// }
// if (!ComponentModel.hasClass(mainType)) {
// if (tarOption) {
// tarOption[mainType] = merge(tarOption[mainType], newOptsInMainType, true);
// }
// }
// else {
// const oldTarOptsInMainType = notInit ? normalizeToArray(tarOption[mainType]) : null;
// const oldFakeCmptsInMainType = fakeCmptsMap.get(mainType) || [];
// const resultTarOptsInMainType = notInit ? (tarOption[mainType] = [] as ComponentOption[]) : null;
// const resultFakeCmptsInMainType = fakeCmptsMap.set(mainType, []);
// const mappingResult = mappingToExists(
// oldFakeCmptsInMainType,
// normalizeToArray(newOptsInMainType),
// (opt && opt.replaceMergeMainTypeMap.get(mainType)) ? 'replaceMerge' : 'normalMerge'
// );
// setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel as ComponentModelConstructor);
// each(mappingResult, function (resultItem, index) {
// // The same logic as `Global.ts#_mergeOption`.
// let fakeCmpt = resultItem.existing;
// const newOption = resultItem.newOption;
// const keyInfo = resultItem.keyInfo;
// let fakeCmptOpt;
// if (!newOption) {
// fakeCmptOpt = oldTarOptsInMainType[index];
// }
// else {
// if (fakeCmpt && fakeCmpt.subType === keyInfo.subType) {
// fakeCmpt.name = keyInfo.name;
// if (notInit) {
// fakeCmptOpt = merge(oldTarOptsInMainType[index], newOption, true);
// }
// }
// else {
// fakeCmpt = extend({}, keyInfo);
// if (notInit) {
// fakeCmptOpt = clone(newOption);
// }
// }
// }
// if (fakeCmpt) {
// notInit && resultTarOptsInMainType.push(fakeCmptOpt);
// resultFakeCmptsInMainType.push(fakeCmpt);
// }
// else {
// notInit && resultTarOptsInMainType.push(void 0);
// resultFakeCmptsInMainType.push(void 0);
// }
// });
// }
// });
// }
export default OptionManager;
/*
* 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.
*/
import GlobalModel from './Global';
import { ComponentOption, ComponentMainType } from '../util/types';
import { createHashMap, assert } from 'zrender/src/core/util';
import { __DEV__ } from '../config';
import { isComponentIdInternal } from '../util/model';
// PNEDING:
// (1) Only Internal usage at present, do not export to uses.
// (2) "Internal components" are generated internally during the `Global.ts#_mergeOption`.
// It is added since echarts 3.
// (3) Why keep supporting "internal component" in global model rather than
// make each type components manage their models themselves?
// Because a protential feature that reproduce a chart from a diffferent chart instance
// might be useful in some BI analysis scenario, where the entire state need to be
// retrieved from the current chart instance. So we'd bettern manage the all of the
// state universally.
// (4) Internal component always merged in "replaceMerge" approach, that is, if the existing
// internal components does not matched by a new option with the same id, it will be
// removed.
// (5) In `InternalOptionCreator`, only the previous component models (dependencies) can be read.
interface InternalOptionCreator {
(ecModel: GlobalModel): ComponentOption[]
}
const internalOptionCreatorMap = createHashMap<InternalOptionCreator, string>();
export function registerInternalOptionCreator(
mainType: ComponentMainType, creator: InternalOptionCreator
) {
assert(internalOptionCreatorMap.get(mainType) == null && creator);
internalOptionCreatorMap.set(mainType, creator);
}
export function concatInternalOptions(
ecModel: GlobalModel,
mainType: ComponentMainType,
newCmptOptionList: ComponentOption[]
): ComponentOption[] {
const internalOptionCreator = internalOptionCreatorMap.get(mainType);
if (!internalOptionCreator) {
return newCmptOptionList;
}
const internalOptions = internalOptionCreator(ecModel);
if (!internalOptions) {
return newCmptOptionList;
}
if (__DEV__) {
for (let i = 0; i < internalOptions.length; i++) {
assert(isComponentIdInternal(internalOptions[i]));
}
}
return newCmptOptionList.concat(internalOptions);
}
此差异已折叠。
......@@ -38,7 +38,8 @@ under the License.
<div id="refer_by_id"></div>
<div id="auto_axis_second_setOption"></div>
<div id="auto_axis_second_setOption_normal_dz"></div>
<div id="auto_axis_second_setOption_only_toolbox_dz"></div>
......@@ -172,7 +173,7 @@ under the License.
}]
};
var chart = testHelper.create(echarts, 'auto_axis_second_setOption', {
var chart = testHelper.create(echarts, 'auto_axis_second_setOption_normal_dz', {
title: [
'two grids, each has two xAxis.',
'dataZoom should auto **control all of the two xAxis of the first** grid.',
......@@ -251,6 +252,146 @@ under the License.
<script>
require(['echarts'], function (echarts) {
var option;
option = {
toolbox: {
left: 'center',
feature: {
dataZoom: {}
}
},
grid: [{
bottom: '60%'
}, {
id: 'gb',
top: '60%'
}],
xAxis: [{
type: 'category'
}, {
type: 'category'
}, {
id: 'xb0',
type: 'category',
gridIndex: 1
}, {
id: 'xb1',
type: 'category',
gridIndex: 1
}],
yAxis: [{
}, {
id: 'yb',
gridIndex: 1
}],
series: [{
type: 'line',
data: [[333, 22], [666, 44]]
}, {
type: 'line',
xAxisIndex: 1,
data: [[88888, 52], [99999, 74]]
}, {
id: 'sb0',
type: 'line',
xAxisIndex: 2,
yAxisIndex: 1,
data: [[63, 432], [98, 552]]
}, {
id: 'sb1',
type: 'line',
xAxisIndex: 3,
yAxisIndex: 1,
data: [[87654, 1432], [56789, 1552]]
}]
};
var chart = testHelper.create(echarts, 'auto_axis_second_setOption_only_toolbox_dz', {
title: [
'[Only toolbox dataZoom] two grids, each has two xAxis.',
'toolbox zoom should work on **all grids**.',
'Click btn "remove the first grid".',
'toolbox zoom should work only on **the second grids**.',
'Click btn "addback the first grid".',
'toolbox zoom should work on **all grids**.',
'Click btn "remove all grids".',
'Should **no error**.',
'Check toolbox zoom should **not work on the original area**.',
'Click btn "addback the first grid".',
'toolbox zoom should work only on the **the first grids**.',
],
option: option,
height: 350,
buttons: [{
text: 'remove the first grid',
onclick: function () {
chart.setOption({
grid: [{
id: 'gb',
}],
xAxis: [{
id: 'xb0',
}, {
id: 'xb1',
}],
yAxis: [{
id: 'yb'
}],
series: [{
id: 'sb0',
}, {
id: 'sb1',
}]
}, { replaceMerge: ['grid', 'xAxis', 'yAxis', 'series'] });
}
}, {
text: 'addback the first grid',
onclick: function () {
chart.setOption({
grid: [{
bottom: '60%'
}],
xAxis: [{
}, {
}],
yAxis: [{
}],
series: [{
type: 'line',
data: [[333, 22], [666, 44]]
}, {
type: 'line',
xAxisIndex: 1,
data: [[88888, 52], [99999, 74]]
}]
});
}
}, {
text: 'remove all grids',
onclick: function () {
chart.setOption({
grid: [],
xAxis: [],
yAxis: [],
series: []
}, { replaceMerge: ['grid', 'xAxis', 'yAxis', 'series'] });
}
}]
});
});
</script>
</body>
</html>
......@@ -60,6 +60,7 @@ under the License.
<div class="chart" id="main-specify-x-axis"></div>
<div id="main0"></div>
<div id="main-refer-by-axis-id"></div>
<script>
......@@ -735,5 +736,90 @@ under the License.
</script>
<script>
require(['echarts'/*, 'map/js/china' */], function (echarts) {
var option;
option = {
toolbox: {
feature: {
dataZoom: {
xAxisId: 'xr',
yAxisId: ['yl0', 'yl1']
}
}
},
legend: {},
grid: [{
right: '60%',
bottom: '60%',
}, {
id: 'gr',
left: '60%',
bottom: '60%',
}, {
id: 'gb',
top: '60%',
}],
xAxis: [{
}, {
id: 'xr',
gridId: 'gr'
}, {
id: 'xb',
gridId: 'gb'
}],
yAxis: [{
id: 'yl0'
}, {
id: 'yl1'
}, {
id: 'yr',
gridId: 'gr'
}, {
id: 'yb',
gridId: 'gb'
}],
series: [{
type: 'line',
yAxisId: 'yl0',
data: [[11, 12], [22, 45], [33, 76]]
}, {
type: 'line',
yAxisId: 'yl1',
data: [[11, 2212], [22, 3345], [33, 4476]]
}, {
type: 'line',
xAxisId: 'xr',
yAxisId: 'yr',
data: [[45, 65], [13, 25], [56, 71]]
}, {
type: 'line',
xAxisId: 'xb',
yAxisId: 'yb',
data: [[123, 654], [234, 321], [345, 812]]
}]
};
var chart = testHelper.create(echarts, 'main-refer-by-axis-id', {
title: [
'Test toolbox datazoom refer with axis id',
'left grid: toolbox only work **on two yAxis**',
'right grid: toolbox only work **on xAxis**',
'bottom grid: toolbox **does not work**'
],
option: option
// height: 300,
// buttons: [{text: 'btn-txt', onclick: function () {}}],
// recordCanvas: true,
});
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册