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:03 UTC

[echarts] 01/10: WIP(legend): merge #12444 and current master

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 e7f431a4acc5ced63736bb4beffc2d9632ddc44f
Author: Ovilia <zw...@gmail.com>
AuthorDate: Tue Mar 2 13:41:37 2021 +0800

    WIP(legend): merge #12444 and current master
---
 src/chart/line/LineSeries.ts        |  10 ++-
 src/chart/line/install.ts           |  16 ++++
 src/component/legend/LegendModel.ts |   2 +-
 src/component/legend/LegendView.ts  |  47 +++++++++---
 src/data/List.ts                    |   4 +-
 src/util/symbol.ts                  |  23 +++---
 src/visual/style.ts                 |  12 ++-
 test/legend-style.html              | 144 ++++++++++++++++++++++++++++++++++++
 8 files changed, 226 insertions(+), 32 deletions(-)

diff --git a/src/chart/line/LineSeries.ts b/src/chart/line/LineSeries.ts
index f940873..1876ab0 100644
--- a/src/chart/line/LineSeries.ts
+++ b/src/chart/line/LineSeries.ts
@@ -127,6 +127,8 @@ class LineSeriesModel extends SeriesModel<LineSeriesOption> {
     hasSymbolVisual = true;
     legendSymbol = 'line';
 
+    visualDrawType = 'stroke' as const;
+
     getInitialData(option: LineSeriesOption): List {
         if (__DEV__) {
             const coordSys = option.coordinateSystem;
@@ -151,6 +153,12 @@ class LineSeriesModel extends SeriesModel<LineSeriesOption> {
             position: 'top'
         },
 
+        itemStyle: {
+            color: 'white',
+            borderColor: 'auto',
+            borderWidth: 1
+        },
+
         endLabel: {
             show: false,
             valueAnimation: true,
@@ -181,7 +189,7 @@ class LineSeriesModel extends SeriesModel<LineSeriesOption> {
         // Disabled if step is true
         smooth: false,
         smoothMonotone: null,
-        symbol: 'emptyCircle',
+        symbol: 'circle',
         symbolSize: 4,
         symbolRotate: null,
 
diff --git a/src/chart/line/install.ts b/src/chart/line/install.ts
index af11575..4738554 100644
--- a/src/chart/line/install.ts
+++ b/src/chart/line/install.ts
@@ -19,6 +19,7 @@
 
 import LineSeries from './LineSeries';
 import LineView from './LineView';
+import LineSeriesModel from './LineSeries';
 
 // In case developer forget to include grid component
 
@@ -34,6 +35,21 @@ export function install(registers: EChartsExtensionInstallRegisters) {
 
     registers.registerLayout(layoutPoints('line', true));
 
+    registers.registerVisual({
+        seriesType: 'line',
+        reset: function (seriesModel: LineSeriesModel) {
+            // Visual coding for legend
+            const lineStyle = seriesModel.getModel('lineStyle');
+            console.log(lineStyle.get('color'), lineStyle.get('width'))
+            if (lineStyle) {
+                seriesModel.getData().setVisual('legendSymbolStyle', {
+                    color: lineStyle.get('color'),
+                    borderWidth: lineStyle.get('width')
+                });
+            }
+        }
+    });
+
     // Down sample after filter
     registers.registerProcessor(
         registers.PRIORITY.PROCESSOR.STATISTIC,
diff --git a/src/component/legend/LegendModel.ts b/src/component/legend/LegendModel.ts
index 674e4f2..074cb4e 100644
--- a/src/component/legend/LegendModel.ts
+++ b/src/component/legend/LegendModel.ts
@@ -405,7 +405,7 @@ class LegendModel<Ops extends LegendOption = LegendOption> extends ComponentMode
         inactiveBorderColor: '#ccc',
 
         itemStyle: {
-            borderWidth: 0
+            // borderWidth: 0
         },
 
         textStyle: {
diff --git a/src/component/legend/LegendView.ts b/src/component/legend/LegendView.ts
index cabb0367..b170572 100644
--- a/src/component/legend/LegendView.ts
+++ b/src/component/legend/LegendView.ts
@@ -35,13 +35,16 @@ import {
     ZRRectLike,
     ECElement,
     CommonTooltipOption,
-    ColorString
+    ColorString,
+    SeriesOption,
+    SymbolOptionMixin
 } from '../../util/types';
 import Model from '../../model/Model';
 import Displayable, { DisplayableState } from 'zrender/src/graphic/Displayable';
 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';
 
 const curry = zrUtil.curry;
 const each = zrUtil.each;
@@ -187,7 +190,8 @@ class LegendView extends ComponentView {
             }
 
             // Representitive series.
-            const seriesModel = ecModel.getSeriesByName(name)[0];
+            const seriesModel = ecModel.getSeriesByName(name)[0] as
+                SeriesModel<SeriesOption & SymbolOptionMixin>;
 
             if (legendDrawnMap.get(name)) {
                 // Have been drawed
@@ -200,17 +204,20 @@ class LegendView extends ComponentView {
                 const style = data.getVisual('style');
                 const color = style[data.getVisual('drawType')] || style.fill;
                 const borderColor = style.stroke;
+                const borderWidth = style.lineWidth;
                 const decal = style.decal;
 
                 // Using rect symbol defaultly
                 const legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
+                const legendSymbolStyle = data.getVisual('legendSymbolStyle') || {};
                 const symbolType = data.getVisual('symbol');
+                const symbolSize = seriesModel.get('symbolSize');
 
                 const itemGroup = this._createItem(
                     name, dataIndex, itemModel, legendModel,
-                    legendSymbolType, symbolType,
-                    itemAlign, color, borderColor, decal,
-                    selectMode
+                    legendSymbolType, symbolType, symbolSize,
+                    itemAlign, color, borderColor, borderWidth,
+                    legendSymbolStyle, decal, selectMode
                 );
 
                 itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId))
@@ -238,6 +245,7 @@ class LegendView extends ComponentView {
 
                         const style = provider.getItemVisual(idx, 'style') as PathStyleProps;
                         const borderColor = style.stroke;
+                        const borderWidth = style.lineWidth;
                         const decal = style.decal;
                         let color = style.fill;
                         const colorArr = parse(style.fill as ColorString);
@@ -253,9 +261,9 @@ class LegendView extends ComponentView {
 
                         const itemGroup = this._createItem(
                             name, dataIndex, itemModel, legendModel,
-                            legendSymbolType, null,
-                            itemAlign, color, borderColor, decal,
-                            selectMode
+                            legendSymbolType, null, null,
+                            itemAlign, color, borderColor, borderWidth,
+                            {}, decal, selectMode
                         );
 
                         // FIXME: consider different series has items with the same name.
@@ -333,12 +341,20 @@ class LegendView extends ComponentView {
         legendModel: LegendModel,
         legendSymbolType: string,
         symbolType: string,
+        symbolSize: number | number[],
         itemAlign: LegendOption['align'],
         color: ZRColor,
         borderColor: ZRColor,
+        borderWidth: number,
+        legendSymbolStyle: ItemStyleOption,
         decal: PatternObject,
         selectMode: LegendOption['selectedMode']
     ) {
+        if (symbolSize != null && typeof symbolSize === 'object') {
+            // Use symbol height as symbol size if it's an array
+            symbolSize = symbolSize[1];
+        }
+
         const itemWidth = legendModel.get('itemWidth');
         const itemHeight = legendModel.get('itemHeight');
         const inactiveColor = legendModel.get('inactiveColor');
@@ -371,7 +387,8 @@ class LegendView extends ComponentView {
         itemGroup.add(
             setSymbolStyle(
                 legendSymbol, legendSymbolType, legendModelItemStyle,
-                borderColor, inactiveBorderColor, decal, isSelected
+                legendSymbolStyle.color || borderColor, legendSymbolStyle.borderWidth || borderWidth,
+                inactiveBorderColor, decal, isSelected
             )
         );
 
@@ -381,7 +398,9 @@ class LegendView extends ComponentView {
             // At least show one symbol, can't be all none
             && ((symbolType !== legendSymbolType) || symbolType === 'none')
         ) {
-            const size = itemHeight * 0.8;
+            const size = symbolSize == null
+                ? itemHeight * 0.8
+                : Math.min(itemHeight, symbolSize as number);
             if (symbolType === 'none') {
                 symbolType = 'circle';
             }
@@ -399,7 +418,7 @@ class LegendView extends ComponentView {
             itemGroup.add(
                 setSymbolStyle(
                     legendSymbolCenter, symbolType, legendModelItemStyle,
-                    borderColor, inactiveBorderColor, decal, isSelected
+                    borderColor, borderWidth, inactiveBorderColor, decal, isSelected
                 )
             );
         }
@@ -553,13 +572,17 @@ function setSymbolStyle(
     symbolType: string,
     legendModelItemStyle: Model<ItemStyleOption>,
     borderColor: ZRColor,
+    borderWidth: number,
     inactiveBorderColor: ZRColor,
     decal: PatternObject,
     isSelected: boolean
 ) {
     let itemStyle;
-    if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
+    if (symbolType.indexOf('empty') < 0) {
         itemStyle = legendModelItemStyle.getItemStyle();
+        itemStyle.lineWidth = borderWidth;
+        // itemStyle.
+        itemStyle.stroke = borderColor;
         (symbol as graphic.Path).style.stroke = borderColor;
         (symbol as graphic.Path).style.decal = decal;
         if (!isSelected) {
diff --git a/src/data/List.ts b/src/data/List.ts
index 7a8b245..72f79dc 100644
--- a/src/data/List.ts
+++ b/src/data/List.ts
@@ -35,7 +35,8 @@ import Element from 'zrender/src/Element';
 import {
     DimensionIndex, DimensionName, DimensionLoose, OptionDataItem,
     ParsedValue, ParsedValueNumeric, OrdinalNumber, DimensionUserOuput,
-    ModelOption, SeriesDataType, OptionSourceData, SOURCE_FORMAT_TYPED_ARRAY, SOURCE_FORMAT_ORIGINAL, DecalObject
+    ModelOption, SeriesDataType, OptionSourceData, SOURCE_FORMAT_TYPED_ARRAY, SOURCE_FORMAT_ORIGINAL,
+    DecalObject, ItemStyleOption
 } from '../util/types';
 import {isDataItemOption, convertOptionIdName} from '../util/model';
 import { getECData } from '../util/innerStore';
@@ -139,6 +140,7 @@ export interface DefaultDataVisual {
     liftZ?: number
     // For legend.
     legendSymbol?: string
+    legendSymbolStyle?: ItemStyleOption
 
     // visualMap will inject visualMeta data
     visualMeta?: VisualMeta[]
diff --git a/src/util/symbol.ts b/src/util/symbol.ts
index 8b5dc28..bd7c4e6 100644
--- a/src/util/symbol.ts
+++ b/src/util/symbol.ts
@@ -174,9 +174,7 @@ const Arrow = graphic.Path.extend({
  */
 // TODO Use function to build symbol path.
 const symbolCtors: Dictionary<SymbolCtor> = {
-    // Use small height rect to simulate line.
-    // Avoid using stroke.
-    line: graphic.Rect as unknown as SymbolCtor,
+    line: graphic.Line as unknown as SymbolCtor,
 
     rect: graphic.Rect as unknown as SymbolCtor,
 
@@ -196,16 +194,13 @@ const symbolCtors: Dictionary<SymbolCtor> = {
 };
 
 
-// NOTICE Only use fill. No line!
 const symbolShapeMakers: Dictionary<SymbolShapeMaker> = {
 
-    line: function (x, y, w, h, shape: graphic.Rect['shape']) {
-        const thickness = 2;
-        // A thin line
-        shape.x = x;
-        shape.y = y + h / 2 - thickness / 2;
-        shape.width = w;
-        shape.height = thickness;
+    line: function (x, y, w, h, shape: graphic.Line['shape']) {
+        shape.x1 = x;
+        shape.y1 = y + h / 2;
+        shape.x2 = x + w;
+        shape.y2 = y + h / 2;
     },
 
     rect: function (x, y, w, h, shape: graphic.Rect['shape']) {
@@ -317,8 +312,6 @@ function symbolPathSetColor(this: ECSymbol, color: ZRColor, innerColor?: string)
         if (this.__isEmptyBrush) {
             symbolStyle.stroke = color;
             symbolStyle.fill = innerColor || '#fff';
-            // TODO Same width with lineStyle in LineView.
-            symbolStyle.lineWidth = 2;
         }
         else {
             symbolStyle.fill = color;
@@ -344,7 +337,9 @@ export function createSymbol(
 
     const isEmpty = symbolType.indexOf('empty') === 0;
     if (isEmpty) {
-        symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
+        const realSymbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
+        console.warn(`[DEPRECATED] Shape "${symbolType}" is deprecated. Please use "${realSymbolType}" with "fill" as "white" instead.`);
+        symbolType = realSymbolType;
     }
     let symbolPath: ECSymbol | graphic.Image;
 
diff --git a/src/visual/style.ts b/src/visual/style.ts
index e8c6832..082ca03 100644
--- a/src/visual/style.ts
+++ b/src/visual/style.ts
@@ -88,16 +88,22 @@ const seriesStyleTask: StageHandler = {
 
         // TODO style callback
         const colorCallback = isFunction(color) ? color as unknown as ColorCallback : null;
+        const hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto';
         // Get from color palette by default.
-        if (!globalStyle[colorKey] || colorCallback) {
+        if (!globalStyle[colorKey] || colorCallback || hasAutoColor) {
             // Note: if some series has color specified (e.g., by itemStyle.color), we DO NOT
             // make it effect palette. Bacause some scenarios users need to make some series
             // transparent or as background, which should better not effect the palette.
-            globalStyle[colorKey] = seriesModel.getColorFromPalette(
+            const colorPalette = seriesModel.getColorFromPalette(
                 // TODO series count changed.
                 seriesModel.name, null, ecModel.getSeriesCount()
             );
-            data.setVisual('colorFromPalette', true);
+            if (!globalStyle[colorKey]) {
+                globalStyle[colorKey] = colorPalette;
+                data.setVisual('colorFromPalette', true);
+            }
+            globalStyle.fill = globalStyle.fill === 'auto' ? colorPalette : globalStyle.fill;
+            globalStyle.stroke = globalStyle.stroke === 'auto' ? colorPalette : globalStyle.stroke;
         }
 
         data.setVisual('style', globalStyle);
diff --git a/test/legend-style.html b/test/legend-style.html
new file mode 100644
index 0000000..70bd350
--- /dev/null
+++ b/test/legend-style.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+
+
+<html>
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <script src="lib/esl.js"></script>
+        <script src="lib/config.js"></script>
+        <script src="lib/jquery.min.js"></script>
+        <script src="lib/facePrint.js"></script>
+        <script src="lib/testHelper.js"></script>
+        <!-- <script src="ut/lib/canteen.js"></script> -->
+        <link rel="stylesheet" href="lib/reset.css" />
+    </head>
+    <body>
+        <style>
+        </style>
+
+
+        <div id="main1"></div>
+
+        <script>
+        require(['echarts'], function (echarts) {
+            var getData = function (seriesId) {
+                var data = [];
+                for (var i = 0; i < 7; ++i) {
+                    data.push(Math.random() * 100 + (seriesId + 1) * 200);
+                }
+                return data;
+            };
+
+            var option = {
+                xAxis: {
+                    type: 'category',
+                    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+                },
+                yAxis: {
+                    type: 'value'
+                },
+                legend: {
+                    data: ['Default Line', 'Line with emptyCircle', 'Line with emptyCircle and color', 'Line with style', 'Line with visualMap', 'Pie A', 'Pie B', 'Pie C']
+                },
+                series: [{
+                    data: getData(0),
+                    type: 'line',
+                    name: 'Default Line'
+                }, {
+                    data: getData(1),
+                    type: 'line',
+                    name: 'Line with emptyCircle',
+                    symbol: 'emptyCircle'
+                }, {
+                    data: getData(2),
+                    type: 'line',
+                    name: 'Line with emptyCircle and color',
+                    symbol: 'emptyCircle',
+                    itemStyle: {
+                        color: 'auto'
+                    }
+                }, {
+                    data: getData(3),
+                    type: 'line',
+                    name: 'Line with style',
+                    symbolSize: 12,
+                    itemStyle: {
+                        color: 'auto',
+                        borderColor: 'blue',
+                        borderWidth: 2,
+                        symbolSize: 25
+                    },
+                    lineStyle: {
+                        color: 'red',
+                        width: 4
+                    }
+                }, {
+                    data: getData(4),
+                    type: 'line',
+                    name: 'Line with visualMap',
+                    symbolSize: 30,
+                    itemStyle: {
+                        borderColor: 'green'
+                    }
+                }, {
+                    type: 'pie',
+                    data: [{
+                        name: 'Pie A',
+                        value: 10
+                    }, {
+                        name: 'Pie B',
+                        value: 8
+                    }, {
+                        name: 'Pie C',
+                        value: 14,
+                        itemStyle: {
+                            color: 'blue'
+                        }
+                    }],
+                    center: ['80%', '50%']
+                }],
+                grid: {
+                    left: 60,
+                    width: '55%'
+                },
+                visualMap: {
+                    type: 'continuous',
+                    min: 1000,
+                    max: 1100,
+                    inRange: {
+                        color: ['green', 'yellow', 'red']
+                    },
+                    show: false,
+                    seriesIndex: 4
+                }
+            };
+
+            var chart = testHelper.create(echarts, 'main1', {
+                title: [
+                    'Legend icon being more intuitive'
+                ],
+                option: option
+            });
+        });
+        </script>
+
+
+    </body>
+</html>


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