echarts MarkerModel 源码

  • 2022-10-20
  • 浏览 (557)

echarts MarkerModel 代码

文件路径:/src/component/marker/MarkerModel.ts

/*
* 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 env from 'zrender/src/core/env';
import { DataFormatMixin } from '../../model/mixin/dataFormat';
import ComponentModel from '../../model/Component';
import SeriesModel from '../../model/Series';
import {
    DisplayStateHostOption,
    ComponentOption,
    AnimationOptionMixin,
    Dictionary,
    CommonTooltipOption,
    ScaleDataValue
} from '../../util/types';
import Model from '../../model/Model';
import GlobalModel from '../../model/Global';
import SeriesData from '../../data/SeriesData';
import { makeInner, defaultEmphasis } from '../../util/model';
import { createTooltipMarkup } from '../tooltip/tooltipMarkup';

function fillLabel(opt: DisplayStateHostOption) {
    defaultEmphasis(opt, 'label', ['show']);
}

export type MarkerStatisticType = 'average' | 'min' | 'max' | 'median';

/**
 * Option to specify where to put the marker.
 */
export interface MarkerPositionOption {
    // Priority: x/y > coord(xAxis, yAxis) > type

    // Absolute position, px or percent string
    x?: number | string
    y?: number | string

    /**
     * Coord on any coordinate system
     */
    coord?: (ScaleDataValue | MarkerStatisticType)[]

    // On cartesian coordinate system
    xAxis?: ScaleDataValue
    yAxis?: ScaleDataValue

    // On polar coordinate system
    radiusAxis?: ScaleDataValue
    angleAxis?: ScaleDataValue

    // Use statistic method
    type?: MarkerStatisticType
    /**
     * When using statistic method with type.
     * valueIndex and valueDim can be specify which dim the statistic is used on.
     */
    valueIndex?: number
    valueDim?: string


    /**
     * Value to be displayed as label. Totally optional
     */
    value?: string | number
}

export interface MarkerOption extends ComponentOption, AnimationOptionMixin {

    silent?: boolean

    data?: unknown[]

    tooltip?: CommonTooltipOption<unknown> & {
        trigger?: 'item' | 'axis' | boolean | 'none'
    }
}

// { [componentType]: MarkerModel }
const inner = makeInner<Dictionary<MarkerModel>, SeriesModel>();

abstract class MarkerModel<Opts extends MarkerOption = MarkerOption> extends ComponentModel<Opts> {

    static type = 'marker';
    type = MarkerModel.type;

    /**
     * If marker model is created by self from series
     */
    createdBySelf = false;

    static readonly dependencies = ['series', 'grid', 'polar', 'geo'];

    __hostSeries: SeriesModel;

    private _data: SeriesData;

    /**
     * @overrite
     */
    init(option: Opts, parentModel: Model, ecModel: GlobalModel) {

        if (__DEV__) {
            if (this.type === 'marker') {
                throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.');
            }
        }
        this.mergeDefaultAndTheme(option, ecModel);
        this._mergeOption(option, ecModel, false, true);
    }

    isAnimationEnabled(): boolean {
        if (env.node) {
            return false;
        }

        const hostSeries = this.__hostSeries;
        return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled();
    }

    /**
     * @overrite
     */
    mergeOption(newOpt: Opts, ecModel: GlobalModel) {
        this._mergeOption(newOpt, ecModel, false, false);
    }

    _mergeOption(newOpt: Opts, ecModel: GlobalModel, createdBySelf?: boolean, isInit?: boolean) {
        const componentType = this.mainType;
        if (!createdBySelf) {
            ecModel.eachSeries(function (seriesModel) {

                // mainType can be markPoint, markLine, markArea
                const markerOpt = seriesModel.get(
                    this.mainType as any, true
                ) as Opts;

                let markerModel = inner(seriesModel)[componentType];
                if (!markerOpt || !markerOpt.data) {
                    inner(seriesModel)[componentType] = null;
                    return;
                }
                if (!markerModel) {
                    if (isInit) {
                        // Default label emphasis `position` and `show`
                        fillLabel(markerOpt);
                    }
                    zrUtil.each(markerOpt.data, function (item) {
                        // FIXME Overwrite fillLabel method ?
                        if (item instanceof Array) {
                            fillLabel(item[0]);
                            fillLabel(item[1]);
                        }
                        else {
                            fillLabel(item);
                        }
                    });

                    markerModel = this.createMarkerModelFromSeries(
                        markerOpt, this, ecModel
                    );
                    // markerModel = new ImplementedMarkerModel(
                    //     markerOpt, this, ecModel
                    // );

                    zrUtil.extend(markerModel, {
                        mainType: this.mainType,
                        // Use the same series index and name
                        seriesIndex: seriesModel.seriesIndex,
                        name: seriesModel.name,
                        createdBySelf: true
                    });

                    markerModel.__hostSeries = seriesModel;
                }
                else {
                    markerModel._mergeOption(markerOpt, ecModel, true);
                }
                inner(seriesModel)[componentType] = markerModel;
            }, this);
        }
    }

    formatTooltip(
        dataIndex: number,
        multipleSeries: boolean,
        dataType: string
    ) {
        const data = this.getData();
        const value = this.getRawValue(dataIndex);
        const itemName = data.getName(dataIndex);

        return createTooltipMarkup('section', {
            header: this.name,
            blocks: [createTooltipMarkup('nameValue', {
                name: itemName,
                value: value,
                noName: !itemName,
                noValue: value == null
            })]
        });
    }

    getData(): SeriesData<this> {
        return this._data as SeriesData<this>;
    }

    setData(data: SeriesData) {
        this._data = data;
    }

    /**
     * Create slave marker model from series.
     */
    abstract createMarkerModelFromSeries(
        markerOpt: Opts,
        masterMarkerModel: MarkerModel,
        ecModel: GlobalModel
    ): MarkerModel;

    static getMarkerModelFromSeries(
        seriesModel: SeriesModel,
        // Support three types of markers. Strict check.
        componentType: 'markLine' | 'markPoint' | 'markArea'
    ) {
        return inner(seriesModel)[componentType];
    }
}

interface MarkerModel<Opts extends MarkerOption = MarkerOption> extends DataFormatMixin {}
zrUtil.mixin(MarkerModel, DataFormatMixin.prototype);

export default MarkerModel;

相关信息

echarts 源码目录

相关文章

echarts MarkAreaModel 源码

echarts MarkAreaView 源码

echarts MarkLineModel 源码

echarts MarkLineView 源码

echarts MarkPointModel 源码

echarts MarkPointView 源码

echarts MarkerView 源码

echarts checkMarkerInSeries 源码

echarts installMarkArea 源码

echarts installMarkLine 源码

0  赞