From ce0fffabf49089f750f1df552c2d39e2e627d7a2 Mon Sep 17 00:00:00 2001 From: yufeng04 <yufeng04@baidu.com> Date: Sat, 21 Sep 2019 01:06:48 +0800 Subject: [PATCH] fix bug #7340 --- src/component/legend/LegendModel.js | 8 + src/component/legend/LegendView.js | 49 +++- src/model/Series.js | 5 + src/model/mixin/dataFormat.js | 2 + src/visual/dataColor.js | 28 +- src/visual/seriesColor.js | 21 ++ test/lengend-borderColor.html | 402 ++++++++++++++++++++++++++++ 7 files changed, 504 insertions(+), 11 deletions(-) create mode 100644 test/lengend-borderColor.html diff --git a/src/component/legend/LegendModel.js b/src/component/legend/LegendModel.js index 70bf54040e..5442c302f3 100644 --- a/src/component/legend/LegendModel.js +++ b/src/component/legend/LegendModel.js @@ -283,6 +283,14 @@ var LegendModel = echarts.extendComponentModel({ // 图例关闭时候的颜色 inactiveColor: '#ccc', + // 图例关闭时候的颜色 + inactiveBorderColor: '#ccc', + + itemStyle: { + // 图例默认无边框 + borderWidth: 0 + }, + textStyle: { // 图例文字颜色 color: '#333' diff --git a/src/component/legend/LegendView.js b/src/component/legend/LegendView.js index fc0d15660e..f12f5336ba 100644 --- a/src/component/legend/LegendView.js +++ b/src/component/legend/LegendView.js @@ -179,6 +179,7 @@ export default echarts.extendComponentView({ if (seriesModel) { var data = seriesModel.getData(); var color = data.getVisual('color'); + var borderColor = data.getVisual('borderColor'); // If color is a callback function if (typeof color === 'function') { @@ -186,6 +187,12 @@ export default echarts.extendComponentView({ color = color(seriesModel.getDataParams(0)); } + // If borderColor is a callback function + if (typeof borderColor === 'function') { + // Use the first data + borderColor = borderColor(seriesModel.getDataParams(0)); + } + // Using rect symbol defaultly var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect'; var symbolType = data.getVisual('symbol'); @@ -193,7 +200,7 @@ export default echarts.extendComponentView({ var itemGroup = this._createItem( name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, - itemAlign, color, + itemAlign, color, borderColor, selectMode ); @@ -219,13 +226,14 @@ export default echarts.extendComponentView({ } var color = data.getItemVisual(idx, 'color'); + var borderColor = data.getItemVisual(idx, 'borderColor'); var legendSymbolType = 'roundRect'; var itemGroup = this._createItem( name, dataIndex, itemModel, legendModel, legendSymbolType, null, - itemAlign, color, + itemAlign, color, borderColor, selectMode ); @@ -299,12 +307,14 @@ export default echarts.extendComponentView({ _createItem: function ( name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, - itemAlign, color, selectMode + itemAlign, color, borderColor, selectMode ) { var itemWidth = legendModel.get('itemWidth'); var itemHeight = legendModel.get('itemHeight'); var inactiveColor = legendModel.get('inactiveColor'); + var inactiveBorderColor = legendModel.get('inactiveBorderColor'); var symbolKeepAspect = legendModel.get('symbolKeepAspect'); + var itemStyle = legendModel.getModel('itemStyle').getItemStyle(); var isSelected = legendModel.isSelected(name); var itemGroup = new Group(); @@ -318,7 +328,7 @@ export default echarts.extendComponentView({ // Use user given icon first legendSymbolType = itemIcon || legendSymbolType; - itemGroup.add(createSymbol( + var legendSymbol = createSymbol( legendSymbolType, 0, 0, @@ -327,7 +337,13 @@ export default echarts.extendComponentView({ isSelected ? color : inactiveColor, // symbolKeepAspect default true for legend symbolKeepAspect == null ? true : symbolKeepAspect - )); + ); + itemGroup.add( + setSympleStyle( + legendSymbol, legendSymbolType, itemStyle, + borderColor, inactiveBorderColor, isSelected + ) + ); // Compose symbols // PENDING @@ -339,8 +355,7 @@ export default echarts.extendComponentView({ if (symbolType === 'none') { symbolType = 'circle'; } - // Put symbol in the center - itemGroup.add(createSymbol( + var legendSymbolCenter = createSymbol( symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, @@ -349,7 +364,14 @@ export default echarts.extendComponentView({ isSelected ? color : inactiveColor, // symbolKeepAspect default true for legend symbolKeepAspect == null ? true : symbolKeepAspect - )); + ); + // Put symbol in the center + itemGroup.add( + setSympleStyle( + legendSymbolCenter, symbolType, itemStyle, + borderColor, inactiveBorderColor, isSelected + ) + ); } var textX = itemAlign === 'left' ? itemWidth + 5 : -5; @@ -481,6 +503,17 @@ export default echarts.extendComponentView({ }); +function setSympleStyle(symbol, symbolType, itemStyle, borderColor, inactiveBorderColor, isSelected) { + if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) { + symbol.style.stroke = borderColor; + if (!isSelected) { + itemStyle.stroke = inactiveBorderColor; + } + symbol.setStyle(itemStyle); + } + return symbol; +} + function dispatchSelectAction(name, api) { api.dispatchAction({ type: 'legendToggleSelect', diff --git a/src/model/Series.js b/src/model/Series.js index 395a096560..8b090e6b93 100644 --- a/src/model/Series.js +++ b/src/model/Series.js @@ -73,6 +73,11 @@ var SeriesModel = ComponentModel.extend({ */ visualColorAccessPath: 'itemStyle.color', + /** + * Access path of borderColor for visual + */ + visualBorderColorAccessPath: 'itemStyle.borderColor', + /** * Support merge layout params. * Only support 'box' now (left/right/top/bottom/width/height). diff --git a/src/model/mixin/dataFormat.js b/src/model/mixin/dataFormat.js index 1d10e6e55d..64d4643092 100644 --- a/src/model/mixin/dataFormat.js +++ b/src/model/mixin/dataFormat.js @@ -38,6 +38,7 @@ export default { var name = data.getName(dataIndex); var itemOpt = data.getRawDataItem(dataIndex); var color = data.getItemVisual(dataIndex, 'color'); + var borderColor = data.getItemVisual(dataIndex, 'borderColor'); var tooltipModel = this.ecModel.getComponent('tooltip'); var renderModeOption = tooltipModel && tooltipModel.get('renderMode'); var renderMode = getTooltipRenderMode(renderModeOption); @@ -59,6 +60,7 @@ export default { dataType: dataType, value: rawValue, color: color, + borderColor: borderColor, dimensionNames: userOutput ? userOutput.dimensionNames : null, encode: userOutput ? userOutput.encode : null, marker: getTooltipMarker({ diff --git a/src/visual/dataColor.js b/src/visual/dataColor.js index 8fbd9ebfd4..5d5f1523fe 100644 --- a/src/visual/dataColor.js +++ b/src/visual/dataColor.js @@ -53,10 +53,13 @@ export default function (seriesType) { var singleDataColor = filteredIdx != null && data.getItemVisual(filteredIdx, 'color', true); - if (!singleDataColor) { - // FIXME Performance - var itemModel = dataAll.getItemModel(rawIdx); + var singleDataBorderColor = filteredIdx != null + && data.getItemVisual(filteredIdx, 'borderColor', true); + + // FIXME Performance + var itemModel = dataAll.getItemModel(rawIdx); + if (!singleDataColor) { var color = itemModel.get('itemStyle.color') || seriesModel.getColorFromPalette( dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope, @@ -74,6 +77,25 @@ export default function (seriesType) { // Set data all color for legend dataAll.setItemVisual(rawIdx, 'color', singleDataColor); } + + if (!singleDataBorderColor) { + var borderColor = itemModel.get('itemStyle.borderColor') + || seriesModel.getColorFromPalette( + dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope, + dataAll.count() + ); + // Legend may use the visual info in data before processed + dataAll.setItemVisual(rawIdx, 'borderColor', borderColor); + + // Data is not filtered + if (filteredIdx != null) { + data.setItemVisual(filteredIdx, 'borderColor', borderColor); + } + } + else { + // Set data all borderColor for legend + dataAll.setItemVisual(rawIdx, 'borderColor', singleDataBorderColor); + } }); } }; diff --git a/src/visual/seriesColor.js b/src/visual/seriesColor.js index b253fff6ea..0cd240ab1c 100644 --- a/src/visual/seriesColor.js +++ b/src/visual/seriesColor.js @@ -33,6 +33,15 @@ export default { // FIXME Set color function or use the platte color data.setVisual('color', color); + + var borderColorAccessPath = (seriesModel.visualBorderColorAccessPath || 'itemStyle.borderColor').split('.'); + var borderColor = seriesModel.get(borderColorAccessPath) // Set in itemStyle + || seriesModel.getColorFromPalette( + // TODO series count changed. + seriesModel.name, null, ecModel.getSeriesCount() + ); // Default borderColor + // FIXME Set borderColor function or use the platte borderColor + data.setVisual('borderColor', borderColor); // Only visible series has each data be visual encoded if (!ecModel.isSeriesFiltered(seriesModel)) { @@ -44,13 +53,25 @@ export default { }); } + if (typeof borderColor === 'function' && !(borderColor instanceof Gradient)) { + data.each(function (idx) { + data.setItemVisual( + idx, 'borderColor', borderColor(seriesModel.getDataParams(idx)) + ); + }); + } + // itemStyle in each data item var dataEach = function (data, idx) { var itemModel = data.getItemModel(idx); var color = itemModel.get(colorAccessPath, true); + var borderColor = itemModel.get(borderColorAccessPath, true); if (color != null) { data.setItemVisual(idx, 'color', color); } + if (borderColor != null) { + data.setItemVisual(idx, 'borderColor', borderColor); + } }; return { dataEach: data.hasItemOption ? dataEach : null }; diff --git a/test/lengend-borderColor.html b/test/lengend-borderColor.html new file mode 100644 index 0000000000..d7515332d7 --- /dev/null +++ b/test/lengend-borderColor.html @@ -0,0 +1,402 @@ +<!-- +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"> + <script src="lib/esl.js"></script> + <script src="lib/config.js"></script> + <meta name="viewport" content="width=device-width, initial-scale=1" /> +</head> + +<body> + <style> + h1 { + line-height: 60px; + height: 60px; + background: #146402; + text-align: center; + font-weight: bold; + color: #eee; + font-size: 14px; + } + .chart { + height: 300px; + } + </style> + + <h1>The line in legend symble should be default value and the borderWidth of legend symble should be legend.itemSyle.borderWidth</h1> + <div class="chart" id="plain"></div> + <h1>The style with legend symble should be series[i].itemStyle</h1> + <div class="chart" id="plain1"></div> + <h1>The style with legend symble should be legend.itemStyle</h1> + <div class="chart" id="plain2"></div> + <script> + require([ + 'echarts' + // 'echarts/util/graphic', + // 'echarts/chart/line', + // 'echarts/component/legend', + // 'echarts/component/grid', + // 'echarts/component/tooltip' + ], function (echarts) { + var graphic = echarts.graphic; + + var chart = echarts.init(document.getElementById('plain'), null, { + + }); + + var option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985' + } + } + }, + legend: { + data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'], + itemStyle: { + // borderColor: '#f00', + borderWidth: 3 + } + }, + toolbox: { + feature: { + saveAsImage: {} + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis: [ + { + type: 'category', + boundaryGap: false, + data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] + } + ], + yAxis: [ + { + type: 'value' + } + ], + series: [ + { + name: '邮件营销', + type: 'line', + stack: '总量', + areaStyle: {}, + // default emptyCircle + // symbol: 'circle', + itemStyle: { + borderColor: '#096', + borderWidth: 1 + }, + data: [120, 132, 101, 134, 90, 230, 210] + }, + { + name: '联盟广告', + type: 'line', + stack: '总量', + areaStyle: {}, + symbol: 'circle', + itemStyle: { + borderColor: '#ffde33', + borderWidth: 1 + }, + data: [220, 182, 191, 234, 290, 330, 310] + }, + { + name: '视频广告', + type: 'line', + stack: '总量', + areaStyle: {}, + symbol: 'rect', + itemStyle: { + borderColor: '#ff9933', + borderWidth: 2 + }, + data: [150, 232, 201, 154, 190, 330, 410] + }, + { + name: '直接访问', + type: 'line', + stack: '总量', + areaStyle: { normal: {} }, + symbol: 'roundRect', + itemStyle: { + borderColor: '#cc0033', + borderWidth: 3 + }, + data: [320, 332, 301, 334, 390, 330, 320] + }, + { + name: '搜索引擎', + type: 'line', + stack: '总量', + label: { + normal: { + show: true, + position: 'top' + } + }, + areaStyle: { normal: {} }, + symbol: 'triangle', + itemStyle: { + borderColor: '#660099', + borderWidth: 4 + }, + data: [820, 932, 901, 934, 1290, 1330, 1320] + } + ] + }; + chart.setOption(option); + + var chart1 = echarts.init(document.getElementById('plain1'), null, {}); + + var option1 = { + tooltip: { + trigger: 'axis', + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + legend: { + data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎', '百度', '谷歌', '必应', '其他'], + itemStyle: { + borderWidth: 3 + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis: [ + { + type: 'category', + data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] + } + ], + yAxis: [ + { + type: 'value' + } + ], + series: [ + { + name: '直接访问', + type: 'bar', + data: [320, 332, 301, 334, 390, 330, 320], + itemStyle: { + borderColor: '#000', + borderWidth: 3 + } + }, + { + name: '邮件营销', + type: 'bar', + stack: '广告', + data: [120, 132, 101, 134, 90, 230, 210], + itemStyle: { + borderColor: '#f00', + borderWidth: 0 + } + }, + { + name: '联盟广告', + type: 'bar', + stack: '广告', + data: [220, 182, 191, 234, 290, 330, 310] + }, + { + name: '视频广告', + type: 'bar', + stack: '广告', + data: [150, 232, 201, 154, 190, 330, 410] + }, + { + name: '搜索引擎', + type: 'bar', + data: [862, 1018, 964, 1026, 1679, 1600, 1570], + markLine: { + lineStyle: { + normal: { + type: 'dashed' + } + }, + data: [ + [{ type: 'min' }, { type: 'max' }] + ] + } + }, + { + name: '百度', + type: 'bar', + barWidth: 5, + stack: '搜索引擎', + data: [620, 732, 701, 734, 1090, 1130, 1120] + }, + { + name: '谷歌', + type: 'bar', + stack: '搜索引擎', + data: [120, 132, 101, 134, 290, 230, 220] + }, + { + name: '必应', + type: 'bar', + stack: '搜索引擎', + data: [60, 72, 71, 74, 190, 130, 110] + }, + { + name: '其他', + type: 'bar', + stack: '搜索引擎', + data: [62, 82, 91, 84, 109, 110, 120] + } + ] + }; + chart1.setOption(option1); + + + var chart2 = echarts.init(document.getElementById('plain2'), null, {}); + + var option2 = { + tooltip: { + trigger: 'item', + formatter: "{a} <br/>{b}: {c} ({d}%)" + }, + legend: { + orient: 'vertical', + x: 'left', + data: ['直达', '营销广告', '搜索引擎', '邮件营销', '联盟广告', '视频广告', '百度', '谷歌', '必应', '其他'], + itemStyle: { + borderWidth: 3, + borderColor: '#f00' + } + }, + series: [ + { + name: '访问来源', + type: 'pie', + selectedMode: 'single', + radius: [0, '30%'], + + label: { + normal: { + position: 'inner' + } + }, + itemStyle: { + borderColor: '#ff9933', + borderWidth: 2 + }, + labelLine: { + normal: { + show: false + } + }, + data: [ + { value: 335, name: '直达', selected: true }, + { value: 679, name: '营销广告' }, + { value: 1548, name: '搜索引擎' } + ] + }, + { + name: '访问来源', + type: 'pie', + radius: ['40%', '55%'], + label: { + normal: { + formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ', + backgroundColor: '#eee', + borderColor: '#aaa', + borderWidth: 1, + borderRadius: 4, + // shadowBlur:3, + // shadowOffsetX: 2, + // shadowOffsetY: 2, + // shadowColor: '#999', + // padding: [0, 7], + rich: { + a: { + color: '#999', + lineHeight: 22, + align: 'center' + }, + // abg: { + // backgroundColor: '#333', + // width: '100%', + // align: 'right', + // height: 22, + // borderRadius: [4, 4, 0, 0] + // }, + hr: { + borderColor: '#aaa', + width: '100%', + borderWidth: 0.5, + height: 0 + }, + b: { + fontSize: 16, + lineHeight: 33 + }, + per: { + color: '#eee', + backgroundColor: '#334455', + padding: [2, 4], + borderRadius: 2 + } + } + } + }, + itemStyle: { + borderColor: '#660099', + borderWidth: 4 + }, + data: [ + { value: 335, name: '直达' }, + { value: 310, name: '邮件营销' }, + { value: 234, name: '联盟广告' }, + { value: 135, name: '视频广告' }, + { value: 1048, name: '百度' }, + { value: 251, name: '谷歌' }, + { value: 147, name: '必应' }, + { value: 102, name: '其他' } + ] + } + ] + }; + chart2.setOption(option2); + + }); + + </script> +</body> + +</html> \ No newline at end of file