echarts styleCompat 源码

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

echarts styleCompat 代码

文件路径:/src/util/styleCompat.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 { Dictionary, ZRStyleProps } from './types';
import { ElementTextConfig } from 'zrender/src/Element';
import { TextStyleProps, TextStylePropsPart, TextProps } from 'zrender/src/graphic/Text';
import { each, hasOwn } from 'zrender/src/core/util';
import { ItemStyleProps } from '../model/mixin/itemStyle';

export interface LegacyStyleProps {
    legacy?: boolean
}

const deprecatedLogs = {} as Dictionary<boolean>;

/**
 * Whether need to call `convertEC4CompatibleStyle`.
 */
export function isEC4CompatibleStyle(
    style: ZRStyleProps & LegacyStyleProps,
    elType: string,
    hasOwnTextContentOption: boolean,
    hasOwnTextConfig: boolean
): boolean {
    // Since echarts5, `RectText` is separated from its host element and style.text
    // does not exist any more. The compat work brings some extra burden on performance.
    // So we provide:
    // `legacy: true` force make compat.
    // `legacy: false`, force do not compat.
    // `legacy` not set: auto detect wheter legacy.
    //     But in this case we do not compat (difficult to detect and rare case):
    //     Becuse custom series and graphic component support "merge", users may firstly
    //     only set `textStrokeWidth` style or secondly only set `text`.
    return style && (
        style.legacy
        || (
            style.legacy !== false
            && !hasOwnTextContentOption
            && !hasOwnTextConfig
            && elType !== 'tspan'
            // Difficult to detect whether legacy for a "text" el.
            && (elType === 'text' || hasOwn(style, 'text'))
        )
    );
}

/**
 * `EC4CompatibleStyle` is style that might be in echarts4 format or echarts5 format.
 * @param hostStyle The properties might be modified.
 * @return If be text el, `textContentStyle` and `textConfig` will not be retured.
 *         Otherwise a `textContentStyle` and `textConfig` will be created, whose props area
 *         retried from the `hostStyle`.
 */
export function convertFromEC4CompatibleStyle(hostStyle: ZRStyleProps, elType: string, isNormal: boolean): {
    textContent: TextProps & {type: string},
    textConfig: ElementTextConfig
} {
    const srcStyle = hostStyle as Dictionary<any>;
    let textConfig: ElementTextConfig;
    let textContent: TextProps & {type: string};

    let textContentStyle: TextStyleProps;
    if (elType === 'text') {
        textContentStyle = srcStyle;
    }
    else {
        textContentStyle = {};
        hasOwn(srcStyle, 'text') && (textContentStyle.text = srcStyle.text);
        hasOwn(srcStyle, 'rich') && (textContentStyle.rich = srcStyle.rich);
        hasOwn(srcStyle, 'textFill') && (textContentStyle.fill = srcStyle.textFill);
        hasOwn(srcStyle, 'textStroke') && (textContentStyle.stroke = srcStyle.textStroke);
        hasOwn(srcStyle, 'fontFamily') && (textContentStyle.fontFamily = srcStyle.fontFamily);
        hasOwn(srcStyle, 'fontSize') && (textContentStyle.fontSize = srcStyle.fontSize);
        hasOwn(srcStyle, 'fontStyle') && (textContentStyle.fontStyle = srcStyle.fontStyle);
        hasOwn(srcStyle, 'fontWeight') && (textContentStyle.fontWeight = srcStyle.fontWeight);

        textContent = {
            type: 'text',
            style: textContentStyle,
            // ec4 do not support rectText trigger.
            // And when text postion is different in normal and emphasis
            // => hover text trigger emphasis;
            // => text position changed, leave mouse pointer immediately;
            // That might cause state incorrect.
            silent: true
        };
        textConfig = {};
        const hasOwnPos = hasOwn(srcStyle, 'textPosition');
        if (isNormal) {
            textConfig.position = hasOwnPos ? srcStyle.textPosition : 'inside';
        }
        else {
            hasOwnPos && (textConfig.position = srcStyle.textPosition);
        }
        hasOwn(srcStyle, 'textPosition') && (textConfig.position = srcStyle.textPosition);
        hasOwn(srcStyle, 'textOffset') && (textConfig.offset = srcStyle.textOffset);
        hasOwn(srcStyle, 'textRotation') && (textConfig.rotation = srcStyle.textRotation);
        hasOwn(srcStyle, 'textDistance') && (textConfig.distance = srcStyle.textDistance);
    }

    convertEC4CompatibleRichItem(textContentStyle, hostStyle);

    each(textContentStyle.rich, function (richItem) {
        convertEC4CompatibleRichItem(richItem as TextStyleProps, richItem);
    });

    return {
        textConfig: textConfig,
        textContent: textContent
    };
}

