Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature #7340. Add the itemStyle to legend #11302

Merged
merged 7 commits into from
Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ More custom build approaches can be checked in this tutorial: [Create Custom Bui

## Contribution

If you wish to debug locally, or make pull requests, please refer to [contributing](https://github.com/apache/incubator-echarts/blob/master/.github/CONTRIBUTING.md) document.
If you wish to debug locally, or make pull requests, please refer to [contributing](https://github.com/apache/incubator-echarts/blob/master/CONTRIBUTING.md) document.

## Resources

Expand Down
10 changes: 9 additions & 1 deletion src/chart/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ function createEl(elOption) {
var graphicType = elOption.type;
var el;

// Those graphic elements are not shapes. They should not be
// overwritten by users, so do them first.
if (graphicType === 'path') {
var shape = elOption.shape;
// Using pathRect brings convenience to users sacle svg path.
Expand All @@ -255,8 +257,14 @@ function createEl(elOption) {
el = new graphicUtil.Text({});
el.__customText = elOption.style.text;
}
else if (graphicType === 'group') {
el = new graphicUtil.Group();
}
else if (graphicType === 'compoundPath') {
throw new Error('"compoundPath" is not supported yet.');
}
else {
var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)];
var Clz = graphicUtil.getShapeClass(graphicType);

if (__DEV__) {
zrUtil.assert(Clz, 'graphic type "' + graphicType + '" can not be found.');
Expand Down
18 changes: 17 additions & 1 deletion src/component/graphic.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ import * as graphicUtil from '../util/graphic';
import * as layoutUtil from '../util/layout';
import {parsePercent} from '../util/number';

var _nonShapeGraphicElements = {

// Reserved but not supported in graphic component.
path: null,
compoundPath: null,

// Supported in graphic component.
group: graphicUtil.Group,
image: graphicUtil.Image,
text: graphicUtil.Text
};

// -------------
// Preprocessor
// -------------
Expand Down Expand Up @@ -440,7 +452,11 @@ function createEl(id, targetElParent, elOption, elMap) {
zrUtil.assert(graphicType, 'graphic type MUST be set');
}

var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)];
var Clz = _nonShapeGraphicElements.hasOwnProperty(graphicType)
// Those graphic elements are not shapes. They should not be
// overwritten by users, so do them first.
? _nonShapeGraphicElements[graphicType]
: graphicUtil.getShapeClass(graphicType);

if (__DEV__) {
zrUtil.assert(Clz, 'graphic type can not be found');
Expand Down
14 changes: 11 additions & 3 deletions src/component/legend/LegendModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,22 @@ var LegendModel = echarts.extendComponentModel({
// 各个item之间的间隔,单位px,默认为10,
// 横向布局时为水平间隔,纵向布局时为纵向间隔
itemGap: 10,
// 图例图形宽度
// the width of legend symbol
itemWidth: 25,
// 图例图形高度
// the height of legend symbol
itemHeight: 14,

// 图例关闭时候的颜色
// the color of unselected legend symbol
inactiveColor: '#ccc',

// the borderColor of unselected legend symbol
inactiveBorderColor: '#ccc',

itemStyle: {
// the default borderWidth of legend symbol
borderWidth: 0
},

textStyle: {
// 图例文字颜色
color: '#333'
Expand Down
49 changes: 41 additions & 8 deletions src/component/legend/LegendView.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,21 +179,28 @@ 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') {
// Use the first data
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');

var itemGroup = this._createItem(
name, dataIndex, itemModel, legendModel,
legendSymbolType, symbolType,
itemAlign, color,
itemAlign, color, borderColor,
selectMode
);

Expand All @@ -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
);

Expand Down Expand Up @@ -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();
Expand All @@ -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,
Expand All @@ -327,7 +337,13 @@ export default echarts.extendComponentView({
isSelected ? color : inactiveColor,
// symbolKeepAspect default true for legend
symbolKeepAspect == null ? true : symbolKeepAspect
));
);
itemGroup.add(
setSymbolStyle(
legendSymbol, legendSymbolType, itemStyle,
borderColor, inactiveBorderColor, isSelected
)
);

// Compose symbols
// PENDING
Expand All @@ -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,
Expand All @@ -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(
setSymbolStyle(
legendSymbolCenter, symbolType, itemStyle,
borderColor, inactiveBorderColor, isSelected
)
);
}

var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
Expand Down Expand Up @@ -481,6 +503,17 @@ export default echarts.extendComponentView({

});

function setSymbolStyle(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',
Expand Down
1 change: 1 addition & 0 deletions src/export.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ zrUtil.each(
'setHoverStyle', 'setLabelStyle', 'setTextStyle', 'setText',
'getFont', 'updateProps', 'initProps', 'getTransform',
'clipPointsByRect', 'clipRectByRect',
'registerShape', 'getShapeClass',
'Group',
'Image',
'Text',
Expand Down
5 changes: 5 additions & 0 deletions src/model/Series.js
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 2 additions & 0 deletions src/model/mixin/dataFormat.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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({
Expand Down
61 changes: 61 additions & 0 deletions src/util/graphic.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ var NORMAL = 'normal';
var _highlightNextDigit = 1;
var _highlightKeyMap = {};

var _customShapeMap = {};


/**
* Extend shape with parameters
Expand All @@ -80,6 +82,53 @@ export function extendPath(pathData, opts) {
return pathTool.extendFromString(pathData, opts);
}

/**
* Register a user defined shape.
* The shape class can be fetched by `getShapeClass`
* This method will not overwrite the built-in shapes.
* The shape can be used in `custom series` and
* `graphic component` by declaring `{type: name}`.
*
* @param {string} name
* @param {Object} ShapeClass Can be generated by `extendShape`.
*/
export function registerShape(name, ShapeClass) {
_customShapeMap[name] = ShapeClass;
}

/**
* Find shape class registered by `registerShape`. Usually used in
* fetching user defined shape.
*
* [Caution]:
* (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared
* to use user registered shapes.
* Because the built-in shape (see `getBuiltInShape`) will be registered by
* `registerShape` by default. That enables users to get both built-in
* shapes as well as the shapes belonging to themsleves. But users can overwrite
* the built-in shapes by using names like 'circle', 'rect' via calling
* `registerShape`. So the echarts inner featrues should not fetch shapes from here
* in case that it is overwritten by users, except that some features, like
* `custom series`, `graphic component`, do it deliberately.
*
* (2) In the features like `custom series`, `graphic component`, the user input
* `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic
* elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names
* are reserved names, that is, if some user register a shape named `'image'`,
* the shape will not be used. If we intending to add some more reserved names
* in feature, that might bring break changes (disable some existing user shape
* names). But that case probably rearly happen. So we dont make more mechanism
* to resolve this issue here.
*
* @param {string} name
* @return {Object} The shape class. If not found, return nothing.
*/
export function getShapeClass(name) {
if (_customShapeMap.hasOwnProperty(name)) {
return _customShapeMap[name];
}
}

/**
* Create a path element from path data string
* @param {string} pathData
Expand Down Expand Up @@ -1377,6 +1426,18 @@ function nearZero(val) {
return val <= (1e-6) && val >= -(1e-6);
}

// Register built-in shapes. These shapes might be overwirtten
// by users, although we do not recommend that.
registerShape('circle', Circle);
registerShape('sector', Sector);
registerShape('ring', Ring);
registerShape('polygon', Polygon);
registerShape('polyline', Polyline);
registerShape('rect', Rect);
registerShape('line', Line);
registerShape('bezierCurve', BezierCurve);
registerShape('arc', Arc);

export {
Group,
ZImage as Image,
Expand Down
25 changes: 23 additions & 2 deletions src/visual/dataColor.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,16 @@ export default function (seriesType) {
var singleDataColor = filteredIdx != null
&& data.getItemVisual(filteredIdx, 'color', true);

if (!singleDataColor) {
var singleDataBorderColor = filteredIdx != null
&& data.getItemVisual(filteredIdx, 'borderColor', true);

var itemModel;
if (!singleDataColor || !singleDataBorderColor) {
// FIXME Performance
var itemModel = dataAll.getItemModel(rawIdx);
itemModel = dataAll.getItemModel(rawIdx);
}

if (!singleDataColor) {
var color = itemModel.get('itemStyle.color')
|| seriesModel.getColorFromPalette(
dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope,
Expand All @@ -74,6 +80,21 @@ export default function (seriesType) {
// Set data all color for legend
dataAll.setItemVisual(rawIdx, 'color', singleDataColor);
}

if (!singleDataBorderColor) {
var borderColor = itemModel.get('itemStyle.borderColor');
// 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);
}
});
}
};
Expand Down
Loading