You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by ov...@apache.org on 2021/03/17 10:10:07 UTC

[echarts] 05/10: WIP(legend): refactor and use fixed line width

This is an automated email from the ASF dual-hosted git repository.

ovilia pushed a commit to branch fix-legend
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit 39d4e530f29db2129cf154dd1b23226c686bb2d3
Author: Ovilia <zw...@gmail.com>
AuthorDate: Tue Mar 16 15:50:39 2021 +0800

    WIP(legend): refactor and use fixed line width
---
 src/chart/line/install.ts           |  21 ++--
 src/component/legend/LegendModel.ts |  78 ++++++++++--
 src/component/legend/LegendView.ts  | 230 +++++++++++++++++++++++-------------
 src/model/mixin/lineStyle.ts        |   2 +-
 4 files changed, 227 insertions(+), 104 deletions(-)

diff --git a/src/chart/line/install.ts b/src/chart/line/install.ts
index 35147e2..b5dd22f 100644
--- a/src/chart/line/install.ts
+++ b/src/chart/line/install.ts
@@ -39,19 +39,18 @@ export function install(registers: EChartsExtensionInstallRegisters) {
         seriesType: 'line',
         reset: function (seriesModel: LineSeriesModel) {
             // Visual coding for legend
-            const lineStyle = seriesModel.getModel('lineStyle');
-            const itemStyle = seriesModel.getModel('itemStyle');
-            const color = itemStyle ? itemStyle.get('color') : null;
-            const borderColor = itemStyle ? itemStyle.get('borderColor') : null;//TODO
-            let lineColor = lineStyle && lineStyle.get('color') || color;
-
+            const lineStyle = seriesModel.getModel('lineStyle').getLineStyle();
+            const itemStyle = seriesModel.getModel('itemStyle').getItemStyle();
+            const color = itemStyle && itemStyle.fill;
+            console.log(itemStyle, lineStyle);
             if (lineStyle) {
-                seriesModel.getData().setVisual('legendSymbolStyle', {
-                    borderColor,
-                    horizontalLineColor: lineColor,
-                    horizontalLineWidth: lineStyle.get('width')
-                });
+                lineStyle.stroke = lineStyle.stroke || color;
             }
+
+            seriesModel.getData().setVisual('legendSymbolStyle', {
+                itemStyle,
+                lineStyle
+            });
         }
     });
 
diff --git a/src/component/legend/LegendModel.ts b/src/component/legend/LegendModel.ts
index e603ce2..b595dc1 100644
--- a/src/component/legend/LegendModel.ts
+++ b/src/component/legend/LegendModel.ts
@@ -26,14 +26,17 @@ import {
     BoxLayoutOptionMixin,
     BorderOptionMixin,
     ColorString,
-    ItemStyleOption,
     LabelOption,
     LayoutOrient,
     CommonTooltipOption,
-    ZRColor
+    ZRColor,
+    DecalObject,
+    ZRLineType
 } from '../../util/types';
 import { Dictionary } from 'zrender/src/core/types';
 import GlobalModel from '../../model/Global';
