2021SC@SDUSC
echarts中的Component是除Series外的其他配置项,有title(图标标题)、legend(图例组件)、AxisPointer(坐标轴指示器)、坐标系以及坐标轴等。用户通过传递option对象来设置相应的Component内容。
在echarts中,采用了Model以及View的架构来管理Component:
- Model:model/Component.js 管理Component数据;
- View:view/Component.js 负责渲染Component视图。
Model层 model/Component.js。Component扩展自Model(Model是Echarts中最基本的元素,其定义了mergeOption等方法,混合了LineStyle、AraeStyle、ItemStyle以及TextStyle),重写了init及mergeOption等方法,定义了mergeDefaultAndTheme、getDefaultOption等方法以及defaultOption、componentIndex等属性。
View层 view/Component.js。Component中定义了group等属性以及init、render、dispose等方法。
Title(图标标题)
title是用户在使用echarts图表时设置的标题组件
title: {
left: 'center',
text: '例子Title',
}
title文件中Model部分通过extendComponentModel方法扩展自Component Model,重写了defaultOption属性,用于设置title的默认option。
View部分通过extendComponentView方法扩展Component View,重写了render方法对title进行渲染,主要代码如下:
render: function (titleModel, ecModel, api) {
...
// 通过zrender的Text图形新建文本元素
var textEl = new graphic.Text({
style: graphic.setTextStyle({}, textStyleModel, {
text: titleModel.get('text'),
textFill: textStyleModel.getTextColor()
}, {disableBox: true}),
z2: 10
});
var textRect = textEl.getBoundingRect();
var subText = titleModel.get('subtext');
// 创建subText元素
var subTextEl = new graphic.Text({
style: graphic.setTextStyle({}, subtextStyleModel, {
text: subText,
textFill: subtextStyleModel.getTextColor(),
y: textRect.height + titleModel.get('itemGap'),
textVerticalAlign: 'top'
}, {disableBox: true}),
z2: 10
});
...
group.add(textEl);
subText && group.add(subTextEl);
// If no subText, but add subTextEl, there will be an empty line.
...
// 设定title的位置
if (!textAlign) {
// Align left if title is on the left. center and right is same
textAlign = titleModel.get('left') || titleModel.get('right');
if (textAlign === 'middle') {
textAlign = 'center';
}
// Adjust layout by text align
if (textAlign === 'right') {
layoutRect.x += layoutRect.width;
}
else if (textAlign === 'center') {
layoutRect.x += layoutRect.width / 2;
}
}
if (!textBaseline) {
textBaseline = titleModel.get('top') || titleModel.get('bottom');
if (textBaseline === 'center') {
textBaseline = 'middle';
}
if (textBaseline === 'bottom') {
layoutRect.y += layoutRect.height;
}
else if (textBaseline === 'middle') {
layoutRect.y += layoutRect.height / 2;
}
textBaseline = textBaseline || 'top';
}
group.attr('position', [layoutRect.x, layoutRect.y]);
var alignStyle = {
textAlign: textAlign,
textVerticalAlign: textBaseline
};
// 设置文本样式
textEl.setStyle(alignStyle);
subTextEl.setStyle(alignStyle);
// 渲染背景
// Get groupRect again because textAlign has been changed
groupRect = group.getBoundingRect();
var padding = layoutRect.margin;
var style = titleModel.getItemStyle(['color', 'opacity']);
style.fill = titleModel.get('backgroundColor');
var rect = new graphic.Rect({
shape: {
x: groupRect.x - padding[3],
y: groupRect.y - padding[0],
width: groupRect.width + padding[1] + padding[3],
height: groupRect.height + padding[0] + padding[2],
r: titleModel.get('borderRadius')
},
style: style,
silent: true
});
graphic.subPixelOptimizeRect(rect);
group.add(rect);
}
title文本渲染主要是通过zrender graphic中的Text进行渲染的,通过zrender Style中定义的setStyle方法对元素进行样式设定。
legend(图例组件)
legend是用户在使用echarts图表时设置的图例组件
legend: {
data:['支出','收入']
},
legend分为两种:plain(平面)和scroll(可滚动)。
legend.plain
legend.plain为平面的legend图例组件,主要包括LegendAction、LegendModel、LegendView文件。
legendAction文件中注册了legend对外API: legendToggleSelect、legendSelect以及legendUnSelect,主要代码如下:
echarts.registerAction(
'legendToggleSelect', 'legendselectchanged',
zrUtil.curry(legendSelectActionHandler, 'toggleSelected')
);
echarts.registerAction(
'legendSelect', 'legendselected',
zrUtil.curry(legendSelectActionHandler, 'select')
);
echarts.registerAction(
'legendUnSelect', 'legendunselected',
zrUtil.curry(legendSelectActionHandler, 'unSelect')
);
legendModel通过extendComponentModel方法扩展自Component Model,重写了defaultOption属性,重写了init方法,定义了select、unSelect、toggleSelected以及isSelected等方法。
legendView通过extendComponentView方法扩展自Component View,重写了init以及render方法对legend进行渲染,主要渲染的代码如下:
render: function (legendModel, ecModel, api) {
...
// renderInner中调用了createItem方法创建Legend item
// 并绑定了click、mouseover、mouseout等事件
this.renderInner(itemAlign, legendModel, ecModel, api);
...
};
_createItem: function (
name, dataIndex, itemModel, legendModel,
legendSymbolType, symbolType,
itemAlign, color, selectMode
) {
...
// 使用util/symbol导出的createSymbol方法,创建相应Type的Symbol图形
itemGroup.add(createSymbol(
legendSymbolType,
0,
0,
itemWidth,
itemHeight,
isSelected ? color : inactiveColor,
// symbolKeepAspect default true for legend
symbolKeepAspect == null ? true : symbolKeepAspect
));
...
// 渲染legend文本
itemGroup.add(new graphic.Text({
style: graphic.setTextStyle({}, textStyleModel, {
text: content,
x: textX,
y: itemHeight / 2,
textFill: isSelected ? textStyleModel.getTextColor() : inactiveColor,
textAlign: textAlign,
textVerticalAlign: 'middle'
})
}));
// Add a invisible rect to increase the area of mouse hover
// 添加legend的tooltip效果
var hitRect = new graphic.Rect({
shape: itemGroup.getBoundingRect(),
invisible: true,
tooltip: tooltipModel.get('show') ? zrUtil.extend({
content: name,
// Defaul formatter
formatter: legendGlobalTooltipModel.get('formatter', true) || function () {
return name;
},
formatterParams: {
componentType: 'legend',
legendIndex: legendModel.componentIndex,
name: name,
$vars: ['name']
}
}, tooltipModel.option) : null
});
itemGroup.add(hitRect);
...
this.getContentGroup().add(itemGroup);
...
return itemGroup;
}
legend.scroll
legend.scroll为可滚动的legend图例组件,主要包括ScrollableLegendAction、ScrollableLegendModel、ScrollableLegendView文件。
ScrollableLegendAction文件中注册了legend对外API。
echarts.registerAction(
'legendScroll', 'legendscroll',
function (payload, ecModel) {
var scrollDataIndex = payload.scrollDataIndex;
scrollDataIndex != null && ecModel.eachComponent(
{mainType: 'legend', subType: 'scroll', query: payload},
function (legendModel) {
legendModel.setScrollDataIndex(scrollDataIndex);
}
);
}
);
ScrollableLegendModel通过extend方法扩展自LegendMode,重写了defaultOption属性,重写了init方法,定义了setScrollDataIndex以及getOrient等方法。
ScrollableLegendView通过extend方法扩展自LegendView,重写了init以及renderInner方法对scrollable legend进行渲染。
|