echarts-ng新版本实现
huang-xiao-jian opened this issue · comments
前言
个人项目中使用echarts-ng
,彼时没有基于echarts3
的封装,但使用过程中,感觉不够顺畅,重构早有打算,但始终无法付诸实践。后续接触ES6
, rollup
, webpack
等新东西,于是元旦三天进行较大的重构,意图修复之前存在的问题。
遗留问题
- 不支持媒体查询: #2
- 容器
resize
调用方式诡异: #3 - 无法顺利迁移
Angular2
: #4 - 切换
theme
不够灵活: #5 - 不支持事件绑定、主动触发事件
- 超大配置对象使用双向绑定,性能,用户体验较差
新版本实现
实现Angular2
迁移简单化,需要关键实现做到框架无关,剔除框架特异性考量。
- 数据传递彻底放弃
watch
- 数据更新调整为命令式更新
- 控制器内暴露
echarts instance
- 使用
@bornkiller/echarts-bridge
(https://github.com/bornkiller/echarts-ng) 作为中间层,方便迁移
Monkey Patch
创建包装实例,作为echarts
实际接口与控制器内部调用的中间层。包装实例在DOM连接
之后,完全为echarts instance
,在连接之前,使用monkey patch
实现部分方法,几乎全部支持链式调用。
monkey patch
实现(连接之前即可使用):
-
group
分组属性 -
showLoading
,hideLoading
-
clear
-
dispose
(不支持链式调用,因为实例已销毁) -
resize
-
on
-
off
实例工具类函数基本不会再连接之前调用,进行延迟挂载即可:
-
getWidth
-
getHeight
-
getDom
-
getOption
-
getDataURL
-
getConnectedDataURL
-
isDisposed
-
dispatchAction
-
convertToPixel
-
convertToPixel
-
containPixel
样例
目前仅提供临时开发样例,后续会通过其他方式,大概理解新版本使用方式即可。
/**
* @description - develop helper for showcase
* @author - bornkiller <hjj491229492@hotmail.com>
*/
(function (angular) {
'use strict';
angular.module('echarts-showcase', ['echarts-ng'])
.controller('ShowcaseController', ['$echarts', '$timeout', function ($echarts, $timeout) {
this.themes = ['vintage', 'dark', 'macarons', 'infographic', 'shine', 'roma'];
this.theme = 'vintage';
this.show = true;
this.mediaOptions = [
{
option: {
legend: {
orient: 'horizontal',
left: 'center',
top: 'top'
},
grid: {
right: '10%'
}
}
},
{
query: {
maxWidth: 850
},
option: {
legend: {
orient: 'vertical',
right: 10,
top: '10%'
},
grid: {
right: '15%'
}
}
}
];
this.options = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '邮件营销',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '联盟广告',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '视频广告',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '直接访问',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '搜索引擎',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
this.legends = [
{ description: '邮件营销', selected: true },
{ description: '联盟广告', selected: true },
{ description: '视频广告', selected: true },
{ description: '直接访问', selected: true },
{ description: '搜索引擎', selected: true }
];
this.instance = $echarts.create(this.theme, {}, this.mediaOptions);
this.instance
.showLoading()
.on('click', (event) => {
console.log(event);
})
.on('legendselectchanged', (event) => {
console.log(event);
});
$timeout(() => {
this.instance.setOption(this.options).hideLoading();
}, 1200);
this.handleThemeChange = () => {
this.instance = $echarts.create(this.theme).setOption(this.options);
};
this.handleLegendChange = (name, selected) => {
this.instance.dispatchAction({
type: selected ? 'legendSelect' : 'legendUnSelect',
name: name
})
};
this.toggleSwitchStatus = () => {
this.show = !this.show;
};
this.sync = _.debounce(() => {
this.instance.resize();
}, 100);
window.addEventListener('resize', this.sync);
}]);
angular.bootstrap(document.body, ['echarts-showcase'], { strictDi: true });
})(angular);
录屏地址:https://www.opentest.co/share/56a9c8b0d0be11e688ecd510bcea4514
特别注意
- 单实例如果需要重复连接,务必注意时间先后顺序。如果连接之后销毁实例,但包装实例未销毁,例如使用
ng-if
等指令,重连接之前,所有操作全部丢失,所以重连接后方可进一步操作,暨ng-if=true
条件先于后续操作; - 动态调整
DOM
尺寸,可以连接后直接调用echarts#resize
方法; - 瀑布图快捷方式后续以其他方式提供;
tooltip的支持还是使用plotOption来控制吗?在原readme里没能找到plotOption的用法,所以现在还不会调整toolkit。或请详述,有demo更好啦。
ps:readme里本页的链接地址尾部多了个“。”结果访问404了
@moux1024 echarts
好像没有plotOption
这个选项,现在的实现基本就是把实例的控制器权完全交给开发者,从而进行更精细的纯手动控制的状态,tooltip
配置最终通过setOption
方法生效。demo
的话,正在写,会单独放置另外一个仓库。