san-echarts
Version:
ECharts component for San
335 lines (325 loc) • 10.4 kB
JavaScript
/**
* san-echarts
* Copyright 2018 Baidu Inc. All rights reserved.
*
* @file Echarts的 San 组件
* @author kentpan
*/
import defered from './defered';
let echarts = require('echarts');
let context = window || global;
if (!!context && (!context.echarts && !!echarts)) {
context.echarts = echarts;
}
let plugsCache = {};
const echartsEvents = [
'legendselectchanged',
'legendselected',
'legendunselected',
'datazoom',
'datarangeselected',
'timelinechanged',
'timelineplaychanged',
'restore',
'dataviewchanged',
'magictypechanged',
'geoselectchanged',
'geoselected',
'geounselected',
'pieselectchanged',
'pieselected',
'pieunselected',
'mapselectchanged',
'mapselected',
'mapunselected',
'axisareaselected',
'focusnodeadjacency',
'unfocusnodeadjacency',
'brush',
'brushselected',
'click',
'dblclick',
'mouseover',
'mouseout',
'mousedown',
'mouseup',
'globalout'
];
const echartsInstanceFunctions = [
'setOption',
'getWidth',
'getHeight',
'getDom',
'getOption',
'resize',
'dispatchAction',
'convertToPixel',
'convertFromPixel',
'containPixel',
'showLoading',
'hideLoading',
'getDataURL',
'getConnectedDataURL',
'appendData',
'clear',
'isDisposed',
'dispose'
];
/**
* [dataEmpty 检测echarts组件数据是否为空]
* @param {[type]} series [description]
* @return {[type]} [description]
*/
const dataIsEmpty = function (series) {
let filterData = [];
if (series instanceof Array) {
filterData = series.filter(seri => {
return !!seri.data.length;
});
}
return !filterData.length;
};
/**
* [bindEvents 注册on-xxx echarts事件]
* @param {[type]} events [description]
* @return {[type]} [description]
*/
const bindEvents = function (events) {
let givenEvents = events && events.name ? [events] : this.data.get('givenEvents');
let chart = this.data.get('echartsInstance');
!!givenEvents.length && givenEvents.forEach(event => {
// 检测是否为echarts内置事件
let name = checkEchartsEvents.call(this, event.name);
let eventHandeler = args => {
return this.fire(name, {
event: name,
chart: chart,
params: args
});
};
!!name && chart && (chart.off(name, eventHandeler), chart.on(name, eventHandeler, this));
});
};
/**
* [checkEchartsEvents 检测是否为echarts内置事件]
* @param {[type]} event [description]
* @return {[type]} [description]
*/
const checkEchartsEvents = function(event) {
let pass = null;
!!~echartsEvents.indexOf(event) && (pass = event);
return pass;
};
const resizeHandler = function() {
return this.resize();
};
/**
* [autoResize 监听窗口resize事件]
* @return {[type]} [description]
*/
const autoResize = function() {
context.removeEventListener('resize', resizeHandler.bind(this));
context.addEventListener('resize', resizeHandler.bind(this));
};
const dispatchPlugs = function(next) {
let plugs = Object.keys(plugsCache || {});
let promises = [];
if (plugs.length) {
plugs.map(name => {
let plug = plugsCache[name];
let fn = plug.fn.call(this, plug.args);
promises.push(fn);
});
}
defered.when(promises).then(result => {
typeof next === 'function' && next.call(this, result);
}).catch(err => {
console.log(err, next);
});
};
/**
* [watchCharts 监听组件数据]
* @return {[type]} [description]
*/
const watchCharts = function() {
this.watch('data', (option, update) => {
this.nextTick(() => {
return this.initEcharts();
});
});
this.watch('config.theme', (theme, update) => {
if (!theme || (!!update && theme !== update.value)) {
return;
}
if (!!this.data.get('echartsInstance') && !!theme) {
this.destroy();
}
this.initEcharts();
});
this.watch('config.size', (size, update) => {
(!!this.data.get('echartsInstance')) && this.nextTick(this.resize.bind(this));
});
this.watch('fullScreen', (full, update) => {
setTimeout(() => {
getRect.call(this, true);
(!!this.data.get('echartsInstance')) && this.nextTick(this.resize.bind(this));
}, 200);
});
this.watch('config.group', this.setGroup);
};
/**
* [initEcharts 初始化echarts]
* @param {[type]} opts [description]
* @param {Boolean} notMerge [description]
* @return {[type]} [description]
*/
const initEcharts = function(opts, isMerge = true) {
if (
!this.data.get('echarts')
|| !this.el
|| !this.data.get('data')
) {
return;
}
let config = this.data.get('config');
if (config) {
let option = opts || this.data.get('data') || {};
let theme = this.getTheme();
let chart = this.data.get('echartsInstance') || this.data.get('echarts').init(this.el, theme);
if (!option.color) {
option.color = this.data.get('chartsColors');
}
let isEmpty = dataIsEmpty(this.data.get('data.series'));
(!!isEmpty) ? this.nextTick(() => {
return this.fire('data-empty', {
element: this.el,
chart: chart
});
}) : chart.setOption(option, !!isMerge);
// this.resize();
// 监听window.resize事件
autoResize.call(this);
!this.data.get('echartsInstance') && this.data.set('echartsInstance', chart);
// 注册echarts事件
bindEvents.call(this);
this.nextTick(() => {
return this.fire('complete', {
element: this.el,
chart: chart
});
});
}
this.hideLoading();
};
export default {
template: `
<div class="{{!!config.dataLoaded ? 'echarts-dataLoaded' : ''}}" style="position: relative;min-height: 300px;height:{{config.size.height ? (config.size.height + 'px') : 'auto'}};">
<div class="san-lazyload" s-if="{{!config.dataLoaded}}"/>
</div>
`,
initData() {
return {
echartsInstance: null,
chartsColors: ['#87cefa', '#da70d6', '#32cd32', '#6495ed', '#ff69b4', '#ba55d3', '#cd5c5c', '#ffa500',
'#40e0d0', '#1e90ff', '#ff6347', '#7b68ee', '#00fa9a', '#ffd700', '#6699FF', '#ff6666', '#3cb371',
'#b8860b', '#30e0e0', '#1AC060', '#009EF5', '#BACF00', '#008A77', '#32CBF6', '#FEE14B', '#ff7f50'],
chinaMapUrl: 'http://gallery.echartsjs.com/dep/echarts/map/js/china.js'
}
},
attached() {
let givenEvents = this.givenANode.events;
this.data.set('givenEvents', givenEvents);
dispatchPlugs.call(this);
watchCharts.call(this);
this.extendIntanceFunctions();
},
registerPlugs(name, fn, args) {
if (!!plugsCache[name]) {
return console.error('plug: '+ name +' exists!');
}
plugsCache[name] = {
name: name,
fn: fn,
args: args
};
console.info('plug: '+ name +' install success!');
},
extendIntanceFunctions() {
// 附加echartsInstance Function(除group之外)
echartsInstanceFunctions.map(instance => {
if (typeof this[instance] !== 'function') {
this[instance] = (...args) => {
let INSTANCE = this.data.get('echartsInstance');
if (!!INSTANCE && typeof INSTANCE[instance] === 'function') {
return INSTANCE[instance](...args);
}
};
}
});
},
initEcharts(options) {
if (!this.data.get('echarts') && !!echarts) {
this.data.set('echarts', echarts);
}
if (!!options) {
return this.data.set('data', options);
}
return dispatchPlugs.call(this, () => {
this.data.set('config.dataLoaded', true);
this.hideLoading();
initEcharts.call(this);
}), this;
},
showLoading() {
this.data.get('echartsInstance') && this.data.get('echartsInstance').showLoading();
return this;
},
hideLoading() {
this.data.get('echartsInstance') && this.data.get('echartsInstance').hideLoading();
return this;
},
getTheme() {
return this.data.get('config.theme') || 'default';
},
resize(size) {
let chart = this.data.get('echartsInstance');
chart && (!!size ? chart.resize(size) : chart.resize());
return this;
},
clear() {
(!!this.data.get('echartsInstance.clear')) && this.data.get('echartsInstance').clear();
return this;
},
destroy() {
context.removeEventListener('resize', resizeHandler.bind(this));
(!!this.data.get('echartsInstance.dispose')) && this.data.get('echartsInstance').dispose();
this.data.set('echartsInstance', null);
return this;
},
setGroup(group) {
return this.connect(group), this;
},
connect(group) {
if (!!(group instanceof Array)) {
group = group.map(chart => chart.chart);
}
echarts && echarts.connect(group);
return this;
},
disconnect(group) {
echarts && echarts.disConnect(group);
return this;
},
registerMap(...args) {
echarts && echarts.registerMap(...args);
return this;
},
registerTheme(...args) {
echarts && echarts.registerTheme(...args);
return this;
},
graphic: echarts.graphic,
getInstance() {
return this.data ? this.data.get('echartsInstance') : null;
}
};