/**
 * The result will be set to `out`.
 */
function convertEC4CompatibleRichItem(out: TextStylePropsPart, richItem: Dictionary<any>): void {
    if (!richItem) {
        return;
    }
    // (1) For simplicity, make textXXX properties (deprecated since ec5) has
    // higher priority. For example, consider in ec4 `borderColor: 5, textBorderColor: 10`
    // on a rect means `borderColor: 4` on the rect and `borderColor: 10` on an attached
    // richText in ec5.
    // (2) `out === richItem` if and only if `out` is text el or rich item.
    // So we can overwite existing props in `out` since textXXX has higher priority.
    richItem.font = richItem.textFont || richItem.font;
    hasOwn(richItem, 'textStrokeWidth') && (out.lineWidth = richItem.textStrokeWidth);
    hasOwn(richItem, 'textAlign') && (out.align = richItem.textAlign);
    hasOwn(richItem, 'textVerticalAlign') && (out.verticalAlign = richItem.textVerticalAlign);
    hasOwn(richItem, 'textLineHeight') && (out.lineHeight = richItem.textLineHeight);
    hasOwn(richItem, 'textWidth') && (out.width = richItem.textWidth);
    hasOwn(richItem, 'textHeight') && (out.height = richItem.textHeight);
    hasOwn(richItem, 'textBackgroundColor') && (out.backgroundColor = richItem.textBackgroundColor);
    hasOwn(richItem, 'textPadding') && (out.padding = richItem.textPadding);
    hasOwn(richItem, 'textBorderColor') && (out.borderColor = richItem.textBorderColor);
    hasOwn(richItem, 'textBorderWidth') && (out.borderWidth = richItem.textBorderWidth);
    hasOwn(richItem, 'textBorderRadius') && (out.borderRadius = richItem.textBorderRadius);
    hasOwn(richItem, 'textBoxShadowColor') && (out.shadowColor = richItem.textBoxShadowColor);
    hasOwn(richItem, 'textBoxShadowBlur') && (out.shadowBlur = richItem.textBoxShadowBlur);
    hasOwn(richItem, 'textBoxShadowOffsetX') && (out.shadowOffsetX = richItem.textBoxShadowOffsetX);
    hasOwn(richItem, 'textBoxShadowOffsetY') && (out.shadowOffsetY = richItem.textBoxShadowOffsetY);
}

/**
 * Convert to pure echarts4 format style.
 * `itemStyle` will be modified, added with ec4 style properties from
 * `textStyle` and `textConfig`.
 *
 * [Caveat]: For simplicity, `insideRollback` in ec4 does not compat, where
 * `styleEmphasis: {textFill: 'red'}` will remove the normal auto added stroke.
 */
export function convertToEC4StyleForCustomSerise(
    itemStl: ItemStyleProps,
    txStl: TextStyleProps,
    txCfg: ElementTextConfig
): ZRStyleProps {

    const out = itemStl as Dictionary<unknown>;

    // See `custom.ts`, a trick to set extra `textPosition` firstly.
    out.textPosition = out.textPosition || txCfg.position || 'inside';
    txCfg.offset != null && (out.textOffset = txCfg.offset);
    txCfg.rotation != null && (out.textRotation = txCfg.rotation);
    txCfg.distance != null && (out.textDistance = txCfg.distance);

    const isInside = (out.textPosition as string).indexOf('inside') >= 0;
    const hostFill = itemStl.fill || '#000';

    convertToEC4RichItem(out, txStl);

    const textFillNotSet = out.textFill == null;
    if (isInside) {
        if (textFillNotSet) {
            out.textFill = txCfg.insideFill || '#fff';
            !out.textStroke && txCfg.insideStroke && (out.textStroke = txCfg.insideStroke);
            !out.textStroke && (out.textStroke = hostFill);
            out.textStrokeWidth == null && (out.textStrokeWidth = 2);
        }
    }
    else {
        if (textFillNotSet) {
            out.textFill = itemStl.fill || txCfg.outsideFill || '#000';
        }
        !out.textStroke && txCfg.outsideStroke && (out.textStroke = txCfg.outsideStroke);
    }

    out.text = txStl.text;
    out.rich = txStl.rich;

    each(txStl.rich, function (richItem) {
        convertToEC4RichItem(richItem as Dictionary<unknown>, richItem);
    });

    return out;
}