+import { ItemStyleProps } from '../../model/mixin/itemStyle';
+import { LineStyleProps } from './../../model/mixin/lineStyle';
 
 type LegendDefaultSelectorOptionsProps = {
     type: string;
@@ -60,6 +63,38 @@ export interface LegendSelectorButtonOption {
     title?: string
 }
 
+export interface LegendItemStyleOption {
+    color?: ZRColor | 'inherit'
+    opacity?: number | 'inherit'
+    decal?: DecalObject | 'none' | 'inherit'
+    shadowBlur?: number | 'inherit'
+    shadowColor?: ColorString | 'inherit'
+    shadowOffsetX?: number | 'inherit'
+    shadowOffsetY?: number | 'inherit'
+    borderColor?: ZRColor | 'inherit'
+    borderWidth?: number | 'inherit'
+    borderType?: ZRLineType | 'inherit'
+    borderCap?: CanvasLineCap | 'inherit'
+    borderJoin?: CanvasLineJoin | 'inherit'
+    borderDashOffset?: number | 'inherit'
+    borderMiterLimit?: number | 'inherit'
+}
+
+export interface LegendLineStyleOption {
+    width?: number | 'inherit' | 'auto'
+    color?: ZRColor | 'inherit'
+    opacity?: number | 'inherit'
+    type?: ZRLineType | 'inherit'
+    cap?: CanvasLineCap | 'inherit'
+    join?: CanvasLineJoin | 'inherit'
+    dashOffset?: number | 'inherit'
+    miterLimit?: number | 'inherit'
+    shadowBlur?: number | 'inherit'
+    shadowColor?: ColorString | 'inherit'
+    shadowOffsetX?: number | 'inherit'
+    shadowOffsetY?: number | 'inherit'
+}
+
 export interface LegendStyleOption {
     /**
      * Icon of the legend items.
@@ -81,7 +116,9 @@ export interface LegendStyleOption {
      */
     formatter?: string | ((name: string) => string)
 
-    itemStyle?: ItemStyleOption
+    itemStyle?: LegendItemStyleOption
+
+    lineStyle?: LegendLineStyleOption
 
     textStyle?: LabelOption
 
@@ -104,9 +141,9 @@ export interface LegendTooltipFormatterParams {
     $vars: ['name']
 }
 
-export interface LegendSymbolStyleOption extends ItemStyleOption {
-    horizontalLineColor?: ZRColor,
-    horizontalLineWidth?: number
+export interface LegendSymbolStyleOption {
+    itemStyle?: ItemStyleProps,
+    lineStyle?: LineStyleProps
 }
 
 export interface LegendOption extends ComponentOption, LegendStyleOption,
@@ -418,7 +455,34 @@ class LegendModel<Ops extends LegendOption = LegendOption> extends ComponentMode
         inactiveBorderColor: '#ccc',
 
         itemStyle: {
-            // borderWidth: 0
+            color: 'inherit',
+            opacity: 'inherit',
+            decal: 'inherit',
+            shadowBlur: 0,
+            shadowColor: 'inherit',
+            shadowOffsetX: 'inherit',
+            shadowOffsetY: 'inherit',
+            borderColor: 'inherit',
+            borderWidth: 'inherit',
+            borderCap: 'inherit',
+            borderJoin: 'inherit',
+            borderDashOffset: 'inherit',
+            borderMiterLimit: 'inherit'
+        },
+
+        lineStyle: {
+            width: 'auto',
+            color: 'inherit',
+            opacity: 'inherit',
+            type: 'inherit',
+            cap: 'inherit',
+            join: 'inherit',
+            dashOffset: 'inherit',
+            miterLimit: 'inherit',
+            shadowBlur: 0,
+            shadowColor: 'inherit',
+            shadowOffsetX: 'inherit',
+            shadowOffsetY: 'inherit'
         },
 
         textStyle: {
diff --git a/src/component/legend/LegendView.ts b/src/component/legend/LegendView.ts
index 1fc9abf..7449414 100644
--- a/src/component/legend/LegendView.ts
+++ b/src/component/legend/LegendView.ts
@@ -25,7 +25,7 @@ import {setLabelStyle, createTextStyle} from '../../label/labelStyle';
 import {makeBackground} from '../helper/listComponent';
 import * as layoutUtil from '../../util/layout';
 import ComponentView from '../../view/Component';
-import LegendModel, { LegendOption, LegendSelectorButtonOption, LegendSymbolStyleOption, LegendTooltipFormatterParams } from './LegendModel';
+import LegendModel, { LegendItemStyleOption, LegendLineStyleOption, LegendOption, LegendSelectorButtonOption, LegendStyleOption, LegendSymbolStyleOption, LegendTooltipFormatterParams } from './LegendModel';
 import GlobalModel from '../../model/Global';
 import ExtensionAPI from '../../core/ExtensionAPI';
 import {
@@ -37,7 +37,9 @@ import {
     CommonTooltipOption,
     ColorString,
     SeriesOption,
-    SymbolOptionMixin
+    SymbolOptionMixin,
+    LineStyleOption,
+    DecalObject
 } from '../../util/types';
 import Model from '../../model/Model';
 import Displayable, { DisplayableState } from 'zrender/src/graphic/Displayable';
@@ -45,6 +47,11 @@ import { PathStyleProps } from 'zrender/src/graphic/Path';
 import { parse, stringify } from 'zrender/src/tool/color';
 import {PatternObject} from 'zrender/src/graphic/Pattern';
 import {SeriesModel} from '../../echarts';
+import linesLayout from '../../chart/lines/linesLayout';
+import {LineStyleProps} from '../../model/mixin/lineStyle';
+import {ItemStyleProps} from '../../model/mixin/itemStyle';
+import {number} from '../../export/api';
+import makeStyleMapper from '../../model/mixin/makeStyleMapper';
 
 const curry = zrUtil.curry;
 const each = zrUtil.each;
@@ -202,16 +209,14 @@ class LegendView extends ComponentView {
             // Legend to control series.
             if (seriesModel) {
                 const data = seriesModel.getData();
-                const legendSymbolStyle = data.getVisual('legendSymbolStyle') || {};
+                const lineVisualStyle = (data.getVisual('legendSymbolStyle') || {}).lineStyle;
 
                 /**
                  * `data.getVisual('style')` may be the color from the register
                  * in series. For example, for line series,
                  */
-                const style = zrUtil.extend(
-                    zrUtil.extend({}, data.getVisual('style')),
-                    legendItemStyle
-                );
+                const style = data.getVisual('style');
+                console.log(style, lineVisualStyle);
 
                 // Using rect symbol defaultly
                 const legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
@@ -222,7 +227,7 @@ class LegendView extends ComponentView {
                     name, dataIndex, itemModel, legendModel,
                     legendSymbolType, symbolType, symbolSize,
                     itemAlign,
-                    legendSymbolStyle, style, true, selectMode
+                    lineVisualStyle, style, true, selectMode
                 );
 
                 itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId))
@@ -335,8 +340,8 @@ class LegendView extends ComponentView {
         symbolType: string,
         symbolSize: number | number[],
         itemAlign: LegendOption['align'],
-        legendSymbolStyle: LegendSymbolStyleOption,
-        dataItemStyle: PathStyleProps,
+        lineVisualStyle: LineStyleProps,
+        itemVisualStyle: PathStyleProps,
         isColorBySeries: boolean,
         selectMode: LegendOption['selectedMode']
     ) {
@@ -352,24 +357,11 @@ class LegendView extends ComponentView {
         const inactiveColor = itemModel.get('inactiveColor');
         const inactiveBorderColor = itemModel.get('inactiveBorderColor');
         const symbolKeepAspect = itemModel.get('symbolKeepAspect');
-        const legendModelItemStyle = itemModel.getModel('itemStyle');
-
-        let color = dataItemStyle.fill;
-        if (!isColorBySeries) {
-            const colorArr = parse(color as ColorString);
-            // Color may be set to transparent in visualMap when data is out of range.
-            // Do not show nothing.
-            if (colorArr && colorArr[3] === 0) {
-                colorArr[3] = 0.2;
-                // TODO color is set to 0, 0, 0, 0. Should show correct RGBA
-                color = stringify(colorArr, 'rgba');
-            }
-        }
+
+        const style = getLegendStyle(itemModel, lineVisualStyle, itemVisualStyle, isColorBySeries);
+        console.log(style)
 
         symbolType = symbolType || 'roundRect';
-        const borderColor = dataItemStyle[symbolType.indexOf('empty') > -1 ? 'fill' : 'stroke'];
-        const borderWidth = dataItemStyle.lineWidth;
-        const decal = dataItemStyle.decal;
 
         const itemGroup = new Group();
 
@@ -387,55 +379,17 @@ class LegendView extends ComponentView {
             // At least show one symbol, can't be all none
             && ((symbolType !== legendSymbolType) || symbolType === 'none');
 
-        // Draw line if hasHorizontalLine, else draw symbol
-        let legendBorderColor = isSelected
-            ? (hasHorizontalLine
-                ? legendSymbolStyle.horizontalLineColor
-                : borderColor
+        // Draw line
+        if (legendSymbolType === 'line' || itemIcon === 'line') {
+            itemGroup.add(
+                createHorizontalLine(itemWidth, itemHeight, style.lineStyle)
             )
-            : inactiveBorderColor;
-        legendBorderColor = legendBorderColor === 'auto'
-            ? color : legendBorderColor;
-        const legendBorderWidth = hasHorizontalLine
-            ? (legendSymbolStyle.horizontalLineWidth == null
-                ? borderWidth
-                : legendSymbolStyle.horizontalLineWidth)
-            : borderWidth;
-        const legendSymbol = createSymbol(
-            legendSymbolType,
-            0,
-            0,
-            itemWidth,
-            itemHeight,
-            legendBorderColor,
-            // symbolKeepAspect default true for legend
-            symbolKeepAspect == null ? true : symbolKeepAspect
-        );
-        itemGroup.add(
-            setSymbolStyle(legendSymbol, legendSymbolType, null, legendBorderWidth, decal)
-        );
+        }
 
-        // Draw symbol if hasHorizontalLine
-        if (hasHorizontalLine) {
-            const size = symbolSize == null
-                ? itemHeight * 0.8
-                : Math.min(itemHeight, symbolSize as number);
-            if (symbolType === 'none') {
-                symbolType = 'circle';
-            }
-            const legendSymbolCenter = createSymbol(
-                symbolType,
-                (itemWidth - size) / 2,
-                (itemHeight - size) / 2,
-                size,
-                size,
-                isSelected ? color : inactiveColor,
-                // symbolKeepAspect default true for legend
-                symbolKeepAspect == null ? true : symbolKeepAspect
-            );
-            // Put symbol in the center
+        // Put symbol in the center
+        if (itemIcon !== 'line') {
             itemGroup.add(
-                setSymbolStyle(legendSymbolCenter, symbolType, borderColor, borderWidth, decal)
+                createItem(symbolType, symbolSize, symbolKeepAspect, itemWidth, itemHeight, style.itemStyle)
             );
         }
 
@@ -583,23 +537,129 @@ class LegendView extends ComponentView {
 
 }
 
-function setSymbolStyle(
-    symbol: graphic.Path | graphic.Image,
+function getLegendStyle(
+    legendModel: LegendModel['_data'][number],
+    lineVisualStyle: LineStyleProps,
+    itemVisualStyle: PathStyleProps,
+    isColorBySeries: boolean
+) {
+    let color = itemVisualStyle.fill;
+    if (!isColorBySeries) {
+        const colorArr = parse(color as ColorString);
+        // Color may be set to transparent in visualMap when data is out of range.
+        // Do not show nothing.
+        if (colorArr && colorArr[3] === 0) {
+            colorArr[3] = 0.2;
+            // TODO color is set to 0, 0, 0, 0. Should show correct RGBA
+            color = stringify(colorArr, 'rgba');
+        }
+    }
+
+    /**
+     * Use series style if is inherit;
+     * elsewise, use legend style
+     */
+
+    // itemStyle
+    const legendItemModel = legendModel.getModel('itemStyle') as Model<LegendItemStyleOption>;
+    const itemProperties = [
+        ['fill', 'color'],
+        ['lineWidth', 'borderWidth'],
+        ['stroke', 'borderColor'],
+        ['width', 'width'],
+        ['opacity', 'opacity']
+    ];
+    const itemStyle: PathStyleProps = {};
+    for (let i = 0; i < itemProperties.length; ++i) {
+        const propName = itemProperties[i][1] as keyof LegendItemStyleOption;
+        const visualName = itemProperties[i][0] as keyof PathStyleProps;
+        const value = legendItemModel.getShallow(propName) as LegendItemStyleOption[keyof LegendItemStyleOption];
+        if (value === 'inherit') {
+            (itemStyle as any)[visualName] = itemVisualStyle[visualName];
+        }
+        else {
+            (itemStyle as any)[visualName] = value;
+        }
+    }
+
+    // lineStyle
+    const legendLineModel = legendModel.getModel('lineStyle') as Model<LegendLineStyleOption>;
+    const lineProperties = [
+        ['stroke', 'color'],
+        ['lineWidth', 'width']
+    ];
+    const lineStyle: LineStyleProps = {};
+    for (let i = 0; i < lineProperties.length; ++i) {
+        const propName = lineProperties[i][1] as keyof LegendLineStyleOption;
+        const visualName = lineProperties[i][0] as keyof LineStyleProps;
+        const value = legendLineModel.getShallow(propName) as LegendLineStyleOption[keyof LegendLineStyleOption];
+        if (value === 'inherit') {
+            (lineStyle as any)[visualName] = lineVisualStyle[visualName];
+        }
+        else if (value === 'auto' && visualName === 'lineWidth') {
+            // If lineStyle.width is 'auto', it is set to be 2 if series has border
+            lineStyle.lineWidth = lineVisualStyle.lineWidth > 0 ? 2 : 0;
+        }
+        else {
+            (lineStyle as any)[visualName] = value;
+        }
+    }
+
+    // Fix auto color to real color
+    (itemStyle.fill === 'auto') && (itemStyle.fill = color);
+    (itemStyle.stroke === 'auto') && (itemStyle.stroke = color);
+    (lineStyle.stroke === 'auto') && (lineStyle.stroke = color);
+
+    return { itemStyle, lineStyle };
+}
+
+function createHorizontalLine(
+    itemWidth: number,
+    itemHeight: number,
+    style: LineStyleProps
+) {
+    const symbol = createSymbol(
+        'line',
+        0,
+        0,
+        itemWidth,
+        itemHeight,
+        style.stroke,
+        false
+    );
+    symbol.setStyle(style);
+    return symbol;
+}
+
+function createItem(
     symbolType: string,
-    borderColor: ZRColor,
-    borderWidth: number,
-    decal: PatternObject
+    symbolSize: number | number[],
+    symbolKeepAspect: boolean,
+    itemWidth: number,
+    itemHeight: number,
+    style: ItemStyleProps
 ) {
-    const style = (symbol as graphic.Path).style;
-    if (symbolType === 'line') {
-        style.stroke = style.fill;
-        style.fill = 'none';
+    if (symbolType === 'none') {
+        symbolType = 'circle';
     }
-    else {
-        style.decal = decal;
-        borderColor && (style.stroke = borderColor);
+    const size = symbolSize == null
+        ? itemHeight
+        : Math.min(itemHeight, symbolSize as number);
+    const symbol = createSymbol(
+        symbolType,
+        (itemWidth - size) / 2,
+        (itemHeight - size) / 2,
+        size,
+        size,
+        style.fill,
+        // symbolKeepAspect default true for legend
+        symbolKeepAspect == null ? true : symbolKeepAspect
+    );
+    symbol.setStyle(style);
+    if (symbolType.indexOf('empty') > -1) {
+        symbol.style.stroke = symbol.style.fill;
+        symbol.style.fill = '#fff';
     }
-    style.lineWidth = borderWidth;
     return symbol;
 }
 
diff --git a/src/model/mixin/lineStyle.ts b/src/model/mixin/lineStyle.ts
index 168102e..712b2fc 100644
--- a/src/model/mixin/lineStyle.ts
+++ b/src/model/mixin/lineStyle.ts
@@ -54,7 +54,7 @@ type LineStyleKeys = 'lineWidth'
     | 'lineJoin'
     | 'miterLimit';
 
-type LineStyleProps = Pick<PathStyleProps, LineStyleKeys>;
+export type LineStyleProps = Pick<PathStyleProps, LineStyleKeys>;
 
 class LineStyleMixin {
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org