/*
|
* 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 zrUtil from 'zrender/src/core/util';
|
import * as visualSolution from '../../visual/visualSolution';
|
import Model from '../../model/Model';
|
import { ComponentOption, ZRColor, VisualOptionFixed } from '../../util/types';
|
import ComponentModel from '../../model/Component';
|
import BrushTargetManager from '../helper/BrushTargetManager';
|
import {
|
BrushCoverCreatorConfig, BrushMode, BrushCoverConfig, BrushDimensionMinMax,
|
BrushAreaRange, BrushTypeUncertain, BrushType
|
} from '../helper/BrushController';
|
import { ModelFinderObject } from '../../util/model';
|
|
const DEFAULT_OUT_OF_BRUSH_COLOR = '#ddd';
|
|
/**
|
* The input to define brush areas.
|
* (1) Can be created by user when calling dispatchAction.
|
* (2) Can be created by `BrushController`
|
* for brush behavior. area params are picked from `cover.__brushOptoin`.
|
* In `BrushController`, "covers" are create or updated for each "area".
|
*/
|
export interface BrushAreaParam extends ModelFinderObject {
|
brushType: BrushCoverConfig['brushType'];
|
id?: BrushCoverConfig['id'];
|
range?: BrushCoverConfig['range'];
|
|
// `ModelFinderObject` and `panelId` are used to match "coord sys target"
|
// for this area. See `BrushTargetManager['setInputRanges']`.
|
// If panelId specified, use it to match panel firstly.
|
// If not specified, use `ModelFinderObject` to match panel,
|
// and then assign the panelId to the area.
|
// If finally no panel matched, panelId keep null/undefined,
|
// means global area.
|
// PENDING: this feature should better belong to BrushController
|
// rather than brush component?
|
panelId?: BrushCoverConfig['panelId'];
|
|
// Range in local coordinates of certain coordinate system.
|
// When dispatchAction, if the area is the global area,
|
// `range` is the input. if the area is not the global area,
|
// `coordRange` is the input, and then convert to `range`.
|
coordRange?: BrushAreaRange;
|
// coord ranges, used in multiple cartesian in one grid.
|
// Only for output to users.
|
coordRanges?: BrushAreaRange[];
|
|
__rangeOffset?: {
|
offset: BrushDimensionMinMax[] | BrushDimensionMinMax,
|
xyMinMax: BrushDimensionMinMax[]
|
}
|
}
|
|
/**
|
* Generated by `brushModel.setAreas`, which merges
|
* `area: BrushAreaParam` and `brushModel.option: BrushOption`.
|
* See `generateBrushOption`.
|
*/
|
export interface BrushAreaParamInternal extends BrushAreaParam {
|
brushMode: BrushMode;
|
brushStyle: BrushCoverConfig['brushStyle'];
|
transformable: BrushCoverConfig['transformable'];
|
removeOnClick: BrushCoverConfig['removeOnClick'];
|
z: BrushCoverConfig['z'];
|
|
__rangeOffset?: {
|
offset: BrushDimensionMinMax | BrushDimensionMinMax[];
|
xyMinMax: BrushDimensionMinMax[]
|
};
|
}
|
|
export type BrushToolboxIconType = BrushType | 'keep' | 'clear';
|
|
export interface BrushOption extends ComponentOption, ModelFinderObject {
|
mainType?: 'brush';
|
|
// Default value see preprocessor.
|
toolbox?: BrushToolboxIconType[];
|
|
// Series indices array, broadcast using dataIndex.
|
// or 'all', which means all series. 'none'/null/undefined means no series.
|
brushLink?: number[] | 'all' | 'none';
|
|
// Throttle in brushSelected event. 'fixRate' or 'debounce'.
|
// If null, no throttle. Valid only in the first brush component
|
throttleType?: 'fixRate' | 'debounce';
|
// Unit: ms, 0 means every event will be triggered.
|
throttleDelay?: number;
|
|
inBrush?: VisualOptionFixed;
|
outOfBrush?: VisualOptionFixed;
|
|
// --- Current painting brush options ---
|
// Default type of brush
|
brushType?: BrushTypeUncertain;
|
brushStyle?: {
|
borderWidth?: number;
|
color?: ZRColor;
|
borderColor?: ZRColor;
|
};
|
transformable?: boolean;
|
brushMode?: BrushMode;
|
removeOnClick?: boolean;
|
}
|
|
class BrushModel extends ComponentModel<BrushOption> {
|
|
static type = 'brush' as const;
|
type = BrushModel.type;
|
|
static dependencies = ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series'];
|
|
static defaultOption: BrushOption = {
|
seriesIndex: 'all',
|
brushType: 'rect',
|
brushMode: 'single',
|
transformable: true,
|
brushStyle: {
|
borderWidth: 1,
|
color: 'rgba(210,219,238,0.3)',
|
borderColor: '#D2DBEE'
|
},
|
throttleType: 'fixRate',
|
throttleDelay: 0,
|
removeOnClick: true,
|
z: 10000
|
};
|
|
/**
|
* @readOnly
|
*/
|
areas: BrushAreaParamInternal[] = [];
|
|
/**
|
* Current activated brush type.
|
* If null, brush is inactived.
|
* see module:echarts/component/helper/BrushController
|
* @readOnly
|
*/
|
brushType: BrushTypeUncertain;
|
|
/**
|
* Current brush painting area settings.
|
* @readOnly
|
*/
|
brushOption: BrushCoverCreatorConfig = {} as BrushCoverCreatorConfig;
|
|
// Inject
|
brushTargetManager: BrushTargetManager;
|
|
|
optionUpdated(newOption: BrushOption, isInit: boolean): void {
|
const thisOption = this.option;
|
|
!isInit && visualSolution.replaceVisualOption(
|
thisOption, newOption, ['inBrush', 'outOfBrush']
|
);
|
|
const inBrush = thisOption.inBrush = thisOption.inBrush || {};
|
// Always give default visual, consider setOption at the second time.
|
thisOption.outOfBrush = thisOption.outOfBrush || {color: DEFAULT_OUT_OF_BRUSH_COLOR};
|
|
if (!inBrush.hasOwnProperty('liftZ')) {
|
// Bigger than the highlight z lift, otherwise it will
|
// be effected by the highlight z when brush.
|
inBrush.liftZ = 5;
|
}
|
}
|
|
/**
|
* If `areas` is null/undefined, range state remain.
|
*/
|
setAreas(areas?: BrushAreaParam[]): void {
|
if (__DEV__) {
|
zrUtil.assert(zrUtil.isArray(areas));
|
zrUtil.each(areas, function (area) {
|
zrUtil.assert(area.brushType, 'Illegal areas');
|
});
|
}
|
|
// If areas is null/undefined, range state remain.
|
// This helps user to dispatchAction({type: 'brush'}) with no areas
|
// set but just want to get the current brush select info from a `brush` event.
|
if (!areas) {
|
return;
|
}
|
|
this.areas = zrUtil.map(areas, function (area) {
|
return generateBrushOption(this.option, area);
|
}, this);
|
}
|
|
/**
|
* Set the current painting brush option.
|
*/
|
setBrushOption(brushOption: BrushCoverCreatorConfig): void {
|
this.brushOption = generateBrushOption(this.option, brushOption);
|
this.brushType = this.brushOption.brushType;
|
}
|
|
}
|
|
|
function generateBrushOption(
|
option: BrushOption, brushOption: BrushAreaParam
|
): BrushAreaParamInternal;
|
function generateBrushOption(
|
option: BrushOption, brushOption: BrushCoverCreatorConfig
|
): BrushCoverCreatorConfig;
|
function generateBrushOption(
|
option: BrushOption, brushOption: BrushAreaParam | BrushCoverCreatorConfig
|
): BrushAreaParamInternal | BrushCoverCreatorConfig {
|
return zrUtil.merge(
|
{
|
brushType: option.brushType,
|
brushMode: option.brushMode,
|
transformable: option.transformable,
|
brushStyle: new Model(option.brushStyle).getItemStyle(),
|
removeOnClick: option.removeOnClick,
|
z: option.z
|
},
|
brushOption,
|
true
|
);
|
}
|
|
export default BrushModel;
|