function convertToEC4RichItem(out: Dictionary<unknown>, richItem: TextStylePropsPart) {
    if (!richItem) {
        return;
    }

    hasOwn(richItem, 'fill') && (out.textFill = richItem.fill);
    hasOwn(richItem, 'stroke') && (out.textStroke = richItem.fill);

    hasOwn(richItem, 'lineWidth') && (out.textStrokeWidth = richItem.lineWidth);
    hasOwn(richItem, 'font') && (out.font = richItem.font);
    hasOwn(richItem, 'fontStyle') && (out.fontStyle = richItem.fontStyle);
    hasOwn(richItem, 'fontWeight') && (out.fontWeight = richItem.fontWeight);
    hasOwn(richItem, 'fontSize') && (out.fontSize = richItem.fontSize);
    hasOwn(richItem, 'fontFamily') && (out.fontFamily = richItem.fontFamily);

    hasOwn(richItem, 'align') && (out.textAlign = richItem.align);
    hasOwn(richItem, 'verticalAlign') && (out.textVerticalAlign = richItem.verticalAlign);
    hasOwn(richItem, 'lineHeight') && (out.textLineHeight = richItem.lineHeight);
    hasOwn(richItem, 'width') && (out.textWidth = richItem.width);
    hasOwn(richItem, 'height') && (out.textHeight = richItem.height);

    hasOwn(richItem, 'backgroundColor') && (out.textBackgroundColor = richItem.backgroundColor);
    hasOwn(richItem, 'padding') && (out.textPadding = richItem.padding);
    hasOwn(richItem, 'borderColor') && (out.textBorderColor = richItem.borderColor);
    hasOwn(richItem, 'borderWidth') && (out.textBorderWidth = richItem.borderWidth);
    hasOwn(richItem, 'borderRadius') && (out.textBorderRadius = richItem.borderRadius);

    hasOwn(richItem, 'shadowColor') && (out.textBoxShadowColor = richItem.shadowColor);
    hasOwn(richItem, 'shadowBlur') && (out.textBoxShadowBlur = richItem.shadowBlur);
    hasOwn(richItem, 'shadowOffsetX') && (out.textBoxShadowOffsetX = richItem.shadowOffsetX);
    hasOwn(richItem, 'shadowOffsetY') && (out.textBoxShadowOffsetY = richItem.shadowOffsetY);

    hasOwn(richItem, 'textShadowColor') && (out.textShadowColor = richItem.textShadowColor);
    hasOwn(richItem, 'textShadowBlur') && (out.textShadowBlur = richItem.textShadowBlur);
    hasOwn(richItem, 'textShadowOffsetX') && (out.textShadowOffsetX = richItem.textShadowOffsetX);
    hasOwn(richItem, 'textShadowOffsetY') && (out.textShadowOffsetY = richItem.textShadowOffsetY);
}

export function warnDeprecated(deprecated: string, insteadApproach: string): void {
    if (__DEV__) {
        const key = deprecated + '^_^' + insteadApproach;
        if (!deprecatedLogs[key]) {
            console.warn(`[ECharts] DEPRECATED: "${deprecated}" has been deprecated. ${insteadApproach}`);
            deprecatedLogs[key] = true;
        }
    }
}

相关信息

echarts 源码目录

相关文章

echarts ECEventProcessor 源码

echarts KDTree 源码

echarts animation 源码

echarts clazz 源码

echarts component 源码

echarts conditionalExpression 源码

echarts decal 源码

echarts event 源码

echarts format 源码

echarts graphic 源码

0  赞