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 2020/04/16 03:50:40 UTC

[incubator-echarts] branch fix-legend-style created (now 796b981)

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

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


      at 796b981  feat(legend): more intuitove legend design

This branch includes the following new commits:

     new 796b981  feat(legend): more intuitove legend design

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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


[incubator-echarts] 01/01: feat(legend): more intuitove legend design

Posted by ov...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 796b981b2dfe858cb46cb4b6be185a4f0efce166
Author: Ovilia <zw...@gmail.com>
AuthorDate: Thu Apr 16 11:48:50 2020 +0800

    feat(legend): more intuitove legend design
---
 src/chart/line.ts                   |  16 ++++
 src/chart/line/LineSeries.ts        |  13 +++-
 src/component/legend/LegendModel.ts |   2 +-
 src/component/legend/LegendView.ts  |  50 ++++++++----
 src/data/List.ts                    |   3 +-
 src/util/symbol.ts                  |  24 +++---
 src/visual/style.ts                 |  10 ++-
 test/legend-style.html              | 146 ++++++++++++++++++++++++++++++++++++
 8 files changed, 230 insertions(+), 34 deletions(-)

diff --git a/src/chart/line.ts b/src/chart/line.ts
index 541b481..b70fd23 100644
--- a/src/chart/line.ts
+++ b/src/chart/line.ts
@@ -27,9 +27,25 @@ import dataSample from '../processor/dataSample';
 
 // In case developer forget to include grid component
 import '../component/gridSimple';
+import LineSeriesModel from './line/LineSeries';
 
 echarts.registerLayout(layoutPoints('line'));
 
