UNPKG

di-echarts

Version:

Apache ECharts is a powerful, interactive charting and data visualization library for browser

249 lines (221 loc) 9.21 kB
/* * 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 * as echarts from '../../../core/echarts'; import * as zrUtil from 'zrender/src/core/util'; import {ToolboxFeature, ToolboxFeatureOption, ToolboxFeatureModel} from '../featureManager'; import { SeriesOption, ECUnitOption } from '../../../util/types'; import GlobalModel from '../../../model/Global'; import ExtensionAPI from '../../../core/ExtensionAPI'; import SeriesModel from '../../../model/Series'; import { SINGLE_REFERRING } from '../../../util/model'; const INNER_STACK_KEYWORD = '__ec_magicType_stack__' as const; const ICON_TYPES = ['line', 'bar', 'stack'] as const; // stack and tiled appears in pair for the title const TITLE_TYPES = ['line', 'bar', 'stack', 'tiled'] as const; const radioTypes = [ ['line', 'bar'], ['stack'] ] as const; type IconType = typeof ICON_TYPES[number]; type TitleType = typeof TITLE_TYPES[number]; export interface ToolboxMagicTypeFeatureOption extends ToolboxFeatureOption { type?: IconType[] /** * Icon group */ icon?: {[key in IconType]?: string} title?: {[key in TitleType]?: string} // TODO LineSeriesOption, BarSeriesOption option?: {[key in IconType]?: SeriesOption} /** * Map of seriesType: seriesIndex */ seriesIndex?: { line?: number bar?: number } } class MagicType extends ToolboxFeature<ToolboxMagicTypeFeatureOption> { getIcons() { const model = this.model; const availableIcons = model.get('icon'); const icons: ToolboxMagicTypeFeatureOption['icon'] = {}; zrUtil.each(model.get('type'), function (type) { if (availableIcons[type]) { icons[type] = availableIcons[type]; } }); return icons; } static getDefaultOption(ecModel: GlobalModel) { const defaultOption: ToolboxMagicTypeFeatureOption = { show: true, type: [], // Icon group icon: { line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4', bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7', // eslint-disable-next-line stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z' // jshint ignore:line }, // `line`, `bar`, `stack`, `tiled` title: ecModel.getLocaleModel().get(['toolbox', 'magicType', 'title']), option: {}, seriesIndex: {} }; return defaultOption; } onclick(ecModel: GlobalModel, api: ExtensionAPI, type: IconType) { const model = this.model; const seriesIndex = model.get(['seriesIndex', type as 'line' | 'bar']); // Not supported magicType if (!seriesOptGenreator[type]) { return; } const newOption: ECUnitOption = { series: [] }; const generateNewSeriesTypes = function (seriesModel: SeriesModel<MegicTypeSeriesOption>) { const seriesType = seriesModel.subType; const seriesId = seriesModel.id; const newSeriesOpt = seriesOptGenreator[type]( seriesType, seriesId, seriesModel, model ); if (newSeriesOpt) { // PENDING If merge original option? zrUtil.defaults(newSeriesOpt, seriesModel.option); (newOption.series as SeriesOption[]).push(newSeriesOpt); } // Modify boundaryGap const coordSys = seriesModel.coordinateSystem; if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) { const categoryAxis = coordSys.getAxesByScale('ordinal')[0]; if (categoryAxis) { const axisDim = categoryAxis.dim; const axisType = axisDim + 'Axis'; const axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0]; const axisIndex = axisModel.componentIndex; newOption[axisType] = newOption[axisType] || []; for (let i = 0; i <= axisIndex; i++) { (newOption[axisType] as any)[axisIndex] = (newOption[axisType] as any)[axisIndex] || {}; } (newOption[axisType] as any)[axisIndex].boundaryGap = type === 'bar'; } } }; zrUtil.each(radioTypes, function (radio) { if (zrUtil.indexOf(radio, type) >= 0) { zrUtil.each(radio, function (item) { model.setIconStatus(item, 'normal'); }); } }); model.setIconStatus(type, 'emphasis'); ecModel.eachComponent( { mainType: 'series', query: seriesIndex == null ? null : { seriesIndex: seriesIndex } }, generateNewSeriesTypes ); let newTitle; let currentType = type as TitleType; // Change title of stack if (type === 'stack') { // use titles in model instead of ecModel // as stack and tiled appears in pair, just flip them // no need of checking stack state newTitle = zrUtil.merge({ stack: model.option.title.tiled, tiled: model.option.title.stack }, model.option.title); if (model.get(['iconStatus', type]) !== 'emphasis') { currentType = 'tiled'; } } api.dispatchAction({ type: 'changeMagicType', currentType: currentType, newOption: newOption, newTitle: newTitle, featureName: 'magicType' }); } } type MegicTypeSeriesOption = SeriesOption & { // TODO: TYPE More specified series option stack?: boolean | string data?: unknown[] markPoint?: unknown markLine?: unknown }; type SeriesOptGenreator = ( seriesType: string, seriesId: string, seriesModel: SeriesModel<MegicTypeSeriesOption>, model: ToolboxFeatureModel<ToolboxMagicTypeFeatureOption> ) => SeriesOption; const seriesOptGenreator: Record<IconType, SeriesOptGenreator> = { 'line': function (seriesType, seriesId, seriesModel, model) { if (seriesType === 'bar') { return zrUtil.merge({ id: seriesId, type: 'line', // Preserve data related option data: seriesModel.get('data'), stack: seriesModel.get('stack'), markPoint: seriesModel.get('markPoint'), markLine: seriesModel.get('markLine') }, model.get(['option', 'line']) || {}, true); } }, 'bar': function (seriesType, seriesId, seriesModel, model) { if (seriesType === 'line') { return zrUtil.merge({ id: seriesId, type: 'bar', // Preserve data related option data: seriesModel.get('data'), stack: seriesModel.get('stack'), markPoint: seriesModel.get('markPoint'), markLine: seriesModel.get('markLine') }, model.get(['option', 'bar']) || {}, true); } }, 'stack': function (seriesType, seriesId, seriesModel, model) { const isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD; if (seriesType === 'line' || seriesType === 'bar') { model.setIconStatus('stack', isStack ? 'normal' : 'emphasis'); return zrUtil.merge({ id: seriesId, stack: isStack ? '' : INNER_STACK_KEYWORD }, model.get(['option', 'stack']) || {}, true); } } }; // TODO: SELF REGISTERED. echarts.registerAction({ type: 'changeMagicType', event: 'magicTypeChanged', update: 'prepareAndUpdate' }, function (payload, ecModel) { ecModel.mergeOption(payload.newOption); }); export default MagicType;