+echarts.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
 echarts.registerProcessor(
     echarts.PRIORITY.PROCESSOR.STATISTIC,
diff --git a/src/chart/line/LineSeries.ts b/src/chart/line/LineSeries.ts
index 1fcb748..8383aad 100644
--- a/src/chart/line/LineSeries.ts
+++ b/src/chart/line/LineSeries.ts
@@ -36,6 +36,9 @@ import {
 import List from '../../data/List';
 import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
 import type Polar from '../../coord/polar/Polar';
+import makeStyleMapper from '../../model/mixin/makeStyleMapper';
+import {ITEM_STYLE_KEY_MAP} from '../../model/mixin/itemStyle';
+import {LINE_STYLE_KEY_MAP} from '../../model/mixin/lineStyle';
 
 type LineDataValue = OptionDataValue | OptionDataValue[];
 
@@ -106,6 +109,8 @@ class LineSeriesModel extends SeriesModel<LineSeriesOption> {
     hasSymbolVisual = true;
     legendSymbol = 'line';
 
+    visualDrawType = 'stroke' as const;
+
     getInitialData(option: LineSeriesOption): List {
         if (__DEV__) {
             const coordSys = option.coordinateSystem;
@@ -132,6 +137,12 @@ class LineSeriesModel extends SeriesModel<LineSeriesOption> {
             position: 'top'
         },
 
+        itemStyle: {
+            color: 'white',
+            borderColor: 'auto',
+            borderWidth: 1
+        },
+
         lineStyle: {
             width: 2,
             type: 'solid'
@@ -149,7 +160,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/component/legend/LegendModel.ts b/src/component/legend/LegendModel.ts
index 290b7b3..fa4298a 100644
--- a/src/component/legend/LegendModel.ts
+++ b/src/component/legend/LegendModel.ts
@@ -391,7 +391,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 dafa108..dbefd0e 100644
--- a/src/component/legend/LegendView.ts
+++ b/src/component/legend/LegendView.ts
@@ -34,12 +34,17 @@ import {
     ZRRectLike,
     ECElement,
     CommonTooltipOption,
-    ColorString
+    ColorString,
+    SeriesOption,
+    SymbolOptionMixin
 } from '../../util/types';
 import Model from '../../model/Model';
 import Displayable from 'zrender/src/graphic/Displayable';
 import { PathStyleProps } from 'zrender/src/graphic/Path';
 import { parse, stringify } from 'zrender/src/tool/color';
+import SeriesModel from '../../model/Series';
+import {LineStyleMixin} from '../../model/mixin/lineStyle';
+import {LineDrawModelOption} from '../../chart/helper/LineDraw';
 
 const curry = zrUtil.curry;
 const each = zrUtil.each;
@@ -184,7 +189,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
@@ -197,16 +203,19 @@ class LegendView extends ComponentView {
                 const style = data.getVisual('style');
                 const color = style.fill;
                 const borderColor = style.stroke;
+                const borderWidth = style.lineWidth;
 
                 // 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,
-                    selectMode
+                    legendSymbolType, symbolType, symbolSize,
+                    itemAlign, color, borderColor, borderWidth,
+                    legendSymbolStyle, selectMode
                 );
 
                 itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId))
@@ -234,6 +243,7 @@ class LegendView extends ComponentView {
 
                         const style = provider.getItemVisual(idx, 'style') as PathStyleProps;
                         const borderColor = style.stroke;
+                        const borderWidth = style.lineWidth;
                         let color = style.fill;
                         const colorArr = parse(style.fill as ColorString);
                         // Color may be set to transparent in visualMap when data is out of range.
@@ -248,9 +258,9 @@ class LegendView extends ComponentView {
 
                         const itemGroup = this._createItem(
                             name, dataIndex, itemModel, legendModel,
-                            legendSymbolType, null,
-                            itemAlign, color, borderColor,
-                            selectMode
+                            legendSymbolType, null, null,
+                            itemAlign, color, borderColor, borderWidth,
+                            {}, selectMode
                         );
 
                         // FIXME: consider different series has items with the same name.
@@ -328,11 +338,19 @@ class LegendView extends ComponentView {
         legendModel: LegendModel,
         legendSymbolType: string,
         symbolType: string,
+        symbolSize: number | number[],
         itemAlign: LegendOption['align'],
         color: ZRColor,
         borderColor: ZRColor,
+        borderWidth: number,
+        legendSymbolStyle: ItemStyleOption,
         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');
@@ -365,7 +383,8 @@ class LegendView extends ComponentView {
         itemGroup.add(
             setSymbolStyle(
                 legendSymbol, legendSymbolType, legendModelItemStyle,
-                borderColor, inactiveBorderColor, isSelected
+                legendSymbolStyle.color || borderColor, legendSymbolStyle.borderWidth || borderWidth,
+                inactiveBorderColor, isSelected
             )
         );
 
@@ -375,7 +394,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';
             }
@@ -393,7 +414,7 @@ class LegendView extends ComponentView {
             itemGroup.add(
                 setSymbolStyle(
                     legendSymbolCenter, symbolType, legendModelItemStyle,
-                    borderColor, inactiveBorderColor, isSelected
+                    borderColor, borderWidth, inactiveBorderColor, isSelected
                 )
             );
         }
@@ -547,13 +568,16 @@ function setSymbolStyle(
     symbolType: string,
     legendModelItemStyle: Model<ItemStyleOption>,
     borderColor: ZRColor,
+    borderWidth: number,
     inactiveBorderColor: ZRColor,
     isSelected: boolean
 ) {
     let itemStyle;
-    if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
+    if (symbolType.indexOf('empty') < 0) {
         itemStyle = legendModelItemStyle.getItemStyle();
-        (symbol as graphic.Path).style.stroke = borderColor;
+        itemStyle.lineWidth = borderWidth;
+        // itemStyle.
+        itemStyle.stroke = borderColor;
         if (!isSelected) {
             itemStyle.stroke = inactiveBorderColor;
         }
diff --git a/src/data/List.ts b/src/data/List.ts
index 1a0c93b..a8656b2 100644
--- a/src/data/List.ts
+++ b/src/data/List.ts
@@ -35,7 +35,7 @@ import {ArrayLike, Dictionary, FunctionPropertyNames} from 'zrender/src/core/typ
 import Element from 'zrender/src/Element';
 import {
     DimensionIndex, DimensionName, DimensionLoose, OptionDataItem,
-    ParsedValue, ParsedValueNumeric, OrdinalNumber, DimensionUserOuput, ModelOption
+    ParsedValue, ParsedValueNumeric, OrdinalNumber, DimensionUserOuput, ModelOption, ItemStyleOption, LineStyleOption
 } from '../util/types';
 import {parseDate} from '../util/number';
 import {isDataItemOption} from '../util/model';
@@ -136,6 +136,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 a0bedde..64daf12 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,
 
@@ -195,17 +193,13 @@ const symbolCtors: Dictionary<SymbolCtor> = {
     triangle: Triangle as unknown as 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 +311,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 +336,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 78f2d56..837d6a7 100644
--- a/src/visual/style.ts
+++ b/src/visual/style.ts
@@ -18,7 +18,7 @@
 */
 
 import { isFunction, extend, createHashMap } from 'zrender/src/core/util';
-import { StageHandler, CallbackDataParams, ZRColor, Dictionary } from '../util/types';
+import { StageHandler, CallbackDataParams, ZRColor, Dictionary, SeriesOption, SymbolOptionMixin } from '../util/types';
 import makeStyleMapper from '../model/mixin/makeStyleMapper';
 import { ITEM_STYLE_KEY_MAP } from '../model/mixin/itemStyle';
 import { LINE_STYLE_KEY_MAP } from '../model/mixin/lineStyle';
@@ -83,11 +83,15 @@ const seriesStyleTask: StageHandler = {
         // TODO style callback
         const colorCallback = isFunction(color) ? color as unknown as ColorCallback : null;
         // Default
-        if ((!globalStyle[colorKey] || colorCallback) && !seriesModel.useColorPaletteOnData) {
-            globalStyle[colorKey] = seriesModel.getColorFromPalette(
+        if ((!globalStyle[colorKey] || colorCallback || globalStyle.fill === 'auto' || globalStyle.stroke)
+            && !seriesModel.useColorPaletteOnData
+        ) {
+            var colorPalette = seriesModel.getColorFromPalette(
                 // TODO series count changed.
                 seriesModel.name, null, ecModel.getSeriesCount()
             );
+            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..3022a5c
--- /dev/null
+++ b/test/legend-style.html
@@ -0,0 +1,146 @@
+